这是修改后的代码,为什么程序会卡住呢??? |
#include"reg52.h" #include "intrins.h" sbit RS=P2^6; //并行的指令/数据选择信号, H数据, L命令 sbit RW=P2^5; //并行读写选择信号, H读, L写 sbit E=P2^7; //并行使能端, H有效, L无效 sbit PSB=P3^2; //并/串接口选择, H并,L串 sbit RET=P3^4; //复位, L有效 sbit kxuanze=P3^1; sbit kenter=P3^3; #define LcdData P0 #define N 25 unsigned char moshiceshi; unsigned char flag,s1num; #define OS_LONG_EYK_EN 1 //如果应用中需要处理长按键动作,则定义为1,否则定义为0(如果应用中不需要处理长按动作,则建议定义为0,以节省代码空间) #define GPIO_KEY P1 unsigned char KeyValue;//用来存放读取到的键值 unsigned char code DIG_CODE[17]={ 0,0,0,0,0,5,0,0,6,0,4,0,0,3,0,0,0}; #define uchar unsigned char #define uint unsigned int static unsigned long Seed = 1; #define A 48271L #define M 2147483647L #define Q (M / A) #define R (M % A) struct Food { unsigned char x; unsigned char y; unsigned char yes; }food;//食物结构体 struct Snake { unsigned char x[N]; unsigned char y[N]; unsigned char node; unsigned char direction; unsigned char life; }snake;//蛇结构体 unsigned char Flag_gamedisplay=0; unsigned char Score=0; unsigned char Speed_tiaosu; //speed越大,速度越慢 unsigned char KeyBuffer=0; #define FUNC 1 //(P3^1)表示级别 #define UP 2 //(P3^3)表示左 #define DOWN 3 //(P3^5)表示右 #define LEFT 4 //(P3^4)表示下 #define RIGHT 5 //(P3^2)表示上 #define PASSSCORE 20 //预定义过关成绩 void Lcd_WriteData(unsigned char); unsigned char Check_Busy(void); unsigned char Lcd_ReadData(void); void Lcd_WriteCmd(unsigned char); void Lcd_PutPixel(unsigned char,unsigned char,unsigned char); //unsigned char Lcd_ReadPixel(unsigned char,unsigned char); void Lcd_HoriLine(unsigned char,unsigned char,unsigned char Length,unsigned char Color); void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color); void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color); void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color); void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color); void Lcd_Clear(unsigned char); void Lcd_WriteStr(unsigned char,unsigned char,unsigned char *); void Lcd_Reset(void); unsigned char OSReadKey(void); unsigned char KeyDown(); //检测按键函数 void Delay10ms(void); //延时10ms double Random(void); void InitRandom(unsigned long InitVal); void InitCpu(void); void DrawBoardf(); void Drawboardt(void); void PrintScore(void); void PrintSpeed(void); void GameOver(void); void Gameplayt(void); void GamePlayf(void); void delay(unsigned int t); void delayus(unsigned int j); void lcd_st(unsigned char *st); void scankey(void); void moshi(void); void zhujiemian(void); unsigned char moshi1(void); unsigned char moshi2(void); void speed(void); void Speed1(void); void Speed2(void); void Speed3(void); void Speed4(void); void game(void); void main() { Lcd_Reset(); Lcd_WriteStr(0,0,"Welcome"); Lcd_WriteStr(2,2,"贪吃蛇"); delay(20000000); zhujiemian(); while(1) { scankey(); } } /************* 测试LCD是否处于忙状态 如果忙则返回0x80,否则返回0 **************/ unsigned char Lcd_CheckBusy(void) { unsigned char Busy; LcdData=0xff; RS=0; RW=1; E=1; _nop_(); Busy=LcdData&0x80; E=0; return Busy; } /********************************* 向LCD写入字节数据 **********************************/ void Lcd_WriteData(unsigned char LCD_Data) { while(Lcd_CheckBusy()); RS=1; RW=0; E=0; _nop_(); _nop_(); LcdData=LCD_Data; E=1; _nop_(); _nop_(); E=0; } /*********************************** 从LCD中读出数据 ************************************/ unsigned char Lcd_ReadData(void) { unsigned char Temp; //while(Lcd_CheckBusy()); LcdData=0xff; RS=1; RW=1; E=1; _nop_(); Temp=LcdData; E=0; return Temp; } /************************************* 向LCD中写入指令代码 **************************************/ void Lcd_WriteCmd(unsigned char CmdCode) { while(Lcd_CheckBusy()); RS=0; RW=0; E=0; _nop_(); _nop_(); LcdData=CmdCode; _nop_(); _nop_(); E=1; _nop_(); _nop_(); E=0; } void set_postion(unsigned char x,unsigned char y) { unsigned char postion; switch(x) { case 0:x=0x80;break; case 1:x=0x90;break; case 2:x=0x88;break; case 3:x=0x98;break; default:break; } postion=x+y; Lcd_WriteCmd(postion); } /************************************* 向LCD指定起始位置写入一个字符串 *************************************/ void Lcd_WriteStr(unsigned char x,unsigned char y,unsigned char *Str) { if((y>3)||(x>7)) return;//如果指定位置不在显示区域内,则不做任何写入直接返回 EA=0; switch(y) { case 0: Lcd_WriteCmd(0x80+x); break; case 1: Lcd_WriteCmd(0x90+x); break; case 2: Lcd_WriteCmd(0x88+x); break; case 3: Lcd_WriteCmd(0x98+x); break; } while(*Str>0) { Lcd_WriteData(*Str); Str++; } EA=1; } /************************************** 为加速逻辑运算而设置的掩码表,这是以牺牲空间而换取时间的办法 ***************************************/ code unsigned int MaskTab[]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000}; /*************************************** 向LCD指定坐标写入一个象素,象素颜色有两种,0代表白(无显示),1代表黑(有显示) ****************************************/ void Lcd_PutPixel(unsigned char x,unsigned char y,unsigned char Color) { unsigned char z,w; unsigned int Temp; if(x>=128||y>=64) return; Color=Color%2; w=15-x%16;//确定对这个字的第多少位进行操作 x=x/16;//确定为一行上的第几字 if(y<32) //如果为上页 z=0x80; else //否则如果为下页 z=0x88; y=y%32; EA=0; Lcd_WriteCmd(0x36); Lcd_WriteCmd(y+0x80); //行地址 Lcd_WriteCmd(x+z); //列地址 Temp=Lcd_ReadData();//先空读一次 Temp=(unsigned int)Lcd_ReadData()<<8;//再读出高8位 Temp|=(unsigned int)Lcd_ReadData();//再读出低8位 EA=1; if(Color==1) //如果写入颜色为1 Temp|=MaskTab[w];//在此处查表实现加速 else //如果写入颜色为0 Temp&=~MaskTab[w];//在此处查表实现加速 EA=0; Lcd_WriteCmd(y+0x80); //行地址 Lcd_WriteCmd(x+z); //列地址 Lcd_WriteData(Temp>>8);//先写入高8位,再写入低8位 Lcd_WriteData(Temp&0x00ff); Lcd_WriteCmd(0x30); EA=1; } /*************************************** 向LCD指定位置画一条长度为Length的指定颜色的水平线 ****************************************/ void Lcd_HoriLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color) { unsigned char i; if(Length==0) return; for(i=0;i<Length;i++) { Lcd_PutPixel(x+i,y,Color); } } /*************************************** 向LCD指定位置画一条长度为Length的指定颜色的垂直线 ****************************************/ void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color) { unsigned char i; if(Length==0) return; for(i=0;i<Length;i++) { Lcd_PutPixel(x,y+i,Color); } } /******************************************* 向LCD指定起始坐标和结束坐标之间画一条指定颜色的直线 void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color) { unsigned int x,y; unsigned int d_x,d_y;//d_x=x2-x1;d_y=y2-y1; int err=0; unsigned char temp=0; if(y2<y1) { x=x1; y=y1; x1=x2; y1=y2; x2=x; y2=y; } d_y=y2-y1; if (d_y==0) { if (x1>x2) { x=x1; x1=x2; x2=x; } for (x=x1;x<=x2;x++) Lcd_PutPixel(x,y1,Color); } else { if(x2>=x1) { temp=1; d_x=x2-x1; } else d_x=x1-x2; x=x1; y=y1; Lcd_PutPixel(x,y,1); if(temp&&(d_y<=d_x)) while(x!=x2) { if(err<0) { x=x+1; err=err+(y2-y); } else { x=x+1; y=y+1; err=err+(y2-y)-(x2-x); } Lcd_PutPixel(x,y,Color); } else if(temp&&(d_y>d_x)) while(y!=y2) { d_x=x2-x; d_y=y2-y; if(err<0) { x=x+1; y=y+1; err=err+d_y-d_x; } else { y=y+1; err=err-d_x; } Lcd_PutPixel(x,y,Color); } else if(!temp&&(d_y<=d_x)) while(x!=x2) { d_x=x-x2; d_y=y2-y; if(err<0) { x=x-1; err=err+d_y; } else { x=x-1; y=y+1; err=err+d_y-d_x; } Lcd_PutPixel(x,y,Color); } else if(!temp &&(d_y>d_x)) while(y!=y2) { d_x=x-x2; d_y=y2-y; if(err<0) { x=x-1; y=y+1; err=err+d_y-d_x; } else { y=y+1; err=err-d_x; } Lcd_PutPixel(x,y,Color); } } } ********************************************/ /******************************************* 向LCD指定左上角坐标和右下角坐标画一个指定颜色的矩形 ********************************************/ void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color) { unsigned char Temp; if(x0>x1) { Temp=x0; x0=x1; x1=Temp; } if(y0>y1) { Temp=y0; y0=y1; y1=Temp; } Lcd_VertLine(x0,y0,y1-y0+1,Color); Lcd_VertLine(x1,y0,y1-y0+1,Color); Lcd_HoriLine(x0,y0,x1-x0+1,Color); Lcd_HoriLine(x0,y1,x1-x0+1,Color); } /**************************************** 对称法画圆的8个镜像点 void CircleDot(unsigned char x,unsigned char y,char xx,char yy,unsigned char Color)//内部函数,对称法画圆的8个镜像点 { Lcd_PutPixel((x+yy),(y+xx),Color);//第 1 个 8 分圆 Lcd_PutPixel((x+xx),(y+yy),Color);//第 2 个 8 分圆 Lcd_PutPixel((x-xx),(y+yy),Color);//第 3 个 8 分圆 Lcd_PutPixel((x-yy),(y+xx),Color);//第 4 个 8 分圆 Lcd_PutPixel((x-yy),(y-xx),Color);//第 5 个 8 分圆 Lcd_PutPixel((x-xx),(y-yy),Color);//第 6 个 8 分圆 Lcd_PutPixel((x+xx),(y-yy),Color);//第 7 个 8 分圆 Lcd_PutPixel((x+yy),(y-xx),Color);//第 8 个 8 分圆 } *****************************************/ /****************************************** 向LCD指定圆心坐标画一个半径为r的指定颜色的圆 void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color)//中点法画圆 {//中点法画圆 unsigned char xx,yy; char deltax,deltay,d; xx=0; yy=r; deltax=3; deltay=2-r-r; d=1-r; CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点 while (xx<yy) { if (d<0) { d+=deltax; deltax+=2; xx++; } else { d+=deltax+deltay; deltax+=2; deltay+=2; xx++; yy--; } CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点 } } *******************************************/ /***************************************** 清除Lcd全屏,如果清除模式Mode为0,则为全屏清除为颜色0(无任何显示) 否则为全屏清除为颜色1(全屏填充显示) ******************************************/ void Lcd_Clear(unsigned char Mode) { unsigned char x,y,ii; unsigned char Temp; if(Mode%2==0) Temp=0x00; else Temp=0xff; Lcd_WriteCmd(0x36);//扩充指令 绘图显示 for(ii=0;ii<9;ii+=8) for(y=0;y<0x20;y++) for(x=0;x<8;x++) { EA=0; Lcd_WriteCmd(y+0x80); //行地址 Lcd_WriteCmd(x+0x80+ii); //列地址 Lcd_WriteData(Temp); //写数据 D15-D8 Lcd_WriteData(Temp); //写数据 D7-D0 EA=1; } Lcd_WriteCmd(0x30); } /**************************************** LCD初始化 *****************************************/ void Lcd_Reset(void) { PSB=1; Lcd_WriteCmd(0x30); //选择基本指令集 delay(5); Lcd_WriteCmd(0x0c); //开显示(无游标、不反白) delay(5); Lcd_WriteCmd(0x01); //清除显示,并且设定地址指针为00H delay(5); Lcd_WriteCmd(0x06); //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位 } void Delay10ms(void) //误差 0us { unsigned char a,b,c; for(c=1;c>0;c--) for(b=38;b>0;b--) for(a=130;a>0;a--); } void delay(unsigned int t) { unsigned int i,j; for(i=0;i<t;i++) for(j=0;j<10;j++); } /*********************************************** 按键驱动扫描 扫描一次键盘以获得按键句柄 注:交OSReadKey()函数调用 ***********************************************/ unsigned char KeyDown(void) { char a=0; GPIO_KEY=0x0f; if(GPIO_KEY!=0x0f)//读取按键是否按下 { Delay10ms();//延时10ms进行消抖 if(GPIO_KEY!=0x0f)//再次检测键盘是否按下 { //测试列 GPIO_KEY=0X0F; switch(GPIO_KEY) { case(0X07): KeyValue=0;break; case(0X0b): KeyValue=1;break; case(0X0d): KeyValue=2;break; case(0X0e): KeyValue=3;break; } //测试行 GPIO_KEY=0XF0; switch(GPIO_KEY) { case(0X70): KeyValue=KeyValue;break; case(0Xb0): KeyValue=KeyValue+4;break; case(0Xd0): KeyValue=KeyValue+8;break; case(0Xe0): KeyValue=KeyValue+12;break; } while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测 { Delay10ms(); a++; } } } return KeyValue; } /********************************************** 功能说明:读取按键动作 入口参数:无 出口参数:返回按键动作 注意: 没有按键动作,则返回0, 使用矩阵按键:向上S12;向下S6;向左S12;向右S9; ***********************************************/ unsigned char OSReadKey(void) { static unsigned char KeyEventCnt=0; static unsigned char KeySampleCnt=0; static unsigned char KeyBuffer=0; #define SHORT_ON_DITHERING_COUNTER 3//定义短按按下去抖时间 #define SHORT_OFF_DITHERING_COUNTER 3//定义短按松开去抖时间,一般与短按按下去抖时间相同 #if OS_LONG_EYK_EN>0 static unsigned int LongKeySampleCnt=0; #define LONG_ON_DITHERING_COUNTER 250//定义长按按下确认需要的时间,如果是每1MS调用一次OSReadKey(),则1000意味着这个时间为1S #define LONG_OFF_DITHERING_COUNTER 3//定义长按松开去抖时间,一般和短按去抖时间相同 #endif unsigned char KeyTemp; KeyTemp=DIG_CODE[KeyDown()]; switch(KeyEventCnt) { case 0: if(KeyTemp!=0) { KeySampleCnt=0; KeyBuffer=KeyTemp; KeyEventCnt=1; } return 0;//no key on,return 0 break; #if OS_LONG_EYK_EN>0 case 1: if(KeyTemp!=KeyBuffer) { KeyEventCnt=0; return 0;//is dithering,return 0 } else { if(++KeySampleCnt>SHORT_ON_DITHERING_COUNTER) { KeySampleCnt=0; KeyEventCnt=2; LongKeySampleCnt=0; return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1 } else return 0;//not sure that key on,return 0 } break; case 2: if(++LongKeySampleCnt>LONG_ON_DITHERING_COUNTER) { KeySampleCnt=0; KeyEventCnt=3; return ((KeyBuffer-1)<<2)+2; //sure that key long on,return (KeyBuffer-1)<<2+2 } else { if(KeyTemp!=KeyBuffer) { if(++KeySampleCnt>SHORT_OFF_DITHERING_COUNTER) { KeyEventCnt=0; return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3 } else return 0; } else { KeySampleCnt=0; return 0; } } break; case 3: if(KeyTemp!=KeyBuffer) { if(++KeySampleCnt>LONG_OFF_DITHERING_COUNTER) { KeyEventCnt=0; return ((KeyBuffer-1)<<2)+4; //after long key on turn to off,(KeyBuffer-1)<<2+4 } else return 0; } else { KeySampleCnt=0; return 0; } break; #else case 1: if(KeyTemp!=KeyBuffer) { KeyEventCnt=0; return 0;//is dithering,return 0 } else { if(++KeySampleCnt>=SHORT_ON_DITHERING_COUNTER) { KeySampleCnt=0; KeyEventCnt=2; return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1 } else return 0;//not sure that key on,return 0 } break; case 2: if(KeyTemp!=KeyBuffer) { if(++KeySampleCnt>=SHORT_OFF_DITHERING_COUNTER) { KeyEventCnt=0; return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3 } else return 0; } else { KeySampleCnt=0; return 0; } break; #endif default:break; } return 0; } /************************************ 伪随机数发生器 *************************************/ double Random(void) { long TmpSeed; TmpSeed=A*(Seed%Q)-R*(Seed/Q); if(TmpSeed>=0) Seed=TmpSeed; else Seed=TmpSeed+M; return (double)Seed/M; } /************************************** 为伪随机数发生器播种 ***************************************/ void InitRandom(unsigned long InitVal) { Seed=InitVal; } /********************************* 初始化MPU **********************************/ void InitCpu(void) { TMOD=0x01; TH0=0; TL0=0; TR0=1; ET0=1; EA=1; } void Timer0Int(void) interrupt 1 { switch(OSReadKey()) { case 5: KeyBuffer=FUNC; //表示级别 break; case 21: KeyBuffer=DOWN; //表示右 break; case 13: KeyBuffer=UP; //表示左 break; case 9: KeyBuffer=RIGHT; //表示上 break; case 17: KeyBuffer=LEFT; //表示下 break; default: break; } } /****************************** 画墙壁,初始化界面 *******************************/ void DrawBoardf() { unsigned char n; for(n=0;n<31;n++) { Lcd_Rectangle(3*n,0,3*n+2,2,1); Lcd_Rectangle(3*n,60,3*n+2,62,1); } for(n=0;n<21;n++) { Lcd_Rectangle(0,3*n,2,3*n+2,1); Lcd_Rectangle(90,3*n,92,3*n+2,1); } Lcd_HoriLine(93,31,35,1); Lcd_HoriLine(93,63,35,1); } void Drawboardt(void) { unsigned char n; for(n=0;n<21;n++) { Lcd_Rectangle(0,3*n,2,3*n+2,1); Lcd_Rectangle(90,3*n,92,3*n+2,1); } Lcd_HoriLine(93,31,35,1); Lcd_HoriLine(93,63,35,1); } /*************************** 打印成绩 ****************************/ void PrintScore(void) { unsigned char Str[3]; Lcd_WriteStr(6,0,"成绩"); Str[0]=(Score/10)|0x30;//十位 Str[1]=(Score%10)|0x30;//个位 Str[2]=0; Lcd_WriteStr(7,1,Str); } /******************************** 打印速度级别 *********************************/ void PrintSpeed(void) { unsigned char Str[2]; Lcd_WriteStr(6,2,"级别"); Str[0]=Speed_tiaosu|0x30; Str[1]=0; Lcd_WriteStr(7,3,Str); } /*********************************** 游戏结束处理 ************************************/ void GameOver(void) { unsigned char n; Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐出食物 for(n=1;n<snake.node;n++) { Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,0);//消隐食物,蛇头已到墙壁内,故不用消去 } if(snake.life==0)//如果蛇还活着 Lcd_WriteStr(2,1,"过关"); else //如果蛇死了 Lcd_WriteStr(2,1,"输了"); Lcd_WriteStr(1,2,"游戏结束"); } /******************************** 游戏的具体过程,也是贪吃蛇算法的关键部分 *********************************/ void GamePlayf(void) { unsigned char n; InitRandom(TL0); food.yes=1;//1表示需要出现新事物,0表示已经存在食物尚未吃掉 snake.life=0;//表示蛇还活着 snake.direction=DOWN; snake.x[0]=6;snake.y[0]=6; snake.x[1]=3;snake.y[1]=6; snake.node=2; PrintScore(); PrintSpeed(); while(1) { if(food.yes==1) { while(1) { food.x=Random()*85+3; food.y=Random()*55+3;//获得随机数 while(food.x%3!=0) food.x++; while(food.y%3!=0) food.y++; for(n=0;n<snake.node;n++)//判断产生的食物坐标是否和蛇身重合 { if((food.x==snake.x[n])&&(food.y==snake.y[n])) break; } if(n==snake.node) { food.yes=0; break;//产生有效的食物坐标 } } } if(food.yes==0) { Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1); } for(n=snake.node-1;n>0;n--) { snake.x[n]=snake.x[n-1]; snake.y[n]=snake.y[n-1]; } switch(snake.direction) { case DOWN:snake.x[0]+=3;break; case UP:snake.x[0]-=3;break; case RIGHT:snake.y[0]-=3;break; case LEFT:snake.y[0]+=3;break; default:break; } for(n=3;n<snake.node;n++)//从第三节开始判断蛇头是否咬到自己 { if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0]) { GameOver(); snake.life=1; break; } } if(snake.x[0]<3||snake.x[0]>=90||snake.y[0]<3||snake.y[0]>=60)//判蛇头是否撞到墙壁 { GameOver(); snake.life=1; } if(snake.life==1) break;//蛇死,则跳出while(1)循环 if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物 { Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐食物 snake.x[snake.node]=200; snake.y[snake.node]=200;//产生蛇新的节坐标先放在看不见的位置 snake.node++;//蛇节数加1 food.yes=1;//食物标志置1 if(++Score>=PASSSCORE) { PrintScore(); GameOver(); break; } PrintScore(); } for(n=0;n<snake.node;n++) { Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); }//根据蛇的节数画出蛇 delay(Speed_tiaosu*1000); //调速 delay(Speed_tiaosu*1000); Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0); switch(KeyBuffer) { case FUNC: KeyBuffer=0; if(++Speed_tiaosu>=10) Speed_tiaosu=1; PrintSpeed(); break; case DOWN: KeyBuffer=0; if(snake.direction!=UP) snake.direction=DOWN; break; case UP: KeyBuffer=0; if(snake.direction!=DOWN) snake.direction=UP; break; case RIGHT: KeyBuffer=0; if(snake.direction!=LEFT) snake.direction=RIGHT; break; case LEFT: KeyBuffer=0; if(snake.direction!=RIGHT) snake.direction=LEFT; break; default: break; } } } void Gameplayt(void) { unsigned char n; InitRandom(TL0); food.yes=1;//1表示需要出现新事物,0表示已经存在食物尚未吃掉 snake.life=0;//表示蛇还活着 snake.direction=DOWN; snake.x[0]=6;snake.y[0]=6; snake.x[1]=3;snake.y[1]=6; snake.node=2; PrintScore(); PrintSpeed(); while(1) { if(food.yes==1) { while(1) { food.x=Random()*85+3; food.y=Random()*55+3;//获得随机数 while(food.x%3!=0) food.x++; while(food.y%3!=0) food.y++; for(n=0;n<snake.node;n++)//判断产生的食物坐标是否和蛇身重合 { if((food.x==snake.x[n])&&(food.y==snake.y[n])) break; } if(n==snake.node) { food.yes=0; break;//产生有效的食物坐标 } } } if(food.yes==0) { Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1); } for(n=snake.node-1;n>0;n--) { snake.x[n]=snake.x[n-1]; snake.y[n]=snake.y[n-1]; } switch(snake.direction) { case DOWN:snake.x[0]+=3;break; case UP:snake.x[0]-=3;break; case RIGHT:snake.y[0]-=3;break; case LEFT:snake.y[0]+=3;break; default:break; } for(n=3;n<snake.node;n++)//从第三节开始判断蛇头是否咬到自己 { if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0]) { GameOver(); snake.life=1; break; } } if(snake.x[0]<3||snake.x[0]>=90)//判蛇头是否撞到墙壁 { GameOver(); snake.life=1; } if(snake.life==1) break;//蛇死,则跳出while(1)循环 if(snake.y[0]<3||snake.y[0]>=60) { if(snake.y[0]<3) snake.y[0]=59; // for(n=0;n<snake.node;n++) // { // Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); // }//根据蛇的节数画出蛇 if(snake.y[0]>=60) snake.y[0]=3; // for(n=0;n<snake.node;n++) // { // Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); // }//根据蛇的节数画出蛇 // } if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物 { Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐食物 snake.x[snake.node]=200; snake.y[snake.node]=200;//产生蛇新的节坐标先放在看不见的位置 snake.node++;//蛇节数加1 food.yes=1;//食物标志置1 if(++Score>=PASSSCORE) { PrintScore(); GameOver(); break; } PrintScore(); } for(n=0;n<snake.node;n++) { Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1); }//根据蛇的节数画出蛇 delay(Speed_tiaosu*1000); //调速 delay(Speed_tiaosu*1000); Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0); switch(KeyBuffer) { case FUNC: KeyBuffer=0; if(++Speed_tiaosu>=10) Speed_tiaosu=1; PrintSpeed(); break; case DOWN: KeyBuffer=0; if(snake.direction!=UP) snake.direction=DOWN; break; case UP: KeyBuffer=0; if(snake.direction!=DOWN) snake.direction=UP; break; case RIGHT: KeyBuffer=0; if(snake.direction!=LEFT) snake.direction=RIGHT; break; case LEFT: KeyBuffer=0; if(snake.direction!=RIGHT) snake.direction=LEFT; break; default: break; } } } void scankey(void) { } void speed(void) { Lcd_WriteStr(0,1,"Speed1"); Lcd_WriteStr(1,1,"Speed2"); Lcd_WriteStr(2,1,"Speed3"); Lcd_WriteStr(3,1,"Speed4"); } void moshi(void) { Lcd_WriteStr(0,1,"mosho1"); Lcd_WriteStr(1,1,"moshi2"); } void zhujiemian(void) { Lcd_WriteCmd(0x01); Lcd_WriteStr(0,0,"开始游戏"); Lcd_WriteStr(0,1,"速度选择"); Lcd_WriteStr(0,2,"模式设置"); } unsigned char moshi1() { moshiceshi=1; DrawBoardf(); GamePlayf(); return moshiceshi; zhujiemian(); } unsigned char moshi2() { moshiceshi=2; Drawboardt(); Gameplayt(); return moshiceshi; zhujiemian(); } void Speed1(void) { unsigned char Speed_tiaosu=1; zhujiemian(); } void Speed2(void) { unsigned char Speed_tiaosu=2; zhujiemian(); } void Speed3(void) { unsigned char Speed_tiaosu=3; zhujiemian(); } void Speed4(void) { unsigned char Speed_tiaosu=4; zhujiemian(); } void game(void) { InitCpu();//初始化CPU Lcd_Reset(); //初始化LCD屏 delay(5000); Lcd_Clear(0);//清屏 switch(Speed_tiaosu) { case '1': Speed1(); break; case '2': Speed2(); break; case '3': Speed3(); break; case '4': Speed4(); break; default: Speed4(); } switch(moshiceshi) { case '1': moshi1(); break; case '2': moshi2(); break; default: moshi1(); } GameOver();//游戏结束 } |
angmall 发表于 2018-8-14 18:15 大神,没有错了,但是单片机运行好像卡住了,我一直按复位键前面的部分功能才可能好用,后面的一直用不了,但我各功能分开检测得时候是都好用得 |
这个试试 #define OS_LONG_KEY_EN 1 |
angmall 发表于 2018-8-13 23:34 我加了还是那个错 |
少了这个 #define OS_LONG_EYK_EN 1 //如果应用中需要处理长按键动作,则定义为1,否则定义为0(如果应用中不需要处理长按动作,则建议定义为0,以节省代码空间) #define GPIO_KEY P1 |