嵌入式Linux开发-在6818开发板显示2048游戏

该项目只是一个原始版本,图片已经删除,我已经上传完整的项目资源zip,如有需要请自行下载!!!

https://download.csdn.net/download/weixin_46836491/86694132?spm=1001.2014.3001.5503

完成图:
在这里插入图片描述
点击左上角
随机清除4个不为0的数

点击左下角重置游戏

代码如下:

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>//字符串函数的头文件
#include <sys/mman.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <time.h>   

/*宏定义*/
#define LCD_PATH "/dev/fb0"   //语法高亮
#define TOUCH_PATH "/dev/input/event0"

#define DWON    0  //上
#define UP      1  //下
#define LEFT    2  //左
#define RIGHT   3 //右
#define EXIT    4 //退出游戏
#define RE_START 5//重新开始游戏
#define Remove 6//消除
//...可以实现其他的按键功能


/*全局变量*/
int* plcd = NULL;//指向帧缓冲的映射区域的首地址 初始化的时候指向为空
int fb_fd = -1;
int x = -1,y = -1;
int matrix[4][4]={
  0,0,0,0,
  0,0,0,0,
  0,0,0,0,
  0,0,0,0
};

int OLD_matrix[4][4];


/*函数声明*/
void Init_Lcd(void);
void UNinit_Lcd(void);
void LCD_Draw_Point(int x,int y,int color);
int Bmp_display(char *bmp_file,int x0,int y0);
void get_xy(int *x,int *y);
void  Init_Game_view(void);
int Get_Zero_num(void);//获取二维数字有多少个0元素
int Rand_Fill_Num(void);//随机位置填充随机数字
int Usr_Control_touch(void);
int IS_Win(void);
int IS_Failed(void);
void Save_old_matrix(void);
int Judge_matrix(void);
void Display_matrix(void);
void matrix_right(void);
void matrix_left(void);
void matrix_down(void);
void matrix_up(void);
void GAME_INIT(void);
void Game_Remove(void);
int Rand_Fill_Num2(void);
int Get_One_num(void);
int main()
{
	srand(time(NULL));
	//1.打开屏幕
	Init_Lcd();
	//2.显示开机图片
	Bmp_display("Begin.bmp",0, 0);
	Bmp_display("play.bmp",240,380);
	//3.判断用户是否按下了开始按键
	while(1)
	{
		get_xy(&x, &y);
		if(x>=0 && x<=800 && y>=300 && y<=480)
		{

			
			//Bmp_display("7.bmp",0, s0);
			
			break;
		}
	}
	x = -1,y=-1;
	InitGame:
	//4.进入游戏界面
	Init_Game_view();
	//5.开始游戏
	while(1)
	{
		int direction = Usr_Control_touch();
		//保存以前的数组
		Save_old_matrix();
		if(direction == RIGHT)
		{
			//棋盘向右移动
			matrix_right();
		}
		else if(direction == LEFT)
		{
			matrix_left();
		}
		else if(direction == UP)
			{
			matrix_up();
		}
		else if(direction==DWON)
			{
			matrix_down();
		}
		else if(direction==RE_START)
			{
			GAME_INIT();
			goto InitGame;
		}else if(direction==Remove)
			{
			Game_Remove();
			
		}
		x = -1,y = -1;//坐标重置
		//在随机的位置填充随机数字之前我们需要判断是否需要填充
		if(Judge_matrix())
		{
			Rand_Fill_Num();
		}
		Display_matrix();
		//判断
		if(IS_Win()==1)
		{
			Bmp_display("shengli.bmp",0,0);
			//询问用户是否重新开始游戏
			while(1)
		{
		get_xy(&x, &y);
		if(x>=280 && x<=450 && y>=350 && y<=600)
		{
			
			break;
			}
		}
			x = -1,y=-1;
			GAME_INIT();
			goto InitGame;
			break;
		}
	
			
		else if(IS_Failed()==1)
		{
			Bmp_display("shibai.bmp",0, 0);
			//嘲讽用户一波 询问是否重新开始游戏
			while(1)
		{
		get_xy(&x, &y);
		if(x>=280 && x<=450 && y>=350 && y<=600)
		{
			
			break;
			}
		}
			x = -1,y=-1;
			GAME_INIT();
			
			goto InitGame;
			break;
		}
	}
	
	//Bmp_display("2.bmp", 0, 0);
	UNinit_Lcd();
}

