linux下运行2048小游戏

前几日在windows下写了一个简单的2048小游戏,然后再linux下运行,了解到了一些函数的使用

文章目录

  • 函数
    • 显示
    • 移动
    • 屏幕
  • 实现
  • 代码实现
    • 随机数产生
    • 移动
    • 判断结束
  • 资料

函数

显示

头文件 curses.h

若没有该头文件需要下载
参考博客

curses工作在屏幕,窗口和子窗口之上。屏幕是设备全部可用显示面积(对终端是该窗口内所有可用字符位置),窗口与具体例程有关。

若要在屏幕上进行输出字符等信息,我们需要划分一个矩形窗口
WINDOW创建一个窗口指针

//指向数字窗口
WINDOW *w_2048=NULL;             //2048游戏窗口
WINDOW *message=NULL;            //信息窗口
WINDOW *score_mode_frame = NULL; //分数和模式窗口
WINDOW *choose = NULL;           //菜单选择窗口 
WINDOW *over_frame = NULL;       //结束窗口

WINDOW *newwin(int lines, int cols, int start_y, int start_x); //创建从(start_y, start_x)开始的lines行cols列的窗口。

w_2048 = newwin(N, N*6, w_2048_y0, w_2048_x0);
choose = newwin(10,3,12,27);
message = newwin(1,36,6,16);
score_mode_frame = newwin(1,36,8,16);
over_frame = newwin(6,30,20,22);

当我们窗口构建完以后,我们就开始对特定坐标处进行填写字符
其中涉及到的几个函数为:
linux下运行2048小游戏_第1张图片
实现步骤:
1.先利用函数wmove将光标移动到需要填写的坐标开始处
2.然后用函数waddstr添加需要显示的字符串,也可以用waddch添加需要的显示的单个字符
3.用函数wrefresh刷新

wmove(over_frame,2,0);
waddstr(over_frame,"PRESS ENTER GO TO MENU ");
wrefresh(over_frame);

其实通过这些函数我们在显示这一部分就差不多可以完成了,剩下的就是移动

移动

当然移动部分的函数也是在curses.h函数中

keypad函数打开或关闭指定窗口的功能键
wgetch函数是从指定窗口获得输入

	keypad(w_2048, TRUE);   //表示w_2048这个窗口,有功能键
	int ch = wgetch(w_2048); //若没有输入则会一直等待
	keypad(w_2048, FALSE);

	switch(ch)
	{
		case 'w':
		case 'W':
		case KEY_UP:
			return UP;
		case 's':
		case 'S':
		case KEY_DOWN:
			return DOWN;
		case 'a':
		case 'A':
		case KEY_LEFT:
			return LEFT;
		case 'd':
		case 'D':
		case KEY_RIGHT:
			return RIGHT;	
		case 'q':
		case 'Q':
			return QUIT;
	}

其中返回值我们是在另外一个文件进行宏定义了的

#define LEFT   1
#define RIGHT  2
#define UP     3
#define DOWN   4
#define ENTER  5
#define QUIT   100

这样我们的移动也就基本完成了,我们就根据移动的返回值来进行相对应的操作

屏幕

屏幕部分是我们最开始和结束的时候需要使用的,涉及的头文件还是curses.h
这些函数一般不需要过多理解,直接调用就行

/*
	open_screen: 初始化字符窗口相关的功能
	参数:无
	返回值:
		无
*/
void open_screen(void)
{
	initscr(); //初始化字符屏幕
	cbreak(); //Ctrl + c
	noecho(); //不用回显 
	keypad(stdscr, TRUE); //使用功能键

}


/*
	close_screen:关闭字符窗口
	参数:无
	返回值:
		无
*/
void close_screen(void)
{
	endwin(); //关闭字符窗口
}

实现

1.菜单(上下键移动,ENTER选择)
<1> 游戏开始
<2> 设置
<3> 退出
linux下运行2048小游戏_第2张图片
2.游戏界面
<1> 得分score(当合成一个数值后,分数加上这个数值)
<2> MAX是指合成的最大数值,则胜利(可设置更改)
<3> mode游戏模式(可设置更改)
<4> 2048游戏矩阵4*4
linux下运行2048小游戏_第3张图片
3.游戏胜利
没移动一次,就会在0处随机产生一个数,当最大数值达到MAX则胜利,按ENTER返回菜单
linux下运行2048小游戏_第4张图片
4.游戏失败
当无可移动以及无可合成的数时,代表游戏失败
linux下运行2048小游戏_第5张图片

代码实现

其实整个主逻辑很简单,就是用过移动改变一些数组,变量的值,然后循环体中不断调用刷新函数。主要就是几个函数的实现的一些算法
首先我们需要一个2048矩阵即二维数组,我们会不断更改二维数组的值,并刷新屏幕

int matrix_2048[N][N];  //2048矩阵  N宏定义为4
//定义指向矩阵的指针
int (*matrix)[N]= matrix_2048;   

随机数产生

1.随机数列表

int rand_list_all[7]={0,0,0,2,4,8,16};             //初始化的随机填充数列
int rand_list_a[14]={2,2,2,2,2,2,4,4,4,4,8,8,8,32};//移动后随机填充单个数字的数列

