Linux C语言编写2048小游戏

article/2025/10/27 6:59:37

2048

在这里插入图片描述

2048小游戏是用Linux C语言写的,运行在Ubuntu系统上,其中Ubuntu链接Ncuses库。首先,我们简单了解一下Ncurses。 Ncurses库是由原CURSES库发展而来的,这个库提供了C/C++对屏幕以及光标、鼠标访问的特性。使得C/C++简易写屏成为可能。

1.1常用函数的介绍

如果要调用NCURSES库中的函数,你必须在代码中加载ncurses.h文件,就是在C或C++程序中添加#include <nursses.h>这一行。
例如: Hello World程序
#include<nurses.h>
int main()
{
initscr(); //初始化,进入curses模式 ,用来清除屏幕("stdscr"窗口)上所有的字符,使屏幕变为空白,等待下一步处理
printw(“Hello World”); //在虚拟屏幕上打印Hello World 输出到”stdscr"的虚拟坐标(0,0)上
refresh(); //将虚拟屏幕上的内容写到显示器上,并刷新 (将缓冲区的内容输出到 屏幕上)printw+refresh()可以不断在虚拟屏幕上写入数据,而调用refresh()函数时让一切看起来似乎时一次完成的。因为refresh()函数至核查窗口和数据中变动的部分。
getch(); //等待用户输入
endwin(); //退出NCURSES模式 释放了curses子系统和相关数据结构的内存,才回到普通字符行模式,否则,结束后终端可能运转得不正常 如果你的程序不能正常地显示东西了,看看initscr()函数和endwin()函数是不是在不该被调用的地方调用了
}

1.2 游戏代码

1.2.1 input.h

#ifdef   __INPUT_H
#define  __INPUT_H#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4#define FIRST 10
#define NEXT  11
#define THEN 12
#define LAST 13#define QUIT 100
#define UNKNOW 250int get_user_input(void);#endif

1.2.2 input.c

#include <curses.h>
#include "input.h"extern WINDOW *w_2048;  //声明一个外部变量,表示这个变量是其他文件(2048.c)中定义的   
int get_user_input(void)
{keypad(w_2048,TRUE);int ch=wgetch(w_2048);keypad(w_2048,FALSE);if(ch=='q'||ch=='Q'){return QUIT;}else if(ch=='a'||ch==KEY_LEFT){return LEFT;}else if(ch=='d'||ch==KEY_RIGHT){return RIGHT;}else if(ch=='s'||ch==KEY_DOWN){return DOWN;}else if(ch=='w'||ch==KEY_UP){return UP;}else if(ch=='1'){return FIRST;}else if(ch=='2'){return NEXT;}else if(ch=='3'){return THEN;}else if(ch=='4'){return LAST;}else{return UNKNOW;}}

相关函数解释:
1.keypad()函数
这个函数允许使用功能键:F1,F2,方向键等。使用keypad(stdscr,TURE)就是显示设备 (stdscr)上使用这些功能。keypad(stdscr,FALSE);就是显示设备(stdscr)关闭这些功能。
2.wgetch()函数
wgetch(*WINDOWS)
这个函数从指定的窗口接收字符

1.2.3 screen.h代码

#define __SCREEN_H
#define __SCREEN_H//打开字符屏幕
void open_screen(void);//关闭字符屏幕
void close_screen(void);

1.2.4 screen.c代码

#include <curses.h>
//打开字符屏幕
void open_screen(void)
{initscr();cbreak();noecho();keypad(stdscr,TRUE);}//关闭字符屏幕
void close_screen(void)
{endwin();
}

