一年前做的小玩意了,硬件丢失了,程序还在,以前都是写在一个文件内,翻出来分成几个文件,程序注释写的很详细,希望对初入单片机的师兄有所帮助
单片机源程序如下:
- //=================================================================================================================================================================
- //软件功能:贪吃蛇
- //硬件描述:最小系统+4x(8x8点阵)+ (1x(HC154)+3x(74HC14D)) + 1x(HC595)
- //程序描述:74595.c中有串进并出程序
- // delay.c中有延迟函数
- // dispaly.c中有点阵显示函数
- // anjian.c中有按键函数
- // related.c中有初始化参数函数、游戏结束图案函数、点阵显示清除函数、糖果随机函数、蛇显示变化函数
- //功能概括描述:16x16点阵用于显示、5个按键有旋转按键、上、下、左、右按键
- // 上、下、左、右按键用于控制蛇上下左右移动
- // 有转折点判断(理论上蛇可以打15折)、蛇碰壁判断、蛇速度改变判断
- //=================================================================================================================================================================
- #include "reg52.h" //51头文件
- #include "intrins.h" //部分运算符所需头文件
- #include "74595.h" //74595程序
- #include "delay.h"
- #include "display.h"
- #include "anjian.h"
- #include "related.h"
- #define uchar unsigned char
- #define uint unsigned int
- //=================================================================================================================================================================
- //sbit Beep=P2^7; //蜂鸣器
- uint HUANCUN[16],STX,SWX,GCUNY; //缓存显示数组,蛇头横坐标,蛇尾横坐标,转折点存储数组,果子位置存储
- uchar SSS,t,STY,SWY,GUO,CBN,GCUNX,Q,cus; //蛇方向变量,定时器计时变量,蛇头纵坐标,蛇尾纵坐标,转折点反向存储数组,糖果,计时变量,随机数,蛇方向前一个状态变量
- uchar idata ZZS[16];
- uint idata ZZD[16];
- //=================================================================================================================================================================
- void Init() //初始化
- {
- TMOD=0x01; //工作方式1
- EA=1; //CPU中断开启
- ET0=1; //定时器T0中断开启
- TH0=(65536-5000)/256; //定时5ms
- TL0=(65536-5000)%256;
- TR0=0; //定时器关闭状态
- KS=1; //开始键置高电平
- // Beep=0;
- }
- //=================================================================================================================================================================
- void main()
- {
- Init();
- while(1)
- {
- Q=rand()%256; //随机代码放在while(1)函数中不停运转
- if(TR0==0){ //如果定时器在关闭状态
- J_S(); //清除缓存
- K_S(); //各种数据初始化
- }else{
- if(GUO!=1){ //如果没有糖果
- SUI_JI(); //调用随机子程序
- t--; //蛇的速度加快
- CBN=t; //CBN用于保存改变后的t
- }
- }
- XIANSI(); //循环显示函数
- }
- }
- //=================================================================================================================================================================
- void time0() interrupt 1
- {
- TH0=(65536-5000)/256;
- TL0=(65536-5000)%256;
- AN_J(); //调用按键子程序
- if((--CBN==0)||(cus!=SSS)){
- CBN=t; //CBN随t的变化而变化
- SE_BH(); //调用蛇变子程序
- }
- }
- //=================================================================================================================================================================
复制代码- #include "related.h"
- //=================================================================================================================================================================
- extern uchar SSS,t,STY,SWY,GUO,GCUNX,Q;
- extern uint HUANCUN[16],STX,SWX,GCUNY;
- extern uchar idata ZZS[16];
- extern uint idata ZZD[16];
- //=================================================================================================================================================================
- //功能描述:开始键按下后,初始化各种参数
- //=================================================================================================================================================================
- void K_S()
- {
- uchar i;
- if(KS==0){ //如果开始键按下
- QC_HC();
- SSS=2; //蛇方向向右
- t=50; //蛇初始速度
- SWY=7; //蛇尾初始纵坐标
- STY=7; //蛇头初始纵坐标
- STX=0x0040; //蛇头初始横坐标
- SWX=0x0100; //蛇尾初始横坐标
- HUANCUN[7]=0x01c0; //初始化蛇全身
- ZZS[0]=SSS; //存储蛇的方向
- for(i=0;i<16;i++){
- ZZD[i]=0xffff;
- }
- GUO=0; //无糖果
- TR0=1; //定时器开启
- }
- }
- //=================================================================================================================================================================
- //功能描述:游戏结束后显示预设图案
- //=================================================================================================================================================================
- void J_S() //结束子程序
- {
- QC_HC();
- HUANCUN[2]=0x0ff0; //显示笑脸
- HUANCUN[3]=0x1008;
- HUANCUN[4]=0x2424;
- HUANCUN[5]=0x2a54;
- HUANCUN[6]=0x2004;
- HUANCUN[7]=0x2004;
- HUANCUN[8]=0x2004;
- HUANCUN[9]=0x2004;
- HUANCUN[10]=0x2244;
- HUANCUN[11]=0x2184;
- HUANCUN[12]=0x1008;
- HUANCUN[13]=0x0ff0;
- }
- //=================================================================================================================================================================
- //功能描述:16x16点阵显示清除
- //=================================================================================================================================================================
- void QC_HC() //清除缓存子程序
- {
- uchar i;
- for(i=0;i<16;i++){ //缓存清零
- HUANCUN[i]=0;
- }
- }
- //=================================================================================================================================================================
- //功能说明:”糖果“随机函数
- //程序说明:Q取0~255之间的数,对应16x16点阵上的256个点
- // Q/16取16x16点阵的哪一行,0x0001<<(Q%16)取16x16点阵的哪一列
- // Q随机出一个数后,有可能点阵上的点是亮着的,要重新随机,直到随机到没亮着的点
- // 然后改变对应缓存显示数组HUANCUN[]里的数据
- // 16x16点阵是以左上角为原点的一个坐标(不过y轴不是负的),记录下对应点的横坐标和纵坐标
- // 改变“糖果”的状态变量GUO=1,就是说当前有“糖果”在
- //=================================================================================================================================================================
- void SUI_JI()
- {
- while(HUANCUN[Q/16]&(0x0001<<(Q%16))) //判断随机数对应的点阵上的点是否是灭的状态
- {
- Q=rand()%256; //如果是亮的,那么再随机一次,直到随机到灭的点
- }
- HUANCUN[Q/16]|=(0x0001<<(Q%16)); //让这个点亮起来
- GCUNX=Q/16; //记录该点的横坐标和纵坐标
- GCUNY=(0x0001<<(Q%16));
- GUO=1; //记录糖果状态
- }
- //=================================================================================================================================================================
- //功能说明:当蛇尾处在转折点处时,这个转折点数据没用了,判断蛇还有没有转折点,如果有,覆盖掉这个转折点
- // 根据改变后的转折点,确定蛇尾的坐标
- //=================================================================================================================================================================
- void ZZ_X()
- {
- uchar i;
- if(ZZS[1]!=0){ //如果有第二个转折点
- for(i=0;i<15;i++){ //把第一个转折点覆盖
- ZZD[i]=ZZD[i+1];
- ZZS[i]=ZZS[i+1];
- }
- }
- switch(ZZS[0]) //判断改变后蛇的方向,而后改变蛇尾坐标
- {
- case 1:
- SWY--;
- break;
- case 2:
- SWX>>=1;
- break;
- case 3:
- SWY++;
- break;
- case 4:
- SWX<<=1;
- break;
- }
- }
- //=================================================================================================================================================================
- //思维说明:蛇移动是不是要判断前面有没有障碍物?这个障碍物有可能是蛇的身体,也有可能是糖果。还有,蛇会不会碰壁呢?
- //程序说明:根据蛇的方向(SSS)来分成4种情况,
- // 蛇头就是一个点,这个点被记录下横(STY)和纵坐标(STX),再加上记录下的方向(SSS),可以确定蛇头的下一个位置
- // 当SSS=1时,蛇向上移动,把蛇头横坐标(STX)和缓存显示数组HUANCUN[STY-1]相与,确定该位置是否被点亮,为什么是STY-1呢?点阵第一行对应HUANCUN[0]
- // 当该位置没被点亮时,表示蛇可以移动上去了,把蛇头的坐标改变
- // 否则,把该位置的坐标和糖果的坐标比较,如果是糖果位置,蛇头一样可变。其他情况游戏结束,关定时器TR0
- // 其他3种情况分析同上
- // 蛇尾也不能忘了,一条蛇只标蛇头可不行
- // 如果蛇吃了糖果,那么蛇头长了一点,蛇尾不用变,蛇头坐标变后跳出函数就行了
- // 否则,就要让蛇尾灭掉HUANCUN[SWY]&=(~SWX);
- // 再则,一条蛇可会转弯的哦,那么必须要有转折点,不止一个,要判断,如果需要的话,要做改变
- //=================================================================================================================================================================
- void SE_BH() //蛇变子程序
- {
- switch(SSS)
- {
- case 1:
- if(STY>0){ //大于0是要判断的,因为下面HUANCUN[STY-1]
- if((HUANCUN[STY-1]&STX)==0) //判断下一个蛇坐标是否是灭的
- STY--; //蛇头坐标改变
- else{
- if(((STY-1)==GCUNX)&&(STX==GCUNY)){ //否则,判断该点是否是糖果点
- STY--; //蛇头坐标改变
- GUO=0; //糖果变量清零
- }else
- TR0=0; //定时器关闭
- return; //跳出
- }
- }else{
- TR0=0;
- return;
- }
- break;
- case 2:
- if((HUANCUN[STY]&(STX>>1))==0)
- STX>>=1;
- else{
- if((STY==GCUNX)&&((STX>>1)==GCUNY)){
- STX>>=1; //蛇头横坐标右移一位
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- case 3:
- if((HUANCUN[STY+1]&STX)==0)
- STY++; //蛇头纵坐标减一位
- else{
- if(((STY+1)==GCUNX)&&(STX==GCUNY)){
- STY++;
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- case 4:
- if((HUANCUN[STY]&(STX<<1))==0)
- STX<<=1;
- else{
- if((STY==GCUNX)&&((STX<<1)==GCUNY)){
- STX<<=1;
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- }
- if((STX!=0)&&(STY>=0)&&(STY<16)){ //如果蛇头没超出边界
- HUANCUN[STY]|=STX; //让蛇头亮起
- HUANCUN[SWY]&=(~SWX); //让蛇尾灭掉
- switch(ZZS[0])
- {
- case 1:
- if(SWY!=ZZD[0])
- SWY--;
- else ZZ_X();
- break;
- case 2:
- if(SWX!=ZZD[0])
- SWX>>=1;
- else ZZ_X();
- break;
- case 3:
- if(SWY!=ZZD[0])
- SWY++;
- else ZZ_X();
- break;
- case 4:
- if(SWX!=ZZD[0])
- SWX<<=1;
- else ZZ_X();
- break;
- }
- }else{
- TR0=0;
- // return;
- }
- }
- //=================================================================================================================================================================
复制代码
- #include "anjian.h"
- extern uchar cus,STY,SSS;
- extern uint STX;
- extern uchar idata ZZS[16];
- extern uint idata ZZD[16];
- //=================================================================================================================================================================
- //思维说明:4个按键控制蛇的方向,当蛇往一个方向移动的时候,控制蛇在这一线上的移动方向的两个按键会失效,只有两个键有用
- //程序说明:SSS表示蛇方向的一个变量,有4个方向,取值范围是1~4
- // 当蛇的方向改变是,存储转折点的横或纵坐标放在数组ZZD[],存储转折点的方向存在ZZS[]
- // 蛇尾是跟着存储起来的转折点转向的,一个点的坐标用横坐标和纵坐标两个坐标表示的,这里为了节省存储空间,
- // 当蛇在横向上移动的时候,可以只存横坐标,为什么存横坐标?因为这个时候纵坐标不变
- // 当蛇在纵向上移动的时候,可以只存纵坐标
- //=================================================================================================================================================================
- void AN_J() //按键子程序
- {
- static uchar a=1,b=1,c=1,d=1; //定义4个方向键的状态变量
- uchar i;
- cus=SSS; //保存蛇的方向
- if(SHANG!=a){ //比较按键当前状态和前一个状态是否一致
- if(a==1){ //前一个状态是否是高电平
- if((SSS!=1)&&(SSS!=3)){ //蛇的状态是左右的时候,才生效
- SSS=1;
- }
- }
- a=SHANG; //锁住,直到下一次按键按下才会再进来
- }
- if(YOU!=b){
- if(b==1){
- if((SSS!=2)&&(SSS!=4)){
- SSS=2;
- }
- }
- b=YOU;
- }
- if(XIA!=c){
- if(c==1){
- if((SSS!=1)&&(SSS!=3)){
- SSS=3;
- }
- }
- c=XIA;
- }
- if(ZUO!=d){
- if(d==1){
- if((SSS!=2)&&(SSS!=4)){
- SSS=4;
- }
- }
- d=ZUO;
- }
- if(cus!=SSS){ //如果蛇的方向改变了
- for(i=0;i<16;i++){ //从第一个转折点开始判断
- if(ZZD[i]==0xffff){ //如果转折点是0xffff,说明后面没有转折点了
- ZZS[i+1]=SSS; //把当前蛇的方向存储起来
- if((cus==1)||(cus==3)){ //如果蛇前一个方向是上下
- ZZD[i]=STY; //把转折点的纵坐标存储起来
- }else ZZD[i]=STX; //否则,存横坐标
- break; //跳出
- }
- }
- }
- }
- //=================================================================================================================================================================
复制代码
原理图: 无
仿真: 无
代码:
贪吃蛇.rar
(58.42 KB, 下载次数: 101)
|