//重新开始
void GAME_INIT()
{
	UNinit_Lcd();
	srand(time(NULL));
	Init_Lcd();
	int b[4][4] = {0};
	int x = -1,y = -1;
	memcpy(matrix, b, sizeof(matrix));
}

//随机清除4个
void Game_Remove()
{
UNinit_Lcd();
srand(time(NULL));
Init_Lcd();
Rand_Fill_Num2();
Rand_Fill_Num2();
Rand_Fill_Num2();
Rand_Fill_Num2();




}

//初始化屏幕 打开屏幕 然后映射

void Init_Lcd(void)
{
	//1.打开屏幕
	//1.打开文件
	int fd = open(LCD_PATH,O_RDWR);//文件描述符 代表 一个已经打开文件
	if(-1 == fd) // fd == -1 <==> fd = -1  -1 = fd =>编译错误
	{
		perror("open LCD fail");//打印错误
		return ;
	}
	fb_fd = fd;
	//2.映射
	plcd = mmap(NULL,480*800*4,PROT_READ|PROT_WRITE,MAP_SHARED,
                  fd,0);
	if(MAP_FAILED == plcd)
	{
		perror("mmap fail");
		return ;
	}
}

//关闭屏幕
void UNinit_Lcd(void)
{
	munmap(plcd,480*800*4);
	plcd = NULL;
	close(fb_fd);
}

//把屏幕上任意的x y的像素点显示成color颜色
void LCD_Draw_Point(int x,int y,int color)
{
	if(x>=0&&x<800&&y>=0&&y<480)//防止传入的参数异常
		*(plcd+x+y*800) = color;
}	

/*
	解析显示一张bmp图片的
	bmp_file:图片文件的路径名 比如:1.bmp              /home/2.bmp 
	x0,y0 在屏幕上显示的起始坐标
*/
int Bmp_display(char *bmp_file,int x0,int y0)
{
	//1.打开bmp图片
	int fd = open(bmp_file,O_RDONLY);
	if(-1==fd)
	{
		printf("open %s fail\n",bmp_file);
		perror("--->");
		return -1;
	}
	//2.判断到底是不是一张bmp图片
	unsigned char buf[4];
	read(fd,buf,2);
	if(buf[0]!= 0x42 || buf[1]!= 0x4d)//若果不是B M
	{
		printf("NOT BMP\n");
		goto ERROR_END;
	}
	//3.获取bmp图片的属性 宽 高 色深
	int width,height;
	short depth;
	lseek(fd,0x12,SEEK_SET);
	read(fd,buf,4);
	
	width=(buf[3]<<24)|
		  (buf[2]<<16)|
		  (buf[1]<<8)|
		  (buf[0]);

	lseek(fd,0x16,SEEK_SET);
	read(fd,buf,4);
	
	height=(buf[3]<<24)|
		  (buf[2]<<16)|
		  (buf[1]<<8)|
		  (buf[0]);

	lseek(fd,0x1c,SEEK_SET);
	read(fd,buf,2);
	
	depth=(buf[1]<<8)|
		  (buf[0]);

	//只支持色深为24和32的
	if(!(depth == 24 || depth == 32))
	{
		printf("NOT Support!\n");
		goto ERROR_END;
	}
	printf("%s:%d*%d depth=%d\n",bmp_file,width,height,depth);
	//4.获取像素数组
	int line_valid_bytes = abs(width)*depth/8;//一行有效字节数
	int line_bytes;//一行总字节数=有效字节数+赖子数 
	int laizi = 0;
	if(line_valid_bytes%4)//判断是否有赖子 不能被4整除
	{
		laizi = 4-line_valid_bytes%4;//差多少就补多少个赖子 要满足4的倍数
	}
	line_bytes = line_valid_bytes + laizi;
	int total_bytes = line_bytes*abs(height);//整个像素数组的大小

	//是不是需要一个地方来存放读出来的这个像素数组呢??
	//unsigned char piexl[total_bytes];
	//也可以向系统申请一块动态内存 
	unsigned char *piexl = (unsigned char *)malloc(total_bytes);
	lseek(fd,54,SEEK_SET);
	read(fd,piexl,total_bytes);
	//5.在屏幕上一一显示这些像素点
	//读像素点字节--->ARGB--->在屏幕上进行显示
	unsigned char a,r,g,b;
	int color;
	int i = 0;
	int x,y;
	for(y=0;y<abs(height);y++)
	{
		for(x=0;x<abs(width);x++)
		{
			//a r g b 0xargb 小端模式  b g r a
			b = piexl[i++];
			g = piexl[i++];
			r = piexl[i++];
			if(depth == 32)
			{
				a = piexl[i++];
			}
			else
			{
				a = 0;//不透明
			}
			color=(a<<24)|(r<<16)|(g<<8)|(b);
			//printf("%x\n",color);
			//在屏幕对应的位置显示
			
			LCD_Draw_Point(width>0?x0+x:x0+abs(width)-x-1, 
							height>0?y0+abs(height)-y-1:y0+y,
							color);
		}
		//每一行的末尾 有可能填充几个赖子
		i += laizi;
	}
	

	free(piexl);
	close(fd);
	ERROR_END:
		close(fd);
		return -2;
}