2.游戏初始随机数的产生

void fill_all_number(void)
{
	int row,col;
	for(row=0;row<N;row++)
	{
		for(col=0;col<N;col++)
		{
			*(*(matrix+row)+col) = rand_list_all[random() % 7];
		}
	}
}
3.移动后的随机填充一个数
既然是随机填充,我们需要知道随机位置,所以我们先知道矩阵中0的个数
```c
//获取矩阵中0的个数
//返回值 num:0的个数
int get_zero_num(void)
{
	int row,col;
	int num =0;
	for(row=0;row<N;row++)
	{
		for(col=0;col<N;col++)
		{
			if(*(*(matrix+row)+col) == 0)
				num++;
		}
	}
	return num;
}
//随机一个位置用于移动的时候
//返回值 0:生成失败          1:生成成功
int fill_a_number(void)
{
	int row,col;
	int n=0;
	int zero_num =get_zero_num();
	if(zero_num == 0)
		return 0;
	int pos = random() % zero_num + 1;
	for(row=0;row<N;row++)
	{
		for(col=0;col<N;col++)
		{
			if(*(*(matrix+row)+col) == 0)
			{
					n++;
				if(n == pos)
					*(*(matrix+row)+col) = rand_list_a[random() % 14];
			}
		}
	}
	return 1;
}

移动

1.通过移动的方向来调用不同的函数

switch(mv)
	{
		case LEFT:
			move_left();
			break;
		case RIGHT:
			move_right();
			break;
		case UP:
			move_up();
			break;
		case DOWN:
			move_down();
			break;
			
	}

2.实现函数
其实我们只需要懂得一个方向的原理就知道其他的了
我们以move_left为例,如果我们把0看过空白的话,相邻的且相同的数会合在一起,放在左边的那个数中,右边的数则会清0,若不满足条件则会紧接着放在左边

我们有两个变量
index:数组下标,指向往左边放数值的位置
temp:临时变量,用于保存下一个非0数或者用于与下一个非0数值进行比较
<1>首先我们操作的数是非0数

if (*(*(matrix+row)+col) != 0)

<2> 然后将第一个非0数放在临时容器变量里面,或者已经移动后,用于存储下一个非0数,存储后该坐标下的值应该清0

if (*(*(matrix+row)+col) != 0)
{
	if (temp == 0)
	{
		temp =	*(*(matrix+row)+col);
		*(*(matrix+row)+col) = 0;
	}

<3> 如果temp里面有值,那么就有两种情况

1> temp与下一个非0数相同
相同则代表我们需要合成,然后将合成的值往左边移动,然后将该坐标值清0,temp清0

if (*(*(matrix+row)+col) == temp)
	{
	//合并,再移动
		temp  += *(*(matrix+row)+col);   //合并
		if(temp == max_number) win_sign =1;  //胜利标志
		score += temp;  //分数
		*(*(matrix+row)+col) = 0;   //清0
		*(*(matrix+row)+ index++) = temp;   //移动
		temp = 0;  //清0
	}

2> temp与下一个非0数不相同

else
{	
	//相邻但不相等
	//先移动x,然后把matrix[i][k]->temp
	*(*(matrix+row)+ index++) = temp;  //移动
	temp = *(*(matrix+row)+col);  //更换
	*(*(matrix+row)+col) = 0;   //清0
}

然后每一行都这样判断循环下去就可以了,对于其他方向注意行和列

判断结束

当我们移动后,如果数值并无变换,我们就得需要考虑一下,是不是达到了结束的条件:无空白(0)的地方,无可合成的数对(每个数的两个垂直方向没有与之相同的数)

//判断游戏是否结束
//返回值 1: 游戏结束,无可移动 0:游戏未结束
int game_over(void)
{
	int row,col;
	
	if(get_zero_num())
	{
		return 0;   //空白位置个数>0,游戏肯定不结束
	}

	for(row = 0;row < N;row++)
	{
		for(col = 0;col < N;col++)
		{
			//j < N - 1 表示这个元素不是这一行的最后一个元素!!
			if(col < N-1 && *(*(matrix+row)+col) == *(*(matrix+row)+(col+1)))
			{
				return 0;
			}
			
			// i < N - 1 表示i不是最后一行
			if(row < N -1 && *(*(matrix+row)+col) == *(*(matrix+(row+1))+col))
			{
				return 0;
			}
		}
	}
	return 1;
	
}

资料

链接:https://pan.baidu.com/s/1iy6vR-hPTxTdf8hkTF3DPw
提取码:8jab

用的时候我们需要通过虚拟机在windows创建一个共享文件夹,然后将文件放入共享文件夹,在linux下才行访问得到这些文件

这个我已经添加过了
linux下运行2048小游戏_第6张图片
linux下运行2048小游戏_第7张图片
linux下运行2048小游戏_第8张图片
就可以完成了

然后找到该文件夹并在终端下打开
linux下运行2048小游戏_第9张图片
linux下运行2048小游戏_第10张图片
在终端处打开
linux下运行2048小游戏_第11张图片
linux下运行2048小游戏_第12张图片

如果有疑问记得留言,谢谢你的观看!!!

你可能感兴趣的:(linux)