相关代码解释:
1. initscr()函数
初始化,进入curses模式 ,用来清除屏幕("stdscr"窗口)上所有的字符,使屏幕变为空白,等待下一步处理
2. cbreak()函数
通常情况下,用户输入的字符将被终端程序送入终端的缓冲区。但当用户有输入换行符时,终端程序将会终端,同时输出当前的缓冲区内容并启用新行的输出缓冲。后面的2048.c代码中, game_is_over()函数 直接改成printf(“game over”) ;程序结束后,会在终端输出game over。但是改成printf(“game over\n”),会显示在屏幕上。但是大多数需要用户输入单个字符并能显示在屏幕上。
cbreak()用来禁用行缓冲,这个函数所初始化的模式可以用来给程序传送控制字符,比如:挂起,中断或退出。这些控制字符被认为是终端驱动程序中的控制字符,因而将这些这符传给终端程序。
3.noecho()函数
这个函数控制用户输入的键盘回显。 noecho()函数可以不让控制字符出现在屏幕上。

1.2.5 main.c代码

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "screen.h"
#include "time.h"int main()
{	//设置随机数zhongzsrandom(time(NULL));	//创建(初始化)我们的字符窗口屏幕open_screen();//进入2048的主循环game_2048();	//关闭字符屏幕close_screnen();return 0;
}

1.2.6 2048.h代码

#ifndef __2048_H__
#define __2048_H__void game_2048(void);#endif

1.2.7 2048.c 代码