/*获取用户的输入:x轴的值 y轴的值*/
void get_xy(int *x,int *y)
{
	//1.打开触摸屏
	int fd = open(TOUCH_PATH,O_RDONLY);
	if(-1 == fd)
	{

		perror("open touch fail");
		return ;
	}
	//2.获取用户输入
	//获取屏幕信息
	struct input_absinfo absI;
	ioctl(fd,EVIOCGABS(ABS_X),&absI); //获取屏幕的x轴信息 最小~最大坐标
	printf("x:%d ~ %d\n",absI.minimum,absI.maximum);
	ioctl(fd,EVIOCGABS(ABS_Y),&absI);//y轴信息
	printf("y:%d ~ %d\n",absI.minimum,absI.maximum);
	ioctl(fd,EVIOCGABS(ABS_PRESSURE),&absI);//屏幕的压力的最小~最大
	printf("pres:%d ~ %d\n",absI.minimum,absI.maximum);
	
	struct input_event ev;
	int flag_x = 0,flag_y = 0;
	while(1)
	{
		int res = read(fd,&ev,sizeof(ev));//sizeof 求变量所占的字节数(空间) 读一个结构体大小
		//假设我读出来的字节数跟ev所占的空间不一样 那么就是读取失败
		if(res!=sizeof(ev))
		{
			continue;
		}
		if(ev.type == EV_ABS && ev.code == ABS_X)//获取X轴坐标
		{
			*x = ev.value*(1.0*800/1024);
			flag_x = 1;
			if(flag_y)
				break;
		}
		if(ev.type == EV_ABS && ev.code == ABS_Y)//获取Y轴坐标
		{
			*y = ev.value*(1.0*480/600);
			flag_y = 1;
			if(flag_x)
				break;
		}
	}
	//3.关闭触摸屏
	close(fd);
}

/*根据二维数组的内容更新游戏棋盘*/
void Display_matrix(void)
{
	char bmp_name[64]={0};//保存游戏区域格子需要显示的图片的名字
	int i,j;
	for(i=0;i<4;i++)//遍历二维数组的每一个元素
	{
		for(j=0;j<4;j++)
		{
			if(matrix[i][j])//假设不为0 则显示对应的图片 为0则显示一张空白图片
			{
				memset(bmp_name,0,64);//将数组清空
				sprintf(bmp_name,"9090/digit_%d.bmp",matrix[i][j]);//相当于把color_x80_4.bmp-->bmp_name
				Bmp_display(bmp_name,100+j*(80+10),65+i*(80+10));
			}
			else
			{
			  	//显示一张空白图片
			  	Bmp_display("play1.bmp",100+j*(80+10),65+i*(80+10));
			}
		}
	}
}

/*显示游戏界面*/
void  Init_Game_view(void)
{
		//0.显示游戏界面的背景
		Bmp_display("7.bmp",0, 0);
		//1.显示四个按键
		Bmp_display("xx.bmp",450,170);
		Bmp_display("xx.bmp",660,170);
		Bmp_display("xx.bmp",550,58);
		Bmp_display("xx.bmp",550,295);
		Bmp_display("shuaxin1.bmp",0,430);
		Bmp_display("futou1.bmp",0,0);
	//3.更新棋盘
	//在棋盘的随机两个位置填充随机数字
	Rand_Fill_Num();
	Rand_Fill_Num();//随机位置填充随机数字
	Display_matrix();
}


