摩尔芯闻 > 行业新闻 > 半导体 > 51单片机 8*8点阵贪吃蛇

51单片机 8*8点阵贪吃蛇

eefocus ·2020-03-14 00:00·电子工程世界
阅读:1439

在学完按键和点阵屏后,其实就可以做这个贪吃蛇了,只要理解了8*8点阵屏,贪吃蛇的显示就不成问题,理解了贪吃蛇的运作机制,做出贪吃蛇就不成问题,在网上也有很多人做出了这个程序,主要思想应该都是差不多的,我自认为我构思的思路还是很清晰的,在构思完后很快就将程序写出来了,这里我将我的思路以及代码分享给大家。


这是我的源码,不过是codeblocks+sdcc的环境编译的,无法用keil直接打开,如果要运行,进行移植一下就可以了,可以用作参考。

链接:https://pan.baidu.com/s/1xw-I-7jr_xupAGmat7nQRw

提取码:p96r


主要实现方法:

一、软件层:

1.地图:用一个8个单元数组来模拟点阵屏上的显示情况,第i个单元代表第i行的显示状况,所以每个元素我们使用一个16进制数来赋值给P0端口,实现点阵屏每一行的显示。

2.蛇:用结构体来表示,结构体变量包含:行走方向,每个身体结点的横坐标x[]和纵坐标y[],蛇的长度,蛇的生命。

3.食物:通过伪随机产生函数rand(),随机产生一个0~64的数,对应8*8数组点阵上的每一点,判断该点是否可以产生食物,然后在该点生成食物。

4.吃食物:如果蛇头坐标与食物坐标重合则食物消失,蛇长度加一。

5.移动:蛇在移动时,每次移动先从蛇尾开始,令它保存上一点的坐标信息,这个过程在循环中完成,然后再根据方向改变蛇头的坐标。

6.死亡:在每次移动后,判断是否撞墙(超出边界,横坐标和纵坐标是否小于0或者大于7),判断是否撞身体(蛇头和身体坐标是否有重合)。如果判断蛇死亡则将蛇的生命值置为0,在程序中判断然后宣布游戏结束。

二、底层:

1.显示:利用8*8点阵屏完成显示,其中应该改变平常的纵向显示(一列一列显示),采用横向显示(一行一行显示),因为这样可以和8*8数组很好地契合。具体实现方法就是用74HC595进行位选,然后将数组地每一行转化为由16进制数表示的模式,一行一行显示。

2.按键:选择4个矩阵按键控制方向(上下左右),然后按下按键后改变蛇的方向信息。还可以拓展一些功能比如暂停(将定时器停止计数),加速减速(改变移动频率)。

3.数码管:显示当前的蛇长

4.计时器:用51单片机的计时器功能计时,每过多久就进行移动一次。

三、软件层主要函数

1.Void INIT_SNAKE();//初始化时钟、蛇、创建食物。

2.Void CreatFood(void);//创建食物

3.Void RUN_SNAKE(void);//蛇移动,以及吃到食物增加身体长度。

4.Void DEAD_SNAKE(void);//判断蛇是否死亡

5.Void KEY_SCAN_SNAKE(void);//通过查询按键获得方向,以及对其他功能键功能实现

6.Void DIGPORT_SHOW(void);//将蛇和食物的数据通过该函数转化成在点阵显示屏上显示的数据并显示。

7.Void GameOver(void);//判断游戏是否结束


然后中途遇到一个大坑,好大好大的坑,虽然很早地完成了半成品,可以移动吃食物长身体,也就是完成了主要功能,但是实际上还有一个很大的缺陷,那就是这只蛇最多只有16节,再往上就会造成数据溢出,导致显示错误。这是为什么呢,因为我在定义时有个地方一直出错,结构体定义蛇结点坐标x和y我都用了一个数组,也就是int x[64],int y[64],但是实际上51单片机(在程序存储空间)并没有这么大的空间,最多只能定义到16,这让我很头疼。也是搜索了各种资料,走了好多弯路,尝试了好多方法,甚至还想自己改一个用汇编语言写的启动文件,最后终于找到了合理的解决方案,并且学习到了一个很重要的知识点。那就是关于51单片机存储器的知识。


首先如果不加定义将默认把变量存储到程序存储空间,这里可用的空间比较少,所以我只能开一个最多16的数组。所以就需要改变存储的区域了,这里在定义结构体变量时需要用到xdata,意思是存储到外部数据存储器(外部RAM),可以存放较多的数据。修改编译通过,把烧写进单片机,贪吃蛇可以运行,但是又出现了一个问题,贪吃蛇的显示经常会出现断片的现象,走着走着身体少了一节,但是实际上这节身体还是存在的。寻找了好久的原因,实际上是由于接口接触不好导致的,将接口部分稳定住就没有这种情况发生了。


http://blog.sina.com.cn/s/blog_94994f7b01010s1h.html

