自己编的贪吃蛇程序,最多就用到了数组,很适合小白,注释比较全
如何将要点亮的坐标转化成点阵屏需要的码表
红色的位置坐标为(0,0)
假设我们要点亮蓝色的位置,即点亮坐标(2,0)和(2,1),由点阵屏的知识我们知道,我们需要的码表tabel[8]={
1 1 0 1 1 1 1 1 --> 0xdf
1 1 0 1 1 1 1 1 --> 0xdf
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
}
很容易发现,需要点亮的位置就要置零
所以我们可以先设一个tabel={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
假设我们的坐标存在一个二维数组里snake[20][2]={{2,0},{2,1}}(后面不赋值的就默认为0,0了)
纵坐标正好就表示我们要修改tabel的第几个数
比如坐标(2,0),我们需要将tabel[0]的0xff的第六位(从右往左数)置零
所以我们可以从这里找到联系(同标红和同标蓝的数据有联系),用以下方法
for(i=0;i<n;i++)//这里的n表示要显示点的个数,此处为n=2
{
tabel[snake[ i][1]]=tabel[snake[ i][1]]^(unsigned char)pow(2,7-snake[ i][0]);
}
其中pow函数是求2的n次方的,包含在头文件<math.h>里,返回值是double
所以要强制类型转换成unsigned char,我们拿纵坐标对应的那个tabel的0xff
与 2的(7-横坐标)次方 按位异或,有点拗口 看例子:
当i=0时,snake[0]={2,0}
pow(2,7-snake[ i][0])=100000
11111111与100000按位异或=11011111即0xdf
当i=2时,snake[1]={2,1}
pow(2,7-snake[ i][0])=100000
11111111与100000按位异或=11011111即0xdf
当i>=2时,tabel为初始值0xff
因此实现了坐标转码表
作者:小仙峰
仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机贪吃蛇源程序如下:
- #include<reg51.h>
- #include<math.h>
- #include<intrins.h>
- #define max 20//最大蛇长
- #define delay 300//delay越小越快
- sbit DIO=P3^4;//串行数据口
- sbit SHCP=P3^5;//移位寄存器时钟
- sbit STCP=P3^6;//输出锁存器时钟
- sbit up=P1^0;//独立键盘上
- sbit down=P1^1;//独立键盘下
- sbit left=P1^2;//左
- sbit right=P1^3;//右
- unsigned char n,i,j,ifdie,button,ret;//依次为当前蛇长,通用循环变量(i和j),是否死亡,上下左右命令储存,果子,eating的返回值
- unsigned char snake[max][2]={1,0,0,0};//蛇的每一个点的坐标数组,蛇头(1,0),第二段为(0,0)
- unsigned char tabel[8] ={0};//这个相当于一个8*8矩阵,用于装坐标转换成的的74HC595需要的8个16进制码
- unsigned char apple[2]={3,3};//初始果子位置,随机数有点麻烦
- void direction(void);//判断上下左右函数
- void eating(void);//判断吃果子函数
- void die(void);//判断死亡函数
- void send_byte(unsigned char byte);//74HC595串入并出要用到的函数
- void show(void);//以上都是处理蛇的坐标,这个函数就是将要显示的坐标转换成74HC595能识别的16进制码
- void main()
- {
- ifdie=1;//先赐死
- while(ifdie)
- {
- ifdie=0;//然后重生
- n=2;//初始蛇长为2
- snake[0][0]=1; snake[0][1]=0;//蛇每次重生在左上角
- snake[1][0]=0; snake[1][1]=0;//蛇每次重生在左上角
- apple[0]=3; apple[1]=3;//果子回到初始位置
- button=0;//重生后要把按键赋零
- while(ifdie!=1)//蛇没死我们就循环执行
- {
- ret=0;//每一轮开始都设没吃到果子
- direction();//判断方向,改变坐标
- eating();//判断如果吃到果子身长+1
- die();//判断死没死
- show();//将蛇身的坐标转码展示到点阵屏上
- if(n==max)
- ifdie=1;//蛇长最大了,赐死吧
- }
- }
- }
- void direction(void)//判断方向
- {
- if(button==1&&snake[0][1]!=snake[1][1]+1)//向上
- {
- for(i=n-1;i>0;i--)//后一个蛇身坐标等于前一个蛇身坐标
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][1]--;//蛇头纵坐标减一
- }
- if(button==2&&snake[0][1]!=snake[1][1]-1)//向下
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][1]++;
- }
- if(button==3&&snake[0][0]!=snake[1][0]+1)//向左
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][0]--;
- }
- if(button==4&&snake[0][0]!=snake[1][0]-1)//向右
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][0]++;
- }
- }
- void eating(void)
- {
- if(snake[0][0]==apple[0]&&snake[0][1]==apple[1])//当蛇头坐标与果子坐标相同时
- {
- for(j=0;j<2;j++)
- {
- snake[n][j]=snake[n-1][j];//吃到果子后,蛇的下一节长出来
- apple[j]=snake[n-1][j];//不会随机数,所以下一个果子出现在蛇尾
- }
- n++;//蛇长加一
- ret = 1;//告诉下面的步骤:吃到了果子
- }
- }
- void die(void)
- {
- if(snake[0][0]==8||snake[0][0]==255||snake[0][1]==8||snake[0][1]==255)//蛇头出界
- ifdie=1;//死掉
- for(i=4;i<n;i++)//因为撞自己蛇长至少要五,所以i从四开始
- {
- if(snake[0][0]==snake[i][0]&&snake[0][1]==snake[i][1])
- ifdie=1;//如果蛇头和蛇身坐标重合,死掉
- }
- }
- void send_byte(unsigned char byte)//这是清翔讲的8*8点阵屏+74HC595的标配函数
- {
- unsigned char dat;
- dat=byte;
- for(j=0;j<8;j++)
- {
- SHCP=0;
- STCP=0;
- if(dat & 0X01)
- DIO=1;
- else
- DIO=0;
- SHCP=1;
- dat>>=1;
- }
- }
- void show(void)//这个比较关键,把坐标转化成8个16进制数
- {
- unsigned char lie=0x80;
- unsigned int z;
- unsigned char t;
- for( i=0;i<8;i++)
- tabel[i]=0xff;//先重置tabel,全都赋值0xff
- if(ret) t=n-1;//如果这一轮吃到了果子,那么蛇长加了一,而实
- else t=n;// 际上这一轮需要显示的是没加一的蛇(因为蛇头和果子重合)
- for(i=0;i<t;i++)//具体思路略
- tabel[snake[i][1]]=tabel[snake[i][1]]^(unsigned char)pow(2,7-snake[i][0]);
- if(ret==0) tabel[apple[1]]=tabel[apple[1]]^(unsigned char)pow(2,7-apple[0]);
- if(n==max)//如果蛇长达到最大了,我们就让全屏亮
- {
- for(i=0;i<8;i++)
- {
- tabel[i]=0;
- }
- }
- for(z=0;z<delay;z++)//这里也是使用74HC595的步骤
- {
- for(i=0;i<8;i++)
- {
- send_byte(tabel[i]);
- send_byte(lie);
- STCP=0;
- STCP=1;
- lie=_cror_ (lie,1);
- }
- if(up==0)//由于需要全程扫描按键是否被按下,那就在显示过程中扫描
- button=1;
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
贪吃蛇小仙峰版.zip
(148.21 KB, 下载次数: 98)
|