2048 游戏代码:C 语言实现,使用 curses 库
2048 游戏代码:C 语言实现,使用 curses 库
该代码使用 C 语言和 curses 库实现经典的 2048 游戏。代码简洁易懂,并附带详细解释。
// gcc 2048.c -o 2048 -lpthread -lcurses
#include <stdio.h>
#include <curses.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int array[4][4] = {
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
};
int tmp[4];//这个作为临时数据处理的一维数组
int kong = 16;//初始状态空位是16个。
int MAX=0;//最大值
WINDOW *win[16];//用来存放16个小窗口
void create_window()//创建16个小窗口
{
int i,j;
int data=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
win[4*i+j] = subwin(stdscr,3,6,2+3*i,1+6*j);//创建小窗口,并定好位置
box(win[4*i+j],0,0);//给每一个小窗口设置好边框
wrefresh(win[4*i+j]);//只刷新小窗口
}
}
void show_2048()//显示2048的矩阵
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
//销毁小窗口
delwin(win[4*i+j]);
//创建新的小窗口
win[4*i+j] = subwin(stdscr,3,6,2+3*i,1+6*j);//创建小窗口,并定好位置
//根据数值开启颜色索引
switch(array[i][j])
{
case 0: wattron(win[4*i+j],COLOR_PAIR(1)); break;
case 2: wattron(win[4*i+j],COLOR_PAIR(2)); break;
}
box(win[4*i+j],0,0);//给每一个小窗口设置好边框
//向第i行第j列的小窗口,放入数组中第i行第j列的数值
mvwprintw(win[4*i+j],1,1,"%4d",array[i][j]);
wrefresh(win[4*i+j]);//只刷新小窗口
//关闭颜色索引
switch(array[i][j])
{
case 0: wattroff(win[4*i+j],COLOR_PAIR(1)); break;
case 2: wattroff(win[4*i+j],COLOR_PAIR(2)); break;
}
}
}
void get_rand()//获取随机数
{
while(1)//判断条件非0,会永远循环,除非break
{
//数值只能在0~3之间获取
int i,j;
i = rand()%4;
j = rand()%4;
//当随机产生的位置上是数值0,则赋值为2
if(array[i][j] == 0)
{
array[i][j] = 2;
break;//跳出循环
}
}
kong--;//每次产生一个随机数,空位-1
}
void do_date()//处理数据---数值累加并且把数值都向左边顶格
{
int i,j;
//printf("%d,%d,%d,%d----",tmp[0],tmp[1],tmp[2],tmp[3]);
//第一步,从左边第一个数值开始,往右边判断是否有相邻数值
//如果有,累加
//如果是0,跳过
//如果不等,结束本次循环
for(i=0;i<4;i++)
{
if(tmp[i] == 0)//如果数值本身为0,不需要进行累加或其他判断,直接下一次循环
continue;
for(j=i+1;j<4;j++)
{
if(tmp[j] == 0)//相邻数值为0
continue;//表示结束本次循环,j++会继续执行
if( tmp[j] != 0 && tmp[i] == tmp[j])//如果两者相等,求和,并且后一个赋值0
{
tmp[i] = tmp[i] + tmp[j];
tmp[j] = 0;
kong++;//当两个相同的数值相加的时候,空位+1
if(tmp[i] > MAX)
MAX = tmp[i];//这里面始终保存最大值
break;//表示结束本次循环,j++不执行,直接退出一层for循环
}
if(tmp[j] != 0 && tmp[i] != tmp[j])//不等且不为0
break;//表示结束本次循环,j++不执行,直接退出一层for循环
}
}
//printf("%d,%d,%d,%d----",tmp[0],tmp[1],tmp[2],tmp[3]);
//去掉数值之间的空格,并且顶格。
for(i=0;i<4;i++)
{
if(tmp[i] == 0)
{
for(j=i+1;j<4;j++)
{
if(tmp[j] !=0 )
{
tmp[i] = tmp[j];
tmp[j] = 0;
break;//表示结束本次循环,j++不执行,直接退出一层for循环
}
}
}
}
//printf("%d,%d,%d,%d\n",tmp[0],tmp[1],tmp[2],tmp[3]);
}
void do_left()//向左
{
//应该把数值都放入到tmp里面,然后每行都运行一次数据处理
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
tmp[j] = array[i][j];//把第i行数据放入到tmp
do_date();//数据放完了再处理
for(j=0;j<4;j++)
array[i][j] = tmp[j];//再把数据放回到第i行
}
}
void do_right()//向右
{
int i,j;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
tmp[3-j] = array[i][j];//把第i行数据放入到tmp
do_date();
for(j=0;j<4;j++)
array[i][j] = tmp[3-j];//把数据倒着放回到array中
}
}
void do_up()//向上
{
//应该把数值都放入到tmp里面,然后每行都运行一次数据处理
int i,j;
for(j=0;j<4;j++)
{
for(i=0;i<4;i++)
tmp[i] = array[i][j];//把第j列数据放入到tmp
do_date();
for(i=0;i<4;i++)
array[i][j] = tmp[i];//再把数据放回到第j列
}
}
void do_down()//向下
{
//应该把数值都放入到tmp里面,然后每行都运行一次数据处理
int i,j;
for(j=0;j<4;j++)
{
for(i=0;i<4;i++)
tmp[3-i] = array[i][j];//把第j列数据放入到tmp
do_date();
for(i=0;i<4;i++)
array[i][j] = tmp[3-i];//再把数据放回到第j列
}
}
int main()
{
initscr();//初始化屏幕和ty终端
create_window();//创建16个小窗口
keypad(stdscr,TRUE);//在stdscr中开启特殊键盘类
start_color();//开启颜色
//定义颜色索引
init_pair(1 ,COLOR_WHITE ,COLOR_CYAN );//索引1
init_pair(2 ,COLOR_RED ,COLOR_GREEN );//索引2
srand(time(NULL));//获取随机数种子
get_rand();
get_rand();
show_2048();
int num;
while(1)
{
num = getch();//直接从键盘获取
refresh();
if(num==KEY_LEFT)//向左 KEY_LEFT
do_left();
if(num==KEY_RIGHT)//向右 KEY_RIGHT
do_right();
if(num==KEY_UP)//向上 KEY_UP
do_up();
if(num==KEY_DOWN)//向下 KEY_DOWN
do_down();
get_rand();//每次键盘结束以后,在空余的位置产生数值2
show_2048();//显示屏幕
if(MAX == 2048)
{
printf("游戏成功\n");
return 0;
}
//判断是否还有空位
if(kong == 0)
{
//检查两两相邻的数值有没有重复的
//先检查横向是否有相邻,如果有,就判断只能左右按键
//再检查纵向是否有相邻,如果有,就判断只能上下按键
//总结按键方向的结果,判断是否可以继续运行。
//如果都不可以,就结束游戏
printf("结束游戏\n");
sleep(3);
break;
}
}
endwin();//销毁屏幕和ty终端
return 0;
}
代码说明
-
创建游戏矩阵
array[4][4]数组用来存储游戏矩阵。 -
创建游戏窗口
create_window()函数使用 curses 库创建 16 个小窗口,用于显示游戏矩阵的每个格子的数字。 -
显示游戏矩阵
show_2048()函数负责在每个小窗口中显示对应array中的数字,并根据数字大小设置不同的颜色。 -
随机生成数字
get_rand()函数随机选择一个空格子,并在该格子中生成数字 2。 -
处理玩家操作
do_left(),do_right(),do_up(),do_down()函数分别处理玩家向左、向右、向上、向下移动的操作。- 使用
tmp数组临时存储一行或一列数据。 - 调用
do_date()函数处理数据,使相同数字合并,并把数值都向左边顶格。 - 将处理后的数据写入
array数组。
- 使用
-
游戏逻辑
main()函数实现游戏主循环:- 初始化游戏环境,包括创建窗口、开启颜色、生成随机数字。
- 循环读取玩家操作,调用对应函数处理数据,并更新游戏界面。
- 判断游戏是否结束:
- 当
MAX等于 2048 时,游戏成功。 - 当
kong等于 0,即没有空格子时,游戏结束。
- 当
代码中关键部分的解释
-
do_date()函数中for(i=0;i<4;i++)部分:这部分代码将
tmp数组中的数字紧凑排列在一起,去掉数值之间的空格,并将数值都顶格。- 当
tmp[i]为 0 时,它将tmp[i]后面的非零数字往前移动,直到遇到非零数字或者到达数组末尾。 - 缺少这部分代码会导致游戏界面中数字排列不整齐,影响游戏体验。
- 当
游戏玩法
- 游戏目标:将数字方块合并成 2048。
- 操作方法:使用方向键控制数字方块移动。
- 规则:
- 当两个相同的数字方块相撞时,它们会合并成一个新的数字方块,其值为两个相撞数字的和。
- 每次移动后,游戏会在空格中随机生成一个新的数字方块。
- 当游戏界面没有空格子且没有可以合并的数字时,游戏结束。
扩展功能
可以根据需要对代码进行扩展,例如:
- 增加游戏难度,例如增加新数字 4 或 8,或改变生成数字的频率。
- 实现游戏排行榜功能。
- 使用更精美的界面设计。
总结
该代码是一个简单的 2048 游戏的 C 语言实现,使用 curses 库进行界面开发。代码简洁易懂,便于学习和修改。开发者可以根据自己的需求进行扩展,开发出更加丰富多彩的游戏。
希望这篇文章能够帮助您理解 2048 游戏的实现原理,并激发您开发游戏的想法!
原文地址: https://www.cveoy.top/t/topic/phlN 著作权归作者所有。请勿转载和采集!