这里是我查阅到的资料,的确是我知识的盲区,在视频课程中也没有学到:

code 指定数据是存储在代码区,数据是在编程的时候跟代码一起写入代码存储器,运行过程中不能改变;

xdata 指定数据是存储在外部数据存储器了;

data 指定数据存储在内部低128字节数据存储器里,如果变量不指定存储位置,默认就是data型,这部分存储器寻址速度最快;

idata 指定数据存储在内部低256字节数据存储器里,但51只有128字节内部RAM,52才有256字节;

pdata 指定数据存储在外部低256字节数据存储器里,这时候寻址用8位寄存器R0和R1,而不用16位的DPTR,寻址速度比xdata快。


部分代码解释

我在主函数里完成整个流程,从初始化到获取键值再到定时移动设计,再到判断死亡判断游戏结束,最后将蛇长显示在数码管上将贪吃蛇显示在点阵屏上


void main(void)

{

int time=0;

INIT_SNAKE();

TR0=1;//开始计时

while(1)

{

KEY_SCAN_SNAKE();//获取键值,改变方向、调速

time=TH0*256+TL0;

if(time >= 10000)//10毫秒记一次

{

t++;

}

if(t>=tlimit)//每隔一段时间移动一次,我在按键中设置了调速的功能,就是改变tlimit的值实现的

{

RUN_SNAKE();//蛇移动一次

TH0=0;//时间置零

TL0=0;

t=0;

}

DEAD_SNAKE();

GameOver();

gDigValue[0]=snake.lenth/10;

gDigValue[1]=snake.lenth%10;

DigDisplay();//将蛇长显示在数码管上

DIGPORT_SHOW();

}

}


初始化过程:


void INIT_SNAKE(void)//初始化时钟、蛇、数码管、创建食物。

{

TMOD = 0x01;     // 设T0为方式1,GATE=1;

TH0 = 0;

TL0 = 0;

ET0 = 1;              // 允许T0中断

EA = 1;     // 开启总中断


int0init();//开启中断

int1init();


for(u8 i=0;i<8;i++)//初始化数码管

gDigValue[i]=17;//17对应的是不亮


snake.life=1;

snake.dir=2;//初始化方向,0为上,1为左,2为右,3为下

snake.x[1]=0;//初始位置设置

snake.y[1]=0;

snake.x[0]=1;

snake.y[0]=0;

snake.lenth=2;


CreatFood();//建立食物

}


蛇的移动就和我思路说的一样,在移动时,每次移动先从蛇尾开始,令它保存上一点的坐标信息,这个过程在循环中完成,然后再根据方向改变蛇头的坐标,然后根据蛇头坐标判断是否吃到食物。


void RUN_SNAKE(void)//蛇移动,以及吃到食物增加身体长度。

{

for(int i=snake.lenth; i>0; i--)//先从蛇尾的身体结点开始,保存上一点的坐标信息

{

snake.y[i]=snake.y[i-1];

snake.x[i]=snake.x[i-1];

}

switch(snake.dir)//根据方向改变蛇头的坐标

{

case 0:snake.y[0]-=1;break;//上

case 1:snake.x[0]-=1;break;//左

case 2:snake.x[0]+=1;break;//右

case 3:snake.y[0]+=1;break;//下

default:break;

}

if(snake.x[0]==food.x && snake.y[0]==food.y)//如果吃到食物就加长然后再次创建食物

{

snake.lenth++;

CreatFood();

}

}


创建食物,就是利用stdlib.h头文件包含的rand()创建一个0~64随机值,然后转换成对应在点阵屏上的坐标,由于不能生成在蛇身上,就需要进行一个判断,如果在蛇的身上就需要重新创建食物。


void CreatFood(void)//创建食物

{

u8 n=0;

n=rand()%64;

food.x=n%8;

food.y=n/8;

for(u8 i=0;i

{

if(food.x==snake.x[i] && food.y==snake.y[i])//食物与蛇重合

{

CreatFood();//递归调用重新产生一个食物

return;

}

}

}


这个显示函数算是比较核心的了,你创建了蛇,创建了食物,完成了蛇的移动,这些都是存在一个虚拟的8*8数组中的,作为游戏肯定要将它显示在点阵屏上。首先要构造出这个8行的显示状况,然后再按行显示,这里采用的是74HC595位选,一行一行地显示。这个构造地方法就是先将这个地图每一行置为0,将蛇结点对应的行对应的位与进去

关键字: 51单片机 8*8点阵 贪吃蛇 编辑:什么鱼 引用地址: http://news.eeworld.com.cn/mcu/ic491519.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

分享到:
微信 新浪微博 QQ空间 LinkedIn

上一篇:富士康中国产能恢复超预期,但疫情范围扩散国外市场堪忧

下一篇:51单片机LED点阵显示文字

打开摩尔直播,更多新闻内容
半导体大咖直播分享高清观看
立即下载