#include <curses.h>
#include <stdlib.h>
#include <string.h>
#include "input.h"
#include <unistd.h>//提示窗口相关参数
WINDOW *wel=NULL;
int wel_lines=2;      //提示窗口的行数
int wel_columns=40;   //提示窗口的列数
int wel_y0=0;         //提示窗口左上顶点的y坐标
int wel_x0=20;        //提示窗口右上顶点的x坐标//游戏数字窗口
WINDOW *w_2048=NULL;
int w_2048_lines=4;
int w_2048_coluwns=24;
int w_2048_y0=3;
int w_2048_x0=20;//得分窗口
WINDOW *w_score=NULL;
int w_score_lines=2;
int w_score_coluwns=24;
int w_score_y0=10;
int w_score_x0=20;//结束窗口
WINDOW *w_over=NULL;
int w_over_lines=4;
int w_over_coluwns=24;
int w_over_y0=14;
int w_over_x0=20;#define ITEM_NUM 4int matrix_2048[ITEM_NUM][ITEM_NUM]=
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};//删除行
void Del(int num)
{int i; for(i=0;i<ITEM_NUM;i++){if(matrix_2048[num][i]!=0)matrix_2048[num][i]=0;}
}//获取0的个数
int get_zero_num()
{int i,j;int n=0;//计数for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){if(matrix_2048[i][j]==0)n++;}}return n;
}//在空白位置上随机填充一个数字
void fill_a_number(void)
{int zero_num=get_zero_num();if(zero_num==0){return;}int pos=random()%zero_num+1;  //范围是【1~zero_num】int n=0;//第几个0int i,j; for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NJM;j++){if(matrix_2048[i][j]==0){n++;if(n==pos){//要填充的位置找到了int a[4]={2,2,4,8};int index=random()%4;matrix_2048[i][j]=a[index];return ;}}}}
}//初始化游戏界面需要用到的窗口
void init_windows()
{start_color();init_pair(1,COLOR_RED,COLOR_BLACK);    //1.创建一个提示(欢迎)字符wel=newwin(wel_lines,wel_columns,wel_y0,wel_x0);wmove(wel,0,0);wattron(wel,COLOR_PAIR(1));waddstr(wel,"welcome to game2048");wmove(wel,1,3);waddstr(wel,"Author:liyingzhi");        wrefresh(wel);//2.创建一个游戏数字字符窗口    w_2048=newwin(w_2048_lines,w_2048_coluwns,w_2048_y0,w_2048_x0);//3.显示最高得分w_score=newwin(w_score_lines,w_score_coluwns,w_score_y0,w_score_x0);//4.结束窗口w_over=newwin(w_over_lines,w_over_coluwns,w_over_y0,w_over_x0);
}
void del_windows()
{delwin(wel);     //删除欢迎框delwin(w_2048);  //删除字符框delwin(w_score); //删除得分框
}//在非0位置随机删除一个数字
void delete_number(int del)
{int zero_num=get_zero_num();int i,j;if(zero_num==0){return;}for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){if (del==j){matrix_2048[i][j]=0;}   }}
}//根据矩阵matrix_2048[][]的内容,在游戏中显示
void show_matrix(void)
{int i,j;int max=matrix_2048[0][0];//最高得分for(i=0;i<ITEM_NUM;i++){for(j=0;j<ITEM_NUM;j++){//移动光标wmovewmove(w_2048, i, j*6);//添加要显示的字符串  int转换成charchar buf[6];if(matrix_2048[i][j]==0){sprintf(buf,"%5d",'_');}else{sprintf(buf,"%5d",matrix_2048[i][j]);}waddstr(w_2048,buf);if(matrix_2048[i][j]>max){max=matrix_2048[i][j];}}
}  //刷新窗口wrefresh(w_2048);//显示得分wmove(w_score,0,6);char buf1[24];sprintf(buf1,"score:%5d",max);waddstr(w_score,buf1);//刷新窗口 wrefreshwrefresh(w_score);}void  move_rightr(void)
{ int  i;for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=ITEM_NUM-1;//指向这一行最后面(要被覆盖)的位置int k=0;//哨兵,从右往左,找下一个非0元素a[i][k],和x进行比较for(k=ITEM_NUM-1;k>=0;k--){if(matrix_2048[i][k]!=0){if(x==0){x=matrix_2048[i][k];matrix_2048[i][k]=0;}else{//找到两个非0值,进行比较if(matrix_2048[i][k]==x){//需要合并,后移x=x+matrix_2048[i][k];  //合并的值matrix_2048[i][k]=0;   //前移后的数字为0matrix_2048[i][m--]=x;  //合并的值后移x=0;}else{matrix_2048[i][m--]=x;x=matrix_2048[i][k];matrix_2048[i][k]=0;}}}}matrix_2048[i][m--]=x;
}void move_up(void)
{    int i;  for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=0;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从上往下,找下一个非0元素 a[i][k],和x进行比较  for(k=0;k<ITEM_NUM;k++){if(matrix_2048[k][i]!=0){if(x==0){x=matrix_2048[k][i];matrix_2048[k][i]=0;      }else{//找到两个非0值,进行比较if(matrix_2048[k][i]==x){  //需要合并,前移x=x+matrix_2048[k][i];  //合并的值matrix_2048[k][i]=0;  //前移后的数字为0matrix_2048[m++][i]=x;  //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[m++][i]=x;x=matrix_2048[k][i];matrix_2048[k][i]=0;   }       }}}matrix_2048[m++][i]=x;}void move_dowm(void)
{  int i;  for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=ITEM_NUM-1;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从下往上,找下一个非0元素 a[i][k],和x进行比较  for(k=ITEM_NUM-1;k>=0;k--){if(matrix_2048[k][i]!=0){if(x==0){x=matrix_2048[k][i];matrix_2048[k][i]=0;      }else{//找到两个非0值,进行比较if(matrix_2048[k][i]==x){  //需要合并,前移x=x+matrix_2048[k][i];  //合并的值matrix_2048[k][i]=0;  //前移后的数字为0matrix_2048[m--][i]=x;  //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[m--][i]=x;x=matrix_2048[k][i];matrix_2048[k][i]=0;}}}}matrix_2048[m--][i]=x;}
}void move_left(void)
{int i;    for(i=0;i<ITEM_NUM;i++){int x=0;//辅助存储非0值进行比较int m=0;//指向这一行最前面(要被覆盖)的位置int k=0;//哨兵,从左至右,找下一个非0元素 a[i][k],和x进行比较for(k=0;k<ITEM_NUM;k++){if(matrix_2048[i][k]!=0){if(x==0){x=matrix_2048[i][k];matrix_2048[i][k]=0;}else{//找到两个非0值,进行比较if(matrix_2048[i][k]==x){  //需要合并,前移x=x+matrix_2048[i][k];   //合并的值matrix_2048[i][k]=0;     //前移后的数字为0matrix_2048[i][m++]=x;   //合并的值前移x=0;//x已经合并前移了,x要重新清0}else{matrix_2048[i][m++]=x;x=matrix_2048[i][k];matrix_2048[i][k]=0;}}}}matrix_2048[i][m++]=x;}}
//完整代码在网址中

函数分析
1、删除函数Del: 参数num是个整型数字,num等于1时,删除第一行;num等于2时,删除第二行。
每一行会有ITEM_NUM个数字,所以用一个for循环,把一行的数字删了
2、get_zero_num()函数:遍历整个二维数组,返回0的个数
3、fill_a_number()函数:首先用get_zero_num()判断是否有空位,random()%zero_num的范围是0~zero_num-1 pos=random()%zero_num+1的范围是1到zero_num pos就可以随机取其中空白的一个位置 int a[4]数组存放要填充的数字
4、init_windows():初始化窗口
newwin()函数的作用是分配内存给窗口相关的数据结构,返回一个指向窗口的结构指针,失败返回NULL。
delwin()函数可以删除一个窗口,并且释放存储窗口数据结构的内存和信息。
第一个参数:窗口的行数 第二个参数:窗口的列数 第三个参数:窗口左上顶点的行坐标
第四个参数:窗口左上顶点的列坐标 成功返回OK,失败返回ERR
mvwin()函数:第一个参数:要移动的窗口的指针 第二个参数:要移动位置左上顶点的行坐标 第三个参数:要移动位置左上顶点的列坐标 成功返回OK,失败返回ERR
5.show_matrix()
max存放最高分数,sprintf()函数把格式化数据写入字符串 第一个参数为要写入的字符串,第二个为格式化字符串,第三 个为变量。sprintf()最常见的应 用之一莫过于把整数打印到字符串中,如:sprintf(s, “%d”, 123); //把整数123打印成一个字符串保存在s中 sprintf(s, “%8x”, 4567); //小写16进制,宽度占8个位置,右对齐 sprintf()会根据参数format 字符串来转换并格式化数据,然后将结果。复制到参数str 所指的字符串数组,直到出现字符串结束(’\0’)为止。
waddstr(w_2048,buf);在w_2048这个窗口输出字符buf
6.move_left()
二维数组行遍历,按下左移键或W,整行往左移,填补空位置(0)。如果相邻位置值相同,要合并并且前移(使用后置++)
x用来存储比较的第一个非0值 m指向这一行最前面(要被覆盖)的位置 k为哨兵,从左至右找下一个非0值
if(x==0) x保存第一个非0值,如果一行只有一个非0值或者是第奇数个0,就执行 matrix_2048[i][m++]。但是m++是后置++, 是赋值后++。如果不止一个0,那么两个值比较,如果相等,x保存合并值,前移后的matrix_2048[i][k]变为0。合并的值前移。如果不相同,首先移动第一个x,利用循环外的matrix_2048[i][m++]移动第二个x
7.move_right()
二维数组行遍历。与move_left不同的是,从右往左遍历,整体往右移,所以第一个遍历的非0数,放到最右边(下标最大值)所以m- -
8.move_up()
二维数组列遍历。所以i和k要交换位置,从上往下遍历,第一个遍历的非0数,放在最上面(下标最小),所以m++
9.move_dowm()
二位数组列遍历。与move_dowm()不同的是,从下往上遍历,第一个遍历的非0数,放在最下面(下标最大),所以m- -
10.change_matrix
判断按下方向键,是否二维数组是否有改变,把matrix_2048备份到matrix_2048_bak,如果有改变,返回1,没有改变,返回0

完整代码地址
链接:https://pan.baidu.com/s/1BvlnS57pMeShkYlHf-YvzA
提取码:s4lb


http://chatgpt.dhexx.cn/article/uqSLiGKV.shtml

相关文章

C语言编写小游戏:MinesWeeper(扫雷)闯关版

《扫雷》&#xff1a;大众类的益智小游戏&#xff0c;游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子&#xff0c;同时避免踩雷&#xff0c;踩到一个雷即全盘皆输。 话不多说&#xff0c;我们直接进入正题。 首先&#xff0c;我们得给用户显示一个菜单栏&…

(C语言)用C语言编写小游戏——三子棋

目录 三子棋效果展示 三子棋的功能实现 1、初始化棋盘格 2、打印棋盘 3、玩家下棋 4、电脑下棋 5、判断输赢&#xff08;玩家赢/电脑赢/平局&#xff09; 完整代码展示 三子棋小游戏的代码实现分为三个文件&#xff0c;test.c&#xff08;测试游戏功能&#xff09;、ga…

c语言编写的小游戏(c语言编写小游戏入门)

C语言编写是要注意什么&#xff1f; 因此&#xff0c;在编写选择语句之前&#xff0c;应该首先明确判断条件是什么&#xff0c;并确定当判断结果为“真”或“假”时应分别执行什么样的操作(算法) c语言编写小游戏请提供俄罗斯方块&#xff0c;坦克大战之类的小游戏的程序的c 应…

(C语言)用C语言编写小游戏——扫雷

目录 扫雷效果展示 扫雷的功能实现 1、初始化棋盘格 2、 打印棋盘 3、布置雷 4、排查雷 完整代码展示 扫雷小游戏的代码实现分为三个文件&#xff0c;test.c&#xff08;测试游戏功能&#xff09;、game.h&#xff08;头文件的包含和函数的声明&#xff09;、game.c&…

详解5个C语言简单易懂小游戏

文章目录 前言一、准备工作二、游戏菜单三、游戏内容1.猜数字2.三子棋3.扫雷4.五子棋5.飞行棋 总结 前言 我们通过5个简单易懂的小游戏来加强我们对C语言的认识&#xff0c;这五个小游戏不仅有单人&#xff0c;还有人机对战和人人对战。让我们在学习之余来上一局紧张刺激的小游…

C语言趣味小游戏——扫雷(详解版)

前言 ​ 全篇无任何废话&#xff0c;本文的解释大多数都在代码段中&#xff0c;所以一定要看代码&#xff0c;边看边学边理解。 这只是初学者入门的一个小游戏&#xff0c;不难懂&#xff0c;没有什么复杂的内容 可以先学习一下比扫雷还简单的猜数字和三子棋 C语言趣味小游戏—…

C语言小程序游戏

c语言小程序游戏 ​ 本代码是我大一刚学完c语言自己编写的&#xff0c;三个游戏分别是飞机竞速、走迷宫和魔塔&#xff0c;满满的都是回忆。 1、不可能的任务-飞机竞速 ​ 这种游戏在以前小时候玩的游戏机里面玩过&#xff0c;那时抱着个游戏机一玩就是一下午&#xff0c;如…

C语言简易小游戏

文章目录 前言一、猜数字游戏二、旋转光标三、多个字符从两端移动&#xff0c;向中间汇聚四、恶搞&#xff1a;关机小程序五、闪烁的五彩爱心六、扫雷七、三子棋 前言 本篇博客将带领大家自己动手写一下一些C语言小游戏&#xff1b;以增加对于C语言的兴趣&#x1f600;&#x…

c语言成绩管理系统(链表)

C语言实现了学生成绩管理系统&#xff0c;可以进行学生成绩的增加&#xff0c;删除&#xff0c;修改&#xff0c;查询&#xff0c;计算平均成绩和展示。 开发语言&#xff1a;C语言 开发工具&#xff1a;Dev c 开发者&#xff1a;呵呵up 创建学生成绩信息 2. 插入学生信息 3.…

C语言实现学生成绩管理系统设计

本系统有增加学生记录、修改学生记录、删除学生记录、按姓名查询学生记录、按C语言成绩对学生进行排序、退出系统6大功能。 能够对学生的姓名&#xff0c;学号&#xff0c;c语言成绩做相应的操作。 在检测到输入成绩大于55时&#xff0c;会自动加上5。 该管理系统设计功能模块…

c语言成绩管理系统常见错误,求教 学生成绩管理系统出错

已结贴√ 问题点数:20 回复次数:5 求教 学生成绩管理系统出错 小弟刚做了个学生成绩管理系统 编译无错误 但是运行的时候连选择函数都不能 特来求教 望高手解释 代码如下: #include #include #define N 20 #define M 100 struct score {int scr1; int scr2; int scr…

c语言课程设计 学生成绩管理系统

学生成绩管理系统要求&#xff1a; 1、系统功能以菜单方式工作&#xff1b; 2、数据的输入&#xff1b; 3、数据的插入&#xff1b; 4、数据的输出&#xff1b; 5、数据的删除&#xff1b; 6、数据的查找&#xff0c;通常以两种方式进行查找&#xff0c;如姓名、学号&#xff1…

C语言学生成绩管理系统详解

文章目录 一、系统概述二、数据类型三、自定义函数说明四、运行界面五、源代码 源代码请直接跳到最后 引言&#xff1a;最近写了C语言的大作业&#xff0c;感觉做得还行&#xff0c;记录一下&#xff0c;给后人一些参考&#xff0c;给自己留更深印象方便后续改进&#xff01; …

学生成绩管理系统 C语言

基础篇问题&#xff1a; 1.输出如下菜单&#xff1a; *********************学生成绩管理系统******************* * 1 成绩录入 2 成绩查询 3 计算平均分 * * 4 计算最高分 5 排名 6 退出 * ******************************…

C语言编程学生成绩管理系统

目录 一、介绍 二、功能 1.录入学生 2.删除学生信息 3.修改学生信息 4.查询学生信息 5.所有学生信息 6.成绩排序 7.退出程序 三、代码 1.主函数 2.头文件 3.函数封装库 一、介绍 利用C语言&#xff0c;运用链表、指针、封装函数等基本知识实现一个学生管理系统。通…

C语言学生成绩管理系统

制作学生成绩管理系统&#xff0c;可以实现以下功能&#xff1a; 每条记录包括&#xff1a;学号、姓名、专业和5门课程的成绩&#xff1b;能够实现添加、删除、修改功能&#xff1b;能够计算某学生的总分和平均分&#xff1b;能按照总分排序输出&#xff1b; 利用C语言的基本…

c语言成绩管理系统

关注微信公众号每日新觉&#xff0c;私聊作者获取提取密码点击下面链接&#xff0c;私聊作者获取提取密码。https://mp.weixin.qq.com/s/QgRQ3YB2JqCvNOGQHQ57rA 作者每日新觉&#xff0c;是一名热爱技术和编程的年轻程序员。他在计算机科学和软件工程领域有着广泛的研究和实践…

c语言成绩管理系统1.0,c语言成绩管理系统完整附源码v1.0 免费版

c语言成绩管理系统拥有和hello word一样的江湖地位&#xff0c;初学C语言的朋友基本都会从管理系统开始入手学习&#xff0c;对于很多大学生来说更是如此&#xff0c;今天为大家带来的这款系统以及源码希望能对大家学习学C语言有所帮助&#xff0c;欢迎下载使用。 C语言介绍 C语…

C语言学生成绩管理系统(综合项目)

1. 这个代码主要实现以下功能&#xff1a; 2. 用到的主要参数有&#xff1a; 1.整型变量int n;用于储存学生人数和之后的循环判断。 2.字符串char name[][];用于储存姓名。 3.浮点型变量float score[];用于储存成绩。 4.长整型变量long ID[Max];用于储存学号。 3.…

【高级语言程序设计】c语言-学生成绩管理系统

c语言期末作业 声明&#xff1a;未经允许&#xff0c;请勿转载 学生成绩管理系统 本系统能够对学生成绩管理功能&#xff0c;包括&#xff1a; 1.对多个学生成绩进行管理&#xff0c;至少10个学生。 2.每个学生至少3门课程。 3.对每个学生大学期间的成绩进行记录。 4.修改学生…