int Get_Zero_num(void)//获取二维数字有多少个0元素
{
  int i,j,count=0;
  for(i=0;i<4;i++)//遍历二维数组的每一个元素
  {
    for(j=0;j<4;j++)
    {
      if(matrix[i][j]==0)
      {
        count++;
      }
    }
  }
   return count;
}
//获取不为0的数
int Get_One_num(void)//获取二维数字有多少个0元素
{
  int i,j,count=0;
  for(i=0;i<4;i++)//遍历二维数组的每一个元素
  {
    for(j=0;j<4;j++)
    {
      if(matrix[i][j]!=0)
      {
        count++;
      }
    }
  }
   return count;
}

int Rand_Fill_Num(void)//随机位置填充随机数字
{
  //随机位置
  int pos_k = rand()%Get_Zero_num()+1;//1~K
  int i,j,count=0;
  int num[] = {2,2,2,2,4,4,8};//模拟概率
  //遍历到填充位置
  for(i=0;i<4;i++)//遍历二维数组的每一个为0元素
  {
    for(j=0;j<4;j++)
    {
      if(matrix[i][j]==0)
      {
        count++;
        if(count == pos_k)
        {
          //填充
          int n = rand()%7;//0~6
          matrix[i][j]=num[n];
          /*
          以上代码可以简化为matrix[i][j]=num[rand()%7];
          */
        }
      }
    }
  }
}

int Rand_Fill_Num2(void)//随机位置填充随机数字
{
  //随机位置
  int pos_k = rand()%Get_One_num()+1;//1~K
  int i,j,count=0;
  int num[] = {0,0,0,0,0,0,0};//模拟概率
  //遍历到填充位置
  for(i=0;i<4;i++)//遍历二维数组的每一个不为0元素
  {
    for(j=0;j<4;j++)
    {
      if(matrix[i][j]!=0)
      {
        count++;
        if(count == pos_k)
        {
          //填充
          int n = rand()%7;//0~6
          matrix[i][j]=num[n];
          /*
          以上代码可以简化为matrix[i][j]=num[rand()%7];
          */
        }
      }
    }
  }
}

int Usr_Control_touch(void)
{
    	while(1)
	{
		get_xy(&x,&y);//这个函数返回之后 就是获取了x y
		if(x>440&&y>160&&x<550&&y<300){
			//左按钮
			printf("x:%d y:%d\n",x,y);
			Bmp_display("bjn.bmp",450,170);
			usleep(50000);
			Bmp_display("xx.bmp",450,170);
			return LEFT;
		}else if(x>550&&y>300&&x<660&&y<430){
			printf("x:%d y:%d\n",x,y);
			Bmp_display("bjn.bmp",550,295);
			usleep(50000);
			Bmp_display("xx.bmp",550,295);
			//下按钮
			return DWON;
		}else if(x>660&&y>188&&x<792&&y<298){
		printf("x:%d y:%d\n",x,y);
			Bmp_display("bjn.bmp",660,170);
			usleep(50000);
			Bmp_display("xx.bmp",660,170);
			//右按钮
			return RIGHT;
		}else if(x>550&&y>58&&x<662&&y<188){
		printf("x:%d y:%d\n",x,y);
			Bmp_display("bjn.bmp",550,58);
			usleep(50000);
			Bmp_display("xx.bmp",550,58);
			//上按钮
			return UP;
		}else if(x>0&&y>410&&x<100&&y<480){
			printf("x:%d y:%d\n",x,y);
			Bmp_display("shuaxin1.bmp",0,430);
			usleep(50000);
			Bmp_display("shuaxin2.bmp",0,430);
			//上按钮
			return RE_START;
			}else if(x>0&&y>0&&x<100&&y<100){
		printf("x:%d y:%d\n",x,y);
			Bmp_display("futou1.bmp",0,0);
			usleep(50000);
			Bmp_display("futou2.bmp",0,0);
			return Remove;
		printf("x:%d y:%d\n",x,y);
				}
	}
    		}


