2048小游戏----嵌入式系统实训
嵌入式系统设计实训
- 引言
本次嵌入式系统实训式设计一款2048小游戏,在Linux编译环境下及ARM Cortex-A8开发平台下的,实现2048游戏的开发,且对其进行性能分析。《2048》是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。《2048》这款小游戏是一款流行的数字游戏,游戏设计初衷是一款益智类的游戏,其特点在于轻松、简单、有趣。在此次实训报告的制作过程中,我们小组将运用学习到的知识以及c编程知识,通过网上现有的资料尝试完成此次实训的开发。
- 实训介绍
- 项目介绍
2048益智游戏:有16个格子,初始时会有两个格子上安放了两个数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。《2048》中每个格子的数据和颜色的都在不断地刷新,在每一次移动之后,几乎在这4*4的每一个方格上的数据都会变化,因此在每一次移动之后,每一个方格上的数据都要刷新一次。相对的,每一个数的背景颜色是不同的,也就是说,在每一次数据刷新的时候,每一个方格上的颜色也要同样的刷新一次。当屏幕上没有写有数据的方格并且屏幕上的数据没有哪两个相邻的数据是一样的两个数,那么就判定为游戏结束。
- 项目目的
本次工程实践训练第一部分是实训装置的使用说明,讲述了系统的组成、硬件的特点和技术指标、软件的使用介绍。第二部分是实训项目部分,叙述了实训的原理、步骤及注意事项等。通过对实训工作情况及项目原理、软硬件的详细介绍,通过实际操作让我们对实训项目有一个充分的认识,培养学生的工程实践能力,进一步提高学生分析和编程能力。
- 项目知识
- 硬件平台
本次项目硬件平台采用粤嵌自主研发的GEC210平台,采用三星s5pv210为芯片方案,该芯片内核为ARM Cortex-A8【2】 。
嵌入式系统是以应用为中心,以计算机技术为基础,软硬件可裁减,以适应应用系统对功能、可靠性、成本、体积和功耗等有严格要求的专用计算机系统。
Linux操作系统介绍
Linux【3】是一套免费使用和自由传播的类UNIX操作系统,其创始人为美国著名黑客 --林纳斯托瓦兹。它能运行主要的UNIX工具软件、应用程序和网络协议,且支持32位和64位硬件,是一个性能稳定的多用户网络操作系统。
操作系统:操作系统是计算机系统中最基本的系统软件,它用于有效地管理系统资源,并为用户使用计算机提供了便利的环境。
ubuntu是一个基于linux的免费开源桌面PC操作系统。
交叉开发
一般来说,研发嵌入式产品,由于从产品成本及功能专用性角度出发考虑。嵌入式产品一般只有程序的运行环境,而并没有程序的编译开发环境。
所以,我们一般在通用电脑上用各种编译开发软件把程序编译调试好后,再下载到开发板或相关产品上去运行。
这个过程,我们称之为交叉开发。
SecureCRT的设置与连接
(1)获取连接上的端口号
用串口线连接好开发板后,启动开发板。
在设备管理器中,查找识别出的端口。
若不能正确识别端口(有感叹号),则需要安装驱动。
(2)SecureCRT的设置
点击快速连接,并进行设置
a.协议: Serial
b.端口: 你电脑识别出的端口号
c.波特率: 115200
d.把数据流控制中的RTS/CTS(R)勾去掉
其它保持默认设置
- C程序的交叉编译及运行
由于ARM处理器与Inter处理器其设计架构有本质区别。所以要在arm开发板上运行的程序,则必须要用专用的编译器来编译。
(1)在Source Right4.0软件中编写好C源代码文件,并保存到共享文件夹中。
如: 2048.c
(2)在Ubuntu系统的共享目录中,用arm-linux-gcc编译器对2048.c进行编译,使生成一个可执行程序。
arm-linux-gcc 2048.c –o 2048
(3)下载到开发板中
rz
(4)运行2048这个程序
chmod +x 2048
./ 2048
- LCD显示原理
屏幕由y行且每行x个像素点的矩阵组成;在屏幕上显示图像,就是给每个像素点显示一种颜色,颜色值,可以量化:Color = xGreen + yBlue + zRed
我们向屏幕设备文件 /dev/fb0 中写入各点颜色值就可以让屏幕显示相应的图片了。
- 项目结果分析总结
- 项目程序代码见附录
- 项目设计过程及展示
图4.3 在SecureCRT 下执行
通过添加代码,使得手指按不同方向滑动屏幕时显示不同数字,用来测试ARM开发板是否运行正确,如下图所示手指上滑打印数字1,下滑打印数字2,左滑打印数字3,右滑打印数字4,执行结果如下图所示。
根据运行结果可得,数字显示与手指滑动方向一致,即ARM开发板是良好的。
附录
1.2048小游戏项目程序代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <linux/input.h>
#define LCD_WIDTH 800 //屏幕宽度
#define LCD_HEIGHT 480 //屏幕高度
#define ITEM_NUM 4 // 创建4行4列的矩阵
#define ITEM_WIDTH 100 // 图片宽100
#define ITEM_HEIGHT 100 // 图片高100
#define BLANK_SIZE 5
#define MATRIX_X0 (LCD_WIDTH - (ITEM_WIDTH + BLANK_SIZE)*ITEM_NUM)/2
#define MATRIX_Y0 (LCD_HEIGHT - (ITEM_HEIGHT + BLANK_SIZE)*ITEM_NUM)/2
void bmp_display(int x0, int y0,const char *bmp_file);
int *plcd = NULL;
int matrix_2048_bak[4][4];
int matrix_2048[4][4] = {
0, 0 , 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
void print_matrix_2048()
{
int i,j;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4 ; j++)
{
printf("%d " ,matrix_2048[i][j]);
}
printf("\n");
}
}
int is_change()
{
int i, j ;
for (i = 0; i < 4; i++)
{
for (j = 0; j < 4; j++)
{
if (matrix_2048[i][j] != matrix_2048_bak[i][j])
{
return 1;
}
}
}
return 0;
}
void LCD_Draw_Point(int x, int y, int color)
{
if (x >= 0 && x < 800 && y >= 0 && y < 480)
{
*(plcd + 800*y + x) = color;
}
}
//LCD_Draw_JuXing: 在屏幕点(x0,y0)处画一个长为w,高为h的矩形
void LCD_Draw_JuXing(int x0, int y0, int w, int h ,int color)
{
//假设矩形内任意点的坐标为(x,y)
int x, y;
for (y = y0; y < y0 + h; y++)
{
for (x = x0; x < x0 + w; x++)
{
LCD_Draw_Point(x, y, color);
}
}
}
void LCD_Draw_Matrix()
{
int i, j;
int x0, y0; //每个棋子矩形左上顶点的坐标
for (i = 0; i < ITEM_NUM; i++)
{
for (j = 0; j < ITEM_NUM ; j++)
{
y0 = MATRIX_Y0 + (ITEM_HEIGHT + BLANK_SIZE)*i;
x0 = MATRIX_X0 + (ITEM_WIDTH + BLANK_SIZE)*j;
if (matrix_2048[i][j] == 0)
{
LCD_Draw_JuXing(x0, y0, ITEM_WIDTH, ITEM_HEIGHT, 0xff0000);
}
else
{
char filename[32];
sprintf(filename, "m%d.bmp", matrix_2048[i][j]);
bmp_display(x0, y0, filename);
}
}
}
}
void bmp_display(int x0, int y0,const char *bmp_file)
{
int fd;
unsigned char buf[4];
int ret;
fd = open(bmp_file, O_RDONLY);
if (fd == -1)
{
printf("failed to open %s\n", bmp_file);
return ;
}
lseek(fd, 0 ,SEEK_SET);
read(fd, buf, 2);
if (buf[0] == 0x42 && buf[1] == 0x4d )
{
printf("BMP file\n");
}
else
{
printf("Not BMP file, GOOD BYE\n");
close(fd);
return ;
}
int width,height;
int depth;
lseek(fd, 0x12, SEEK_SET);
read(fd, buf, 4);
width = (buf[0]) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
lseek(fd, 0x16, SEEK_SET);
read(fd, buf, 4);
height = (buf[0]) | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
printf("%d X %d\n", width, height);
lseek(fd, 0x1c, SEEK_SET);
read(fd, buf, 2);
depth = (buf[0]) | (buf[1] << 8);
if (depth != 24 && depth != 32)
{
printf("Not Support\n");
close(fd);
return ;
}
int bytes_per_line = abs(width) * (depth / 8);
int laizi = 0;
if (bytes_per_line % 4 != 0)
{
laizi = 4 - bytes_per_line % 4;
}
int bytes_line = bytes_per_line + laizi;
int size = bytes_line * abs(height);
unsigned char *p = malloc(size);
lseek(fd, 54, SEEK_SET);
read(fd, p, size);
unsigned char b ,g, r ,a;
int color;
int i = 0;
int x;
int y;
for (y = 0; y < abs(height); y++)
{
for (x = 0 ;x < abs(width); x++ )
{
b = p[i++];
g = p[i++];
r = p[i++];
if (depth == 32)
{
a = p[i++];
}
else
{
a = 0;
}
color = (a << 24) | (r << 16) | (g << 8) | (b);
LCD_Draw_Point( width > 0 ? x0 + x : x0 + abs(width) - 1 -x,
height > 0 ? y0 + height - 1 - y : y0 + y,
color);
}
i = i + laizi;
}
free(p);
close(fd);
}
int get_zero_num()
{
int n = 0;
int i, j;
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_random(void)
{
int zero_num = get_zero_num(); //获取数组中值为0的个数
int pos; //随机的位置的编号,应该要在[0, zero_num)
pos = random() % zero_num ; // => pos =>[0,zero_num)
int i,j;
int n = 0; //第几个0
for (i = 0; i < ITEM_NUM; i++)
{
for (j = 0; j < ITEM_NUM; j++)
{
if (matrix_2048[i][j] == 0)
{
if (n == pos)
{
matrix_2048[i][j] = 2;//a[index];
return ;
}
n++;
}
}
}
}
#define MOVE_UP 1
#define MOVE_DOWN 2
#define MOVE_LEFT 3
#define MOVE_RIGHT 4
int get_finger_movemenet(void)
{
int fd;
int ret;
fd = open("/dev/input/event0", O_RDONLY);
//fd = open("/dev/event0", O_RDONLY);
if (fd == -1)
{
printf("open /dev/event0 failed\n");
return -1;
}
int x1 = -1, y1 = -1; //在一次滑动过程中,第一个点的坐标
int x2, y2; //在一次滑动过程中 ,最后一个点的坐标
struct input_event ev;
while (1)
{
ret = read(fd, &ev, sizeof(ev));
if (ret != sizeof(ev))
{
continue;
}
if (ev.type == EV_ABS && ev.code == ABS_X)
{
if (x1 == -1)
{
x1 = ev.value;
}
x2 = ev.value;
}
if (ev.type == EV_ABS && ev.code == ABS_Y)
{
if (y1 == -1)
{
y1 = ev.value;
}
y2 = ev.value;
}
if (ev.type == EV_ABS && ev.code == ABS_PRESSURE && ev.value == 0)
{
int delt_x = abs(x2 - x1); // 左右
int delt_y = abs(y2 - y1); //上下
if (delt_x > 2*delt_y)
{
if (x2 > x1)
{
close(fd);
return MOVE_RIGHT;
}
else
{
close(fd);
return MOVE_LEFT;
}
}
else if (delt_y > 2*delt_x)
{
//上下
if (y2 > y1)
{
close(fd);
return MOVE_DOWN;
}
else
{
close(fd);
return MOVE_UP;
}
}
else
{
x1 = -1;
y1 = -1;
}
}
}
close(fd);
}
void move_left(void)
{
int i, j;
int x, y;
for (i = 0; i < ITEM_NUM; i++)
{
for (x = 0; x < ITEM_NUM; )
{
if (matrix_2048[i][x] != 0)
{
for (y = x + 1; y < ITEM_NUM; y++)
{
if (matrix_2048[i][y] != 0)
{
if (matrix_2048[i][x] == matrix_2048[i][y])
{
matrix_2048[i][x] += matrix_2048[i][y];
matrix_2048[i][y] = 0;
x = y + 1;
break;
}
else
{
x = y;
}
}
}
if (y >= ITEM_NUM)
{
break;
}
}
else
{
x++;
}
}
x = 0;
for (y = 0 ; y < ITEM_NUM; y++)
{
if (matrix_2048[i][y] != 0)
{
if (x != y)
{
matrix_2048[i][x] = matrix_2048[i][y];
matrix_2048[i][y] = 0;
}
x++;
}
}
}
}
void move_right(void)
{
int i, j;
int x, y;
for (i = 0; i < ITEM_NUM; i++)
{
for (x = ITEM_NUM; x >0; )
{
if (matrix_2048[i][x] != 0)
{
for (y = x-1; y>=0; y--)
{
if (matrix_2048[i][y] != 0)
{
if (matrix_2048[i][x] == matrix_2048[i][y])
{
matrix_2048[i][x] += matrix_2048[i][y];
matrix_2048[i][y] = 0;
x = y - 1;
break;
}
else
{
x = y;
}
}
}
if (y<0)
{
break;
}
}
else
{
x--;
}
}
x = ITEM_NUM-1;
for (y = ITEM_NUM-1 ; y >= 0; y--)
{
if (matrix_2048[i][y] != 0)
{
if (x != y)
{
matrix_2048[i][x] = matrix_2048[i][y];
matrix_2048[i][y] = 0;
}
x--;
}
}
}
}
void move_down(void)
{
int i, j;
int x, y;
for (i = 0; i < ITEM_NUM; i++)
{
for (x = 0; x < ITEM_NUM; )
{
if (matrix_2048[x][i] != 0)
{
for (y = x + 1; y < ITEM_NUM; y++)
{
if (matrix_2048[y][i] != 0)
{
if (matrix_2048[x][i] == matrix_2048[y][i])
{
matrix_2048[x][i] += matrix_2048[y][i];
matrix_2048[y][i] = 0;
x = y + 1;
break;
}
else
{
x = y;
}
}
}
if (y >= ITEM_NUM)
{
break;
}
}
else
{
x++;
}
}
x = 0;
for (y = 0; y < ITEM_NUM; y++)
{
if (matrix_2048[y][i] != 0)
{
if (x != y)
{
matrix_2048[x][i] = matrix_2048[y][i];
matrix_2048[y][i] = 0;
}
x++;
}
}
}
}
void move_up(void)
{
int i, j;
int x, y;
for (i = 0; i < ITEM_NUM; i++)
{
for (x = ITEM_NUM; x >=0; )
{
if (matrix_2048[x][i] != 0)
{
for (y = x - 1; y >= 0; y--)
{
if (matrix_2048[y][i] != 0)
{
if (matrix_2048[x][i] == matrix_2048[y][i])
{
matrix_2048[x][i] += matrix_2048[y][i];
matrix_2048[y][i] = 0;
x = y -1;
break;
}
else
{
x = y;
}
}
}
if (y<0)
{
break;
}
}
else
{
x--;
}
}
x = ITEM_NUM-1;
for (y = ITEM_NUM-1 ; y >= 0; y--)
{
if (matrix_2048[y][i] != 0)
{
if (x != y)
{
matrix_2048[x][i] = matrix_2048[y][i];
matrix_2048[y][i] = 0;
}
x--;
}
}
}
}
int is_gameover(void)
{
int x,y;
for(y=0;y<ITEM_NUM;y++)
{
for(x=0;x<ITEM_NUM;x++)
{
if(matrix_2048[x][y]==0)
{
return 0;
}
if(x<ITEM_NUM-1 && matrix_2048[x][y]==matrix_2048[x+1][y])
{
return 0;
}
if(y<ITEM_NUM-1 && matrix_2048[x][y]==matrix_2048[x][y+1])
{
return 0;
}
}
}
return 1;
}
//根据手指滑动方向变换矩阵
void change_matrix(int mv)
{
if (mv == MOVE_LEFT)
{
move_left();
}
else if (mv == MOVE_RIGHT)
{
move_right();
}
else if (mv == MOVE_UP)
{
move_down();
}
else if (mv == MOVE_DOWN)
{
move_up();
}
}
int main()
{
//1. 打开文件
int fd = open("/dev/fb0", O_RDWR);
if (fd == -1)
{
printf("failed to open /dev/fb0\n");
return -1;
}
printf("open /dev/fb0 successfully\n");
//2. 操作文件
plcd = mmap(NULL,
800*480*4,
PROT_WRITE,
MAP_SHARED,
fd,
0);
if (plcd == MAP_FAILED)
{
printf("failed to mmap\n");
return -1;
}
srandom( time(NULL)) ;//设置随机数种子
LCD_Draw_JuXing(0, 0, LCD_WIDTH, LCD_HEIGHT, 0X555555);
fill_random();
//is_gameover();
LCD_Draw_Matrix();
while (1)
{
int mv = get_finger_movemenet();
printf("mv = %d\n", mv);
change_matrix(mv);
fill_random();
LCD_Draw_Matrix();
print_matrix_2048();
if (is_gameover())
{
break;
}
}
//3.关闭文件
munmap(plcd, 800*480*4);
close(fd);
}
2048小游戏----嵌入式系统实训相关推荐
- C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训
C语言实现2048小游戏---粤嵌GE6818嵌入式系统实训 实现的全部功能: 功能演示: 版本介绍 简易版--大佬选这个 完整版--想保研.想得高分.想要装逼的同学选这个 至尊版--零基础的.想要装 ...
- C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训
C语言实现电子音乐相册---粤嵌GEC6818嵌入式系统实训 功能演示: 版本介绍 滑动式 点击放大式 完整版 至尊版 获取方式 功能演示: 演示视频: 滑动式 点击放大式 版本介绍 分为滑动式.点击 ...
- 基于蓝牙智能家庭影音控制系统---粤嵌GEC6818嵌入式系统实训
版本介绍 普通版 完整版 至尊版 版本介绍 分为普通版.完整版.至尊版三个版本. 普通版 可以满足实训要求,提供代码,不提供技术指导. 实现功能: 1所有界面自行设计,要求尽可能好看 2.执行程序,加 ...
- C语言实现2048小游戏
C语言实现2048小游戏-粤嵌GE6818嵌入式系统实训 部分功能演示视频. 实现的全部功能: 1.字模显示封面组员名字 2.完成2048游戏在板子上的运行 3.成功或者失败需要有标志也可以计分 4. ...
- 我的名片能运行Linux和Python,还能玩2048小游戏,成本只要20元
晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI 猜猜它是什么?印着姓名.职位和邮箱,看起来是个名片.可是右下角有芯片,看起来又像是个PCB电路板. 其实它是一台超迷你的ARM计算机,不仅 ...
- 《STM32单片机开发应用教程(HAL库版)---基于国信长天嵌入式竞赛实训平台(CT117E-M4)》第二章 软件安装与使用
写在前面-- 作为<STM32单片机开发应用教程(HAL库版)-基于国信长天嵌入式竞赛实训平台(CT117E-M4)>系列之第二章,本章节将介绍开发软件STM32CubeMX和KEIL5的 ...
- python游戏代码五子棋_用20行Python代码实现2048小游戏,你会吗?
前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...
- python秒表游戏代码_用20行Python代码实现2048小游戏,你会吗?
前些天在b站上看到有个大佬用c写了一个2048小游戏,我便一下来了兴趣.心想着,我貌似也能用Python来整一波,话不多说,直接开搞. 2048的游戏规则: 2048游戏总共有16个格子,初始时会有两 ...
- c语言2048代码linux,C语言2048小游戏课设(附源码).doc
PAGE PAGE 1 C语言2048小游戏课设 项目说明 本系统基于C语言开发,适用于刚入门的C语言新手项目课设,开发软件采用VC++6.0开发,VS,DEV C++等均可运行.(书生) 项目运行截 ...
最新文章
- 用Python分析《红楼梦》:见证了贾府的兴衰,你是否还能“笑道”世事无常
- LeetCode 6 Z字形变换
- mac下安装nginx
- oracle 存储 更新,oracle 更新空间数据存储过程语句
- 解决DeferredResult 使用 @ResponseBody 注解返回中文乱码
- Js正则表达式数字或者带小数点的数字
- python函数-函数进阶
- hihocoder1543 SCI表示法
- C#.NET 大型企业信息化系统集成快速开发平台 4.2 版本 - 基于数据库资源的多语言实现...
- BZOJ 3359: [Usaco2004 Jan]矩形( dp )
- wamp环境单独安装(windows下apache2.4、mysql5.5、php5.5的版本)
- 死锁的产生原因和解决办法
- 反射的应用之动态代理,顺便复习静态代理
- CASS11:超越自我,再续辉煌!CASS10.1.6:延续经典,只为更好!
- 最新Web前端面试题精选大全及答案
- ffmpeg命令分析-acc
- 上 k8s 生产环境的一些准备!
- 【VREP】四舵轮(or n舵轮)自旋与平移融合运动解算
- webpack出现CssSyntaxError
- 地球系统模式CESM学习记录
热门文章
- IDEA自定义文件识别格式
- 转发:Android项目中,在一个数据库里建立多张表
- python 中三种定义类的方式
- [内功修神]计算机网络
- IDEA搭建JavaWeb项目,JDBC和Servlet-JSP技术实现注册功能
- 致刚入行的web前端工程师:你的学习方法正确吗?
- “肉瘾”女孩从软件测试工程师到主管的成长感悟
- Codeforces Round #492 D. Suit and Tie
- js 文字转码 escape,encodeURI,encodeURIComponent(marksheng)
- PyTorch无法指定GPU的问题解决