void matrix_left(void)
{
	//改变棋盘的 改变的二维数组 	
	int i, j;//i为矩阵行下标,j为矩阵列下标
	int value, save_zero;
	for(i = 0; i < 4; i++)
	{
		value = 0;
		save_zero= 0;
		for(j = 0; j < 4 ; j++)
		{
			if (matrix[i][j] == 0)
				continue;
			
			if (value == 0)
				value = matrix[i][j];
			else
			{
				if (value == matrix[i][j])
				{
					matrix[i][save_zero++] = value * 2;
					value = 0;
				} else {
					matrix[i][save_zero++] = value;
					value = matrix[i][j];
				}
			}
			matrix[i][j] = 0;
		}
 
		if (value != 0)
			matrix[i][save_zero] = value;
 
	}
		
}


void matrix_right(void)
{
	int i, j;//i为矩阵行下标,j为矩阵列下标
	int value;
	int save_zero;
	for (i = 0; i < 4; i++)
	{
		value = 0;
		save_zero = 4 -1;
		for (j = 4 - 1; j >= 0 ; j--)
		{
			if(matrix[i][j] == 0)
			{
				continue;
			}
			if(value == 0)
			{
				value = matrix[i][j];
			}
			else
			{
				if(value == matrix[i][j])
				{
					matrix[i][save_zero--] = 2 * value;
					value = 0;
				}
				else
				{
					matrix[i][save_zero--] = value;
					value = matrix[i][j];
				}
			}
			matrix[i][j] = 0;
		}
		if(value != 0)
		{
			matrix[i][save_zero] = value;
		}
	
	}
}
 

void matrix_up(void)
{
	int i, j;//i为矩阵行下标,j为矩阵列下标
	int value;
	int save_zero;
 
	for(j = 0; j < 4; j++)
	{
		value = 0;
		save_zero= 0;
		for(i = 0; i < 4 ; i++)
		{
		
			if(matrix[i][j] == 0)
			{
				continue;
			}
			if(value == 0)
			{
				value = matrix[i][j];
			}
			else
			{
				if(value == matrix[i][j])
				{
					matrix[save_zero++][j] =2 * value;
					value = 0;
				}
				else
				{
					matrix[save_zero++][j] = value;
					value = matrix[i][j];
				}
			}
			matrix[i][j] = 0;
		}
		if(value != 0)
		{
			matrix[save_zero][j] = value;
		}
 
	}
}

void matrix_down(void)
{
	int i, j;//i为矩阵行下标,j为矩阵列下标
	int value;
	int save_zero;
	
	for(j = 0; j < 4; j++)
	{
		value = 0;
		save_zero = 4 - 1;
		for(i = 4 - 1; i >= 0 ; i--)
		{
			if(matrix[i][j] == 0)
			{
				continue;
			}
			if(value == 0)
			{
				value = matrix[i][j];
			}
			else
			{
				if(value == matrix[i][j])
				{
					matrix[save_zero--][j] = 2 * value;
					value = 0;
				}
				else
				{
					matrix[save_zero--][j] = value;
					value = matrix[i][j];
				}
			}
			matrix[i][j] = 0;
		}
		if(value != 0)
		{
			matrix[save_zero][j] = value;
			
		}
		
	}
	
}


/*成功返回1 没有失败返回0*/
int IS_Win(void)
{
	int i,j;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			if(matrix[i][j] == 32)
			{	
				return 1;
			}
		}
	}
	return 0;
}

/*失败返回1 没有失败返回0*/
int IS_Failed(void)
{
	int i, j;
	if(Get_Zero_num() != 0)
	{
		return 0;
	}
 
	for(i = 0; i < 4; i++)
	{
		for(j = 0; j < 4 ; j++)
		{
			if (j != 4 -1)
			{
				if (matrix[i][j] == matrix[i][j+1])
				{
					return 0;
				}
			}
			if (i != 4 - 1)
			{
				if (matrix[i][j] == matrix[i+1][j])
				{
					return 0;
				}
			}
		}
	}
	
	
	return 1;

  //棋盘满了
  
  
}

/*保存原来的数组*/
void Save_old_matrix(void)
{
	int i,j;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			OLD_matrix[i][j] = matrix[i][j];
		}
	}	
}

/*相同返回0   不相同返回1*/
int Judge_matrix(void)
{
	int i,j;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			if(OLD_matrix[i][j] != matrix[i][j])
			{
				return 1;
			}
		}
	}
	return 0;
}






评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ChampLixxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值