找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2146|回复: 2
打印 上一主题 下一主题
收起左侧

贪吃蛇游戏程序分模块检测好用,合在一起单片机执行得时候功能不能实现

[复制链接]
回帖奖励 5 黑币 回复本帖可获得 5 黑币奖励! 每人限 1 次
跳转到指定楼层
楼主
ID:377361 发表于 2018-8-15 02:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
贪吃蛇游戏程序分模块检测好用,合在一起单片机执行得时候功能不能实现,一直按复位键部分功能可能好用,很多功能执行不了,谢谢

  1. #include"reg52.h"
  2. #include "intrins.h"
  3. sbit RS=P2^6; //并行的指令/数据选择信号, H数据, L命令
  4. sbit RW=P2^5; //并行读写选择信号, H读, L写
  5. sbit E=P2^7; //并行使能端, H有效, L无效
  6. sbit PSB=P3^2; //并/串接口选择, H并,L串
  7. sbit RET=P3^4; //复位, L有效
  8. sbit kxuanze=P3^1;
  9. sbit kenter=P3^3;
  10. #define  LcdData P0
  11. #define N 25
  12. unsigned char moshiceshi;
  13. unsigned char flag,s1num;
  14. #define OS_LONG_EYK_EN   1          //如果应用中需要处理长按键动作,则定义为1,否则定义为0(如果应用中不需要处理长按动作,则建议定义为0,以节省代码空间)
  15. #define GPIO_KEY P1
  16. unsigned char KeyValue;//用来存放读取到的键值
  17. unsigned char code DIG_CODE[17]={
  18. 0,0,0,0,0,5,0,0,6,0,4,0,0,3,0,0,0};
  19. #define uchar unsigned char
  20. #define uint unsigned int
  21. static unsigned long Seed = 1;
  22. #define A 48271L
  23. #define M 2147483647L
  24. #define Q (M / A)
  25. #define R (M % A)
  26. struct Food
  27. {
  28. unsigned char x;
  29. unsigned char y;
  30. unsigned char yes;
  31. }food;//食物结构体
  32. struct Snake
  33. {
  34. unsigned char x[N];
  35. unsigned char y[N];
  36. unsigned char node;
  37. unsigned char direction;
  38. unsigned char life;
  39. }snake;//蛇结构体
  40. unsigned char Flag_gamedisplay=0;
  41. unsigned char Score=0;
  42. unsigned char Speed_tiaosu;     //speed越大,速度越慢
  43. unsigned char KeyBuffer=0;
  44. #define FUNC 1       //(P3^1)表示级别
  45. #define UP 2       //(P3^3)表示左
  46. #define DOWN 3       //(P3^5)表示右
  47. #define LEFT 4       //(P3^4)表示下
  48. #define RIGHT 5       //(P3^2)表示上
  49. #define PASSSCORE 20     //预定义过关成绩

  50. void Lcd_WriteData(unsigned char);
  51. unsigned char Check_Busy(void);
  52. unsigned char Lcd_ReadData(void);
  53. void Lcd_WriteCmd(unsigned char);
  54. void Lcd_PutPixel(unsigned char,unsigned char,unsigned char);
  55. //unsigned char Lcd_ReadPixel(unsigned char,unsigned char);
  56. void Lcd_HoriLine(unsigned char,unsigned char,unsigned char Length,unsigned char Color);
  57. void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color);
  58. void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color);
  59. void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color);
  60. void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color);
  61. void Lcd_Clear(unsigned char);
  62. void Lcd_WriteStr(unsigned char,unsigned char,unsigned char *);
  63. void Lcd_Reset(void);
  64. unsigned char OSReadKey(void);
  65. unsigned char KeyDown();   //检测按键函数
  66. void Delay10ms(void);   //延时10ms
  67. double Random(void);
  68. void InitRandom(unsigned long InitVal);
  69. void InitCpu(void);
  70. void DrawBoardf();
  71. void Drawboardt(void);
  72. void PrintScore(void);
  73. void PrintSpeed(void);
  74. void GameOver(void);
  75. void Gameplayt(void);
  76. void GamePlayf(void);
  77. void delay(unsigned int t);
  78. void delayus(unsigned int j);
  79. void lcd_st(unsigned char *st);
  80. void scankey(void);
  81. void moshi(void);
  82. void zhujiemian(void);
  83. unsigned char moshi1(void);
  84. unsigned char moshi2(void);
  85. void speed(void);
  86. void Speed1(void);
  87. void Speed2(void);
  88. void Speed3(void);
  89. void Speed4(void);
  90. void game(void);

  91. void main()
  92. {
  93. Lcd_Reset();
  94. Lcd_WriteStr(0,0,"Welcome");
  95. Lcd_WriteStr(2,2,"贪吃蛇");
  96. delay(20000000);
  97. zhujiemian();
  98. while(1)
  99. {
  100.   scankey();
  101. }
  102. }

  103. /*************
  104. 测试LCD是否处于忙状态
  105. 如果忙则返回0x80,否则返回0
  106. **************/
  107. unsigned char Lcd_CheckBusy(void)
  108. {
  109.     unsigned char Busy;
  110.    LcdData=0xff;
  111.     RS=0;
  112.     RW=1;
  113.     E=1;
  114.     _nop_();
  115.     Busy=LcdData&0x80;
  116.     E=0;
  117.     return Busy;
  118. }
  119. /*********************************
  120. 向LCD写入字节数据
  121. **********************************/
  122. void Lcd_WriteData(unsigned char LCD_Data)
  123. {  
  124. while(Lcd_CheckBusy());
  125. RS=1;
  126. RW=0;
  127. E=0;
  128. _nop_();  
  129. _nop_();
  130. LcdData=LCD_Data;
  131. E=1;
  132. _nop_();
  133. _nop_();
  134. E=0;
  135. }
  136. /***********************************
  137. 从LCD中读出数据
  138. ************************************/
  139. unsigned char Lcd_ReadData(void)
  140. {
  141. unsigned char Temp;
  142. //while(Lcd_CheckBusy());
  143.   LcdData=0xff;
  144.   RS=1;
  145. RW=1;
  146. E=1;
  147. _nop_();
  148.     Temp=LcdData;
  149.     E=0;
  150.     return Temp;
  151. }
  152. /*************************************
  153. 向LCD中写入指令代码
  154. **************************************/
  155. void Lcd_WriteCmd(unsigned char CmdCode)
  156. {  
  157. while(Lcd_CheckBusy());
  158.     RS=0;
  159.     RW=0;
  160.     E=0;
  161.     _nop_();  
  162. _nop_();
  163.     LcdData=CmdCode;
  164.     _nop_();
  165. _nop_();
  166.     E=1;
  167.     _nop_();  
  168. _nop_();
  169.     E=0;
  170. }
  171. void set_postion(unsigned char x,unsigned char y)
  172. {
  173. unsigned char postion;
  174. switch(x)
  175. {
  176. case 0:x=0x80;break;   
  177. case 1:x=0x90;break;
  178. case 2:x=0x88;break;
  179. case 3:x=0x98;break;
  180. default:break;
  181. }
  182. postion=x+y;
  183. Lcd_WriteCmd(postion);
  184. }
  185. /*************************************
  186. 向LCD指定起始位置写入一个字符串
  187. *************************************/
  188. void Lcd_WriteStr(unsigned char x,unsigned char y,unsigned char *Str)
  189. {
  190. if((y>3)||(x>7))
  191.   return;//如果指定位置不在显示区域内,则不做任何写入直接返回
  192. EA=0;
  193. switch(y)
  194. {
  195.   case 0:
  196.     Lcd_WriteCmd(0x80+x);
  197.     break;
  198.   case 1:
  199.     Lcd_WriteCmd(0x90+x);
  200.     break;   
  201.   case 2:
  202.     Lcd_WriteCmd(0x88+x);
  203.     break;
  204.   case 3:
  205.     Lcd_WriteCmd(0x98+x);
  206.     break;
  207. }
  208. while(*Str>0)
  209. {  
  210.   Lcd_WriteData(*Str);
  211.     Str++;     
  212. }
  213. EA=1;
  214. }
  215. /**************************************
  216. 为加速逻辑运算而设置的掩码表,这是以牺牲空间而换取时间的办法
  217. ***************************************/
  218. code unsigned int MaskTab[]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
  219.         0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
  220. /***************************************
  221. 向LCD指定坐标写入一个象素,象素颜色有两种,0代表白(无显示),1代表黑(有显示)
  222. ****************************************/
  223. void Lcd_PutPixel(unsigned char x,unsigned char y,unsigned char Color)
  224. {
  225. unsigned char z,w;
  226. unsigned int Temp;
  227. if(x>=128||y>=64)
  228.   return;
  229. Color=Color%2;
  230. w=15-x%16;//确定对这个字的第多少位进行操作
  231. x=x/16;//确定为一行上的第几字
  232. if(y<32) //如果为上页
  233.   z=0x80;
  234. else     //否则如果为下页
  235.   z=0x88;
  236. y=y%32;
  237. EA=0;
  238. Lcd_WriteCmd(0x36);
  239. Lcd_WriteCmd(y+0x80);        //行地址
  240. Lcd_WriteCmd(x+z);     //列地址
  241. Temp=Lcd_ReadData();//先空读一次
  242. Temp=(unsigned int)Lcd_ReadData()<<8;//再读出高8位
  243. Temp|=(unsigned int)Lcd_ReadData();//再读出低8位
  244. EA=1;
  245. if(Color==1) //如果写入颜色为1
  246.   Temp|=MaskTab[w];//在此处查表实现加速
  247. else         //如果写入颜色为0
  248.   Temp&=~MaskTab[w];//在此处查表实现加速
  249. EA=0;
  250. Lcd_WriteCmd(y+0x80);        //行地址
  251. Lcd_WriteCmd(x+z);     //列地址
  252.     Lcd_WriteData(Temp>>8);//先写入高8位,再写入低8位
  253.     Lcd_WriteData(Temp&0x00ff);
  254. Lcd_WriteCmd(0x30);
  255. EA=1;
  256. }
  257. /***************************************
  258. 向LCD指定位置画一条长度为Length的指定颜色的水平线
  259. ****************************************/
  260. void Lcd_HoriLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
  261. {
  262. unsigned char i;
  263. if(Length==0)
  264.   return;
  265. for(i=0;i<Length;i++)
  266. {
  267.   Lcd_PutPixel(x+i,y,Color);
  268. }
  269. }
  270. /***************************************
  271. 向LCD指定位置画一条长度为Length的指定颜色的垂直线
  272. ****************************************/
  273. void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
  274. {
  275. unsigned char i;
  276. if(Length==0)
  277.   return;
  278. for(i=0;i<Length;i++)
  279. {
  280.   Lcd_PutPixel(x,y+i,Color);
  281. }
  282. }
  283. /*******************************************
  284. 向LCD指定起始坐标和结束坐标之间画一条指定颜色的直线
  285. void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color)
  286. {
  287. unsigned int x,y;
  288. unsigned int d_x,d_y;//d_x=x2-x1;d_y=y2-y1;
  289. int err=0;
  290. unsigned char temp=0;
  291. if(y2<y1)
  292. {
  293.   x=x1;
  294.   y=y1;
  295.   x1=x2;
  296.   y1=y2;
  297.   x2=x;
  298.   y2=y;
  299. }
  300. d_y=y2-y1;
  301. if (d_y==0)
  302. {
  303.   if (x1>x2)
  304.   {
  305.    x=x1;
  306.    x1=x2;
  307.    x2=x;
  308.   }
  309.   for (x=x1;x<=x2;x++)
  310.    Lcd_PutPixel(x,y1,Color);
  311. }
  312. else
  313. {
  314.   if(x2>=x1)
  315.   {
  316.    temp=1;
  317.    d_x=x2-x1;
  318.   }
  319.   else
  320.    d_x=x1-x2;
  321.   x=x1;
  322.   y=y1;
  323.   Lcd_PutPixel(x,y,1);
  324.   if(temp&&(d_y<=d_x))
  325.    while(x!=x2)
  326.    {
  327.     if(err<0)
  328.     {
  329.      x=x+1;
  330.      err=err+(y2-y);
  331.     }
  332.     else
  333.     {
  334.      x=x+1;
  335.      y=y+1;
  336.      err=err+(y2-y)-(x2-x);
  337.     }
  338.     Lcd_PutPixel(x,y,Color);
  339.    }
  340.   else if(temp&&(d_y>d_x))
  341.    while(y!=y2)
  342.    {
  343.     d_x=x2-x;
  344.     d_y=y2-y;
  345.     if(err<0)
  346.     {
  347.      x=x+1;
  348.      y=y+1;
  349.      err=err+d_y-d_x;
  350.     }
  351.     else
  352.     {
  353.      y=y+1;
  354.      err=err-d_x;
  355.     }
  356.     Lcd_PutPixel(x,y,Color);
  357.    }
  358.   else if(!temp&&(d_y<=d_x))
  359.    while(x!=x2)
  360.    {
  361.     d_x=x-x2;
  362.     d_y=y2-y;
  363.     if(err<0)
  364.     {
  365.      x=x-1;
  366.      err=err+d_y;
  367.     }
  368.     else
  369.     {
  370.      x=x-1;
  371.      y=y+1;
  372.      err=err+d_y-d_x;
  373.     }
  374.     Lcd_PutPixel(x,y,Color);
  375.    }
  376.   else if(!temp &&(d_y>d_x))
  377.    while(y!=y2)
  378.    {
  379.     d_x=x-x2;
  380.     d_y=y2-y;
  381.     if(err<0)
  382.     {
  383.      x=x-1;
  384.      y=y+1;
  385.      err=err+d_y-d_x;
  386.     }
  387.     else
  388.     {
  389.      y=y+1;
  390.      err=err-d_x;
  391.     }
  392.     Lcd_PutPixel(x,y,Color);
  393.    }
  394. }
  395. }
  396. ********************************************/
  397. /*******************************************
  398. 向LCD指定左上角坐标和右下角坐标画一个指定颜色的矩形
  399. ********************************************/
  400. void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color)
  401. {
  402. unsigned char Temp;
  403. if(x0>x1)
  404. {
  405.   Temp=x0;
  406.   x0=x1;
  407.   x1=Temp;
  408. }
  409. if(y0>y1)
  410. {
  411.   Temp=y0;
  412.   y0=y1;
  413.   y1=Temp;
  414. }
  415. Lcd_VertLine(x0,y0,y1-y0+1,Color);
  416. Lcd_VertLine(x1,y0,y1-y0+1,Color);
  417. Lcd_HoriLine(x0,y0,x1-x0+1,Color);
  418. Lcd_HoriLine(x0,y1,x1-x0+1,Color);
  419. }
  420. /****************************************
  421. 对称法画圆的8个镜像点
  422. void CircleDot(unsigned char x,unsigned char y,char xx,char yy,unsigned char Color)//内部函数,对称法画圆的8个镜像点
  423. {
  424. Lcd_PutPixel((x+yy),(y+xx),Color);//第 1 个 8 分圆
  425. Lcd_PutPixel((x+xx),(y+yy),Color);//第 2 个 8 分圆
  426. Lcd_PutPixel((x-xx),(y+yy),Color);//第 3 个 8 分圆
  427. Lcd_PutPixel((x-yy),(y+xx),Color);//第 4 个 8 分圆
  428. Lcd_PutPixel((x-yy),(y-xx),Color);//第 5 个 8 分圆
  429. Lcd_PutPixel((x-xx),(y-yy),Color);//第 6 个 8 分圆
  430. Lcd_PutPixel((x+xx),(y-yy),Color);//第 7 个 8 分圆
  431. Lcd_PutPixel((x+yy),(y-xx),Color);//第 8 个 8 分圆
  432. }
  433. *****************************************/
  434. /******************************************
  435. 向LCD指定圆心坐标画一个半径为r的指定颜色的圆
  436. void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color)//中点法画圆
  437. {//中点法画圆
  438. unsigned char xx,yy;
  439. char deltax,deltay,d;
  440. xx=0;
  441. yy=r;
  442. deltax=3;
  443. deltay=2-r-r;
  444. d=1-r;
  445. CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点
  446. while (xx<yy)
  447. {
  448.   if (d<0)
  449.   {
  450.    d+=deltax;
  451.    deltax+=2;
  452.    xx++;
  453.   }
  454.   else
  455.   {
  456.    d+=deltax+deltay;
  457.    deltax+=2;
  458.    deltay+=2;
  459.    xx++;
  460.    yy--;
  461.   }
  462.   CircleDot(x,y,xx,yy,Color);//对称法画圆的8个镜像点
  463. }
  464. }
  465. *******************************************/
  466. /*****************************************
  467. 清除Lcd全屏,如果清除模式Mode为0,则为全屏清除为颜色0(无任何显示)
  468. 否则为全屏清除为颜色1(全屏填充显示)
  469. ******************************************/
  470. void Lcd_Clear(unsigned char Mode)
  471. {
  472. unsigned char x,y,ii;
  473. unsigned char Temp;
  474. if(Mode%2==0)
  475.   Temp=0x00;
  476. else
  477.   Temp=0xff;
  478. Lcd_WriteCmd(0x36);//扩充指令 绘图显示
  479. for(ii=0;ii<9;ii+=8)   
  480.   for(y=0;y<0x20;y++)     
  481.    for(x=0;x<8;x++)
  482.    {  
  483.     EA=0;
  484.     Lcd_WriteCmd(y+0x80);        //行地址
  485.     Lcd_WriteCmd(x+0x80+ii);     //列地址     
  486.     Lcd_WriteData(Temp); //写数据 D15-D8
  487.     Lcd_WriteData(Temp); //写数据 D7-D0
  488.     EA=1;
  489.    }
  490. Lcd_WriteCmd(0x30);
  491. }
  492. /****************************************
  493. LCD初始化
  494. *****************************************/
  495. void Lcd_Reset(void)
  496. {  
  497. PSB=1;
  498. Lcd_WriteCmd(0x30);       //选择基本指令集
  499. delay(5);
  500. Lcd_WriteCmd(0x0c);       //开显示(无游标、不反白)
  501. delay(5);
  502. Lcd_WriteCmd(0x01);       //清除显示,并且设定地址指针为00H
  503. delay(5);
  504. Lcd_WriteCmd(0x06);       //指定在资料的读取及写入时,设定游标的移动方向及指定显示的移位
  505. }

  506. void Delay10ms(void)   //误差 0us
  507. {
  508.     unsigned char a,b,c;
  509.     for(c=1;c>0;c--)
  510.         for(b=38;b>0;b--)
  511.             for(a=130;a>0;a--);
  512. }
  513. void delay(unsigned int t)
  514. {  
  515. unsigned int i,j;
  516. for(i=0;i<t;i++)
  517. for(j=0;j<10;j++);   
  518. }
  519. /***********************************************
  520. 按键驱动扫描
  521. 扫描一次键盘以获得按键句柄
  522. 注:交OSReadKey()函数调用
  523. ***********************************************/
  524. unsigned char KeyDown(void)
  525. {
  526. char a=0;
  527. GPIO_KEY=0x0f;
  528. if(GPIO_KEY!=0x0f)//读取按键是否按下
  529. {
  530.   Delay10ms();//延时10ms进行消抖
  531.   if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
  532.   {
  533.    
  534.    //测试列
  535.    GPIO_KEY=0X0F;
  536.    switch(GPIO_KEY)
  537.    {
  538.     case(0X07): KeyValue=0;break;
  539.     case(0X0b): KeyValue=1;break;
  540.     case(0X0d): KeyValue=2;break;
  541.     case(0X0e): KeyValue=3;break;
  542.    }
  543.    //测试行
  544.    GPIO_KEY=0XF0;
  545.    switch(GPIO_KEY)
  546.    {
  547.     case(0X70): KeyValue=KeyValue;break;
  548.     case(0Xb0): KeyValue=KeyValue+4;break;
  549.     case(0Xd0): KeyValue=KeyValue+8;break;
  550.     case(0Xe0): KeyValue=KeyValue+12;break;
  551.    }
  552.    while((a<50)&&(GPIO_KEY!=0xf0))  //检测按键松手检测
  553.    {
  554.     Delay10ms();
  555.     a++;
  556.    }
  557.   }
  558. }

  559. return KeyValue;   
  560. }
  561. /**********************************************
  562. 功能说明:读取按键动作
  563. 入口参数:无
  564. 出口参数:返回按键动作
  565. 注意:
  566. 没有按键动作,则返回0,
  567. 使用矩阵按键:向上S12;向下S6;向左S12;向右S9;
  568. ***********************************************/
  569. unsigned char OSReadKey(void)
  570. {
  571. static unsigned char KeyEventCnt=0;
  572. static unsigned char KeySampleCnt=0;
  573. static unsigned char KeyBuffer=0;
  574. #define SHORT_ON_DITHERING_COUNTER 3//定义短按按下去抖时间
  575. #define SHORT_OFF_DITHERING_COUNTER 3//定义短按松开去抖时间,一般与短按按下去抖时间相同
  576. #if OS_LONG_EYK_EN>0
  577. static unsigned int LongKeySampleCnt=0;
  578. #define LONG_ON_DITHERING_COUNTER 250//定义长按按下确认需要的时间,如果是每1MS调用一次OSReadKey(),则1000意味着这个时间为1S
  579. #define LONG_OFF_DITHERING_COUNTER 3//定义长按松开去抖时间,一般和短按去抖时间相同
  580. #endif
  581. unsigned char KeyTemp;
  582. KeyTemp=DIG_CODE[KeyDown()];
  583. switch(KeyEventCnt)
  584. {
  585.   case 0:
  586.    if(KeyTemp!=0)
  587.    {
  588.     KeySampleCnt=0;
  589.     KeyBuffer=KeyTemp;
  590.     KeyEventCnt=1;     
  591.    }
  592.    return 0;//no key on,return 0
  593.    break;
  594.   
  595.   #if OS_LONG_EYK_EN>0
  596.   case 1:
  597.    if(KeyTemp!=KeyBuffer)
  598.    {
  599.     KeyEventCnt=0;
  600.     return 0;//is dithering,return 0
  601.    }
  602.    else
  603.    {
  604.     if(++KeySampleCnt>SHORT_ON_DITHERING_COUNTER)
  605.     {
  606.      KeySampleCnt=0;
  607.      KeyEventCnt=2;
  608.      LongKeySampleCnt=0;
  609.      return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
  610.     }
  611.     else
  612.      return 0;//not sure that key on,return 0                 
  613.    }
  614.    break;
  615.    
  616.   case 2:
  617.    if(++LongKeySampleCnt>LONG_ON_DITHERING_COUNTER)
  618.    {
  619.     KeySampleCnt=0;
  620.     KeyEventCnt=3;
  621.     return ((KeyBuffer-1)<<2)+2; //sure that key long on,return (KeyBuffer-1)<<2+2
  622.    }
  623.    else
  624.    {
  625.     if(KeyTemp!=KeyBuffer)
  626.     {
  627.      if(++KeySampleCnt>SHORT_OFF_DITHERING_COUNTER)
  628.      {
  629.       KeyEventCnt=0;
  630.       return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
  631.      }
  632.      else
  633.       return 0;
  634.     }
  635.     else
  636.     {
  637.      KeySampleCnt=0;
  638.      return 0;
  639.     }
  640.    }
  641.    break;
  642.   
  643.   case 3:
  644.    if(KeyTemp!=KeyBuffer)
  645.    {
  646.     if(++KeySampleCnt>LONG_OFF_DITHERING_COUNTER)
  647.     {
  648.      KeyEventCnt=0;
  649.      return ((KeyBuffer-1)<<2)+4;  //after long key on turn to off,(KeyBuffer-1)<<2+4
  650.     }
  651.     else
  652.      return 0;
  653.    }
  654.    else
  655.    {
  656.     KeySampleCnt=0;
  657.     return 0;
  658.    }
  659.    break;
  660.   
  661.   #else
  662.   case 1:
  663.    if(KeyTemp!=KeyBuffer)
  664.    {
  665.     KeyEventCnt=0;
  666.     return 0;//is dithering,return 0
  667.    }
  668.    else
  669.    {
  670.     if(++KeySampleCnt>=SHORT_ON_DITHERING_COUNTER)
  671.     {
  672.      KeySampleCnt=0;
  673.      KeyEventCnt=2;
  674.      return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
  675.     }
  676.     else
  677.      return 0;//not sure that key on,return 0                 
  678.    }
  679.    break;
  680.    
  681.   case 2:
  682.    if(KeyTemp!=KeyBuffer)
  683.    {
  684.     if(++KeySampleCnt>=SHORT_OFF_DITHERING_COUNTER)
  685.     {
  686.      KeyEventCnt=0;
  687.      return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
  688.     }
  689.     else
  690.      return 0;
  691.    }
  692.    else
  693.    {
  694.     KeySampleCnt=0;
  695.     return 0;
  696.    }
  697.    break;
  698.   #endif
  699.   default:break;
  700. }
  701. return 0;
  702. }

  703. /************************************
  704. 伪随机数发生器
  705. *************************************/
  706. double Random(void)
  707. {
  708. long TmpSeed;
  709. TmpSeed=A*(Seed%Q)-R*(Seed/Q);
  710. if(TmpSeed>=0)
  711. Seed=TmpSeed;
  712. else
  713. Seed=TmpSeed+M;
  714. return (double)Seed/M;
  715. }
  716. /**************************************
  717. 为伪随机数发生器播种
  718. ***************************************/
  719. void InitRandom(unsigned long InitVal)
  720. {
  721. Seed=InitVal;
  722. }
  723. /*********************************
  724. 初始化MPU
  725. **********************************/
  726. void InitCpu(void)
  727. {
  728. TMOD=0x01;
  729. TH0=0;
  730. TL0=0;
  731. TR0=1;
  732. ET0=1;
  733. EA=1;
  734. }
  735. void Timer0Int(void) interrupt 1
  736. {
  737. switch(OSReadKey())
  738. {
  739. case 5:
  740.    KeyBuffer=FUNC;        //表示级别
  741.    break;
  742. case 21:
  743.    KeyBuffer=DOWN;       //表示右
  744.    break;
  745. case 13:
  746.    KeyBuffer=UP;       //表示左
  747.     break;
  748. case 9:
  749.    KeyBuffer=RIGHT;      //表示上
  750.    break;
  751.     case 17:
  752.    KeyBuffer=LEFT;       //表示下
  753.    break;
  754. default:
  755.    break;
  756. }
  757. }
  758. /******************************
  759. 画墙壁,初始化界面
  760. *******************************/
  761. void DrawBoardf()
  762. {
  763. unsigned char n;
  764. for(n=0;n<31;n++)
  765.   {
  766.    Lcd_Rectangle(3*n,0,3*n+2,2,1);
  767.    Lcd_Rectangle(3*n,60,3*n+2,62,1);
  768.   }
  769. for(n=0;n<21;n++)
  770.   {
  771.    Lcd_Rectangle(0,3*n,2,3*n+2,1);
  772.    Lcd_Rectangle(90,3*n,92,3*n+2,1);  
  773.   }
  774. Lcd_HoriLine(93,31,35,1);
  775. Lcd_HoriLine(93,63,35,1);
  776. }
  777. void Drawboardt(void)
  778. {
  779. unsigned char n;
  780. for(n=0;n<21;n++)
  781. {
  782. Lcd_Rectangle(0,3*n,2,3*n+2,1);
  783. Lcd_Rectangle(90,3*n,92,3*n+2,1);  
  784. }
  785. Lcd_HoriLine(93,31,35,1);
  786. Lcd_HoriLine(93,63,35,1);
  787. }

  788. /***************************
  789. 打印成绩
  790. ****************************/
  791. void PrintScore(void)
  792. {
  793. unsigned char Str[3];        
  794. Lcd_WriteStr(6,0,"成绩");
  795. Str[0]=(Score/10)|0x30;//十位
  796. Str[1]=(Score%10)|0x30;//个位
  797. Str[2]=0;        
  798. Lcd_WriteStr(7,1,Str);
  799. }
  800. /********************************
  801. 打印速度级别
  802. *********************************/
  803. void PrintSpeed(void)
  804. {
  805. unsigned char Str[2];
  806. Lcd_WriteStr(6,2,"级别");
  807. Str[0]=Speed_tiaosu|0x30;
  808. Str[1]=0;
  809. Lcd_WriteStr(7,3,Str);
  810. }
  811. /***********************************
  812. 游戏结束处理
  813. ************************************/
  814. void GameOver(void)
  815. {
  816. unsigned char n;
  817. Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐出食物
  818. for(n=1;n<snake.node;n++)
  819. {
  820. Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,0);//消隐食物,蛇头已到墙壁内,故不用消去  
  821. }
  822. if(snake.life==0)//如果蛇还活着
  823. Lcd_WriteStr(2,1,"过关");
  824. else             //如果蛇死了
  825. Lcd_WriteStr(2,1,"输了");
  826. Lcd_WriteStr(1,2,"游戏结束");
  827. }
  828. /********************************
  829. 游戏的具体过程,也是贪吃蛇算法的关键部分
  830. *********************************/
  831. void GamePlayf(void)
  832. {
  833. unsigned char n;
  834. InitRandom(TL0);
  835. food.yes=1;//1表示需要出现新事物,0表示已经存在食物尚未吃掉
  836. snake.life=0;//表示蛇还活着
  837. snake.direction=DOWN;
  838. snake.x[0]=6;snake.y[0]=6;
  839. snake.x[1]=3;snake.y[1]=6;
  840. snake.node=2;
  841. PrintScore();
  842. PrintSpeed();
  843. while(1)
  844. {
  845. if(food.yes==1)
  846. {
  847.   while(1)
  848.   {
  849.    food.x=Random()*85+3;
  850.    food.y=Random()*55+3;//获得随机数
  851.    while(food.x%3!=0)
  852.     food.x++;
  853.    while(food.y%3!=0)
  854.     food.y++;
  855.       for(n=0;n<snake.node;n++)//判断产生的食物坐标是否和蛇身重合
  856.    {
  857.     if((food.x==snake.x[n])&&(food.y==snake.y[n]))
  858.      break;
  859.    }
  860.    if(n==snake.node)
  861.    {
  862.     food.yes=0;
  863.     break;//产生有效的食物坐标
  864.    }
  865.   }
  866. }
  867. if(food.yes==0)
  868. {
  869.   Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
  870. }
  871. for(n=snake.node-1;n>0;n--)
  872. {
  873.   snake.x[n]=snake.x[n-1];
  874.   snake.y[n]=snake.y[n-1];
  875. }
  876. switch(snake.direction)
  877. {
  878.   case DOWN:snake.x[0]+=3;break;
  879.   case UP:snake.x[0]-=3;break;
  880.   case RIGHT:snake.y[0]-=3;break;
  881.   case LEFT:snake.y[0]+=3;break;
  882.   default:break;
  883. }
  884. for(n=3;n<snake.node;n++)//从第三节开始判断蛇头是否咬到自己
  885. {
  886.   if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
  887.   {
  888.    GameOver();
  889.    snake.life=1;
  890.    break;
  891.   }
  892. }
  893. if(snake.x[0]<3||snake.x[0]>=90||snake.y[0]<3||snake.y[0]>=60)//判蛇头是否撞到墙壁
  894. {
  895.   GameOver();
  896.   snake.life=1;
  897. }
  898. if(snake.life==1)
  899.   break;//蛇死,则跳出while(1)循环
  900. if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
  901. {
  902.   Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐食物
  903.   snake.x[snake.node]=200;
  904.   snake.y[snake.node]=200;//产生蛇新的节坐标先放在看不见的位置
  905.   snake.node++;//蛇节数加1
  906.   food.yes=1;//食物标志置1
  907.   if(++Score>=PASSSCORE)
  908.   {
  909.    PrintScore();
  910.    GameOver();
  911.    break;
  912.   }
  913.   PrintScore();
  914. }
  915. for(n=0;n<snake.node;n++)
  916. {
  917.   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
  918. }//根据蛇的节数画出蛇
  919. delay(Speed_tiaosu*1000);   //调速
  920. delay(Speed_tiaosu*1000);
  921. 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);
  922. switch(KeyBuffer)
  923. {
  924.   case FUNC:
  925.     KeyBuffer=0;
  926.     if(++Speed_tiaosu>=10)
  927.      Speed_tiaosu=1;
  928.        PrintSpeed();
  929.     break;
  930.   case DOWN:
  931.     KeyBuffer=0;
  932.     if(snake.direction!=UP)
  933.      snake.direction=DOWN;
  934.     break;
  935.   case UP:
  936.     KeyBuffer=0;
  937.     if(snake.direction!=DOWN)
  938.      snake.direction=UP;
  939.     break;
  940.   case RIGHT:
  941.     KeyBuffer=0;
  942.     if(snake.direction!=LEFT)
  943.      snake.direction=RIGHT;
  944.     break;
  945.      case LEFT:
  946.     KeyBuffer=0;
  947.     if(snake.direction!=RIGHT)
  948.      snake.direction=LEFT;
  949.     break;
  950.   default:
  951.     break;
  952. }   
  953. }
  954. }
  955. void Gameplayt(void)
  956. {
  957. unsigned char n;
  958. InitRandom(TL0);
  959. food.yes=1;//1表示需要出现新事物,0表示已经存在食物尚未吃掉
  960. snake.life=0;//表示蛇还活着
  961. snake.direction=DOWN;
  962. snake.x[0]=6;snake.y[0]=6;
  963. snake.x[1]=3;snake.y[1]=6;
  964. snake.node=2;
  965. PrintScore();
  966. PrintSpeed();
  967. while(1)
  968. {
  969. if(food.yes==1)
  970. {
  971.   while(1)
  972.   {
  973.    food.x=Random()*85+3;
  974.    food.y=Random()*55+3;//获得随机数
  975.    while(food.x%3!=0)
  976.     food.x++;
  977.    while(food.y%3!=0)
  978.     food.y++;
  979.       for(n=0;n<snake.node;n++)//判断产生的食物坐标是否和蛇身重合
  980.    {
  981.     if((food.x==snake.x[n])&&(food.y==snake.y[n]))
  982.      break;
  983.    }
  984.    if(n==snake.node)
  985.    {
  986.     food.yes=0;
  987.     break;//产生有效的食物坐标
  988.    }
  989.   }
  990. }
  991. if(food.yes==0)
  992. {
  993.   Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
  994. }
  995. for(n=snake.node-1;n>0;n--)
  996. {
  997.   snake.x[n]=snake.x[n-1];
  998.   snake.y[n]=snake.y[n-1];
  999. }
  1000. switch(snake.direction)
  1001. {
  1002.   case DOWN:snake.x[0]+=3;break;
  1003.   case UP:snake.x[0]-=3;break;
  1004.   case RIGHT:snake.y[0]-=3;break;
  1005.   case LEFT:snake.y[0]+=3;break;
  1006.   default:break;
  1007. }
  1008. for(n=3;n<snake.node;n++)//从第三节开始判断蛇头是否咬到自己
  1009. {
  1010.   if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
  1011.   {
  1012.    GameOver();
  1013.    snake.life=1;
  1014.    break;
  1015.   }
  1016. }
  1017. if(snake.x[0]<3||snake.x[0]>=90)//判蛇头是否撞到墙壁
  1018. {
  1019.   GameOver();
  1020.   snake.life=1;
  1021. }
  1022. if(snake.life==1)
  1023.   break;//蛇死,则跳出while(1)循环
  1024. if(snake.y[0]<3||snake.y[0]>=60)   
  1025. {  if(snake.y[0]<3)
  1026.     snake.y[0]=59;
  1027. //      for(n=0;n<snake.node;n++)
  1028. //  {
  1029. //   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
  1030. //  }//根据蛇的节数画出蛇
  1031.     if(snake.y[0]>=60)
  1032.     snake.y[0]=3;
  1033. //    for(n=0;n<snake.node;n++)
  1034. //  {
  1035. //   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
  1036. //  }//根据蛇的节数画出蛇
  1037. //  

  1038. }
  1039. if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
  1040. {
  1041.   Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隐食物
  1042.   snake.x[snake.node]=200;
  1043.   snake.y[snake.node]=200;//产生蛇新的节坐标先放在看不见的位置
  1044.   snake.node++;//蛇节数加1
  1045.   food.yes=1;//食物标志置1
  1046.   if(++Score>=PASSSCORE)
  1047.   {
  1048.    PrintScore();
  1049.    GameOver();
  1050.    break;
  1051.   }
  1052.   PrintScore();
  1053. }
  1054. for(n=0;n<snake.node;n++)
  1055. {
  1056.   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
  1057. }//根据蛇的节数画出蛇
  1058. delay(Speed_tiaosu*1000);   //调速
  1059. delay(Speed_tiaosu*1000);
  1060. 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);
  1061. switch(KeyBuffer)
  1062. {
  1063.   case FUNC:
  1064.     KeyBuffer=0;
  1065.     if(++Speed_tiaosu>=10)
  1066.      Speed_tiaosu=1;
  1067.        PrintSpeed();
  1068.     break;
  1069.   case DOWN:
  1070.     KeyBuffer=0;
  1071.     if(snake.direction!=UP)
  1072.      snake.direction=DOWN;
  1073.     break;
  1074.   case UP:
  1075.     KeyBuffer=0;
  1076.     if(snake.direction!=DOWN)
  1077.      snake.direction=UP;
  1078.     break;
  1079.   case RIGHT:
  1080.     KeyBuffer=0;
  1081.     if(snake.direction!=LEFT)
  1082.      snake.direction=RIGHT;
  1083.     break;
  1084.      case LEFT:
  1085.     KeyBuffer=0;
  1086.     if(snake.direction!=RIGHT)
  1087.      snake.direction=LEFT;
  1088.     break;
  1089.   default:
  1090.     break;
  1091. }   
  1092. }
  1093. }


  1094. void scankey(void)
  1095. {





  1096. }

  1097. void speed(void)
  1098. {
  1099. Lcd_WriteStr(0,1,"Speed1");

  1100. Lcd_WriteStr(1,1,"Speed2");

  1101. Lcd_WriteStr(2,1,"Speed3");

  1102. Lcd_WriteStr(3,1,"Speed4");        
  1103. }
  1104. void moshi(void)
  1105. {
  1106. Lcd_WriteStr(0,1,"mosho1");

  1107. Lcd_WriteStr(1,1,"moshi2");         
  1108. }
  1109. void zhujiemian(void)
  1110. {
  1111. Lcd_WriteCmd(0x01);
  1112.   Lcd_WriteStr(0,0,"开始游戏");
  1113. Lcd_WriteStr(0,1,"速度选择");
  1114. Lcd_WriteStr(0,2,"模式设置");
  1115. }
  1116. unsigned char moshi1()
  1117. {
  1118. moshiceshi=1;
  1119. DrawBoardf();
  1120. GamePlayf();
  1121. return moshiceshi;
  1122. zhujiemian();
  1123. }
  1124. unsigned char moshi2()
  1125. {
  1126. moshiceshi=2;
  1127.   Drawboardt();
  1128.   Gameplayt();
  1129. return moshiceshi;
  1130. zhujiemian();
  1131. }
  1132. void Speed1(void)
  1133. {
  1134. unsigned char Speed_tiaosu=1;
  1135. zhujiemian();
  1136. }         
  1137. void Speed2(void)
  1138. {
  1139. unsigned char Speed_tiaosu=2;
  1140. zhujiemian();

  1141. }         
  1142. void Speed3(void)
  1143. {
  1144. unsigned char Speed_tiaosu=3;
  1145. zhujiemian();
  1146.         
  1147. }         
  1148. void Speed4(void)
  1149. {
  1150. unsigned char Speed_tiaosu=4;
  1151. zhujiemian();
  1152. }         
  1153. void game(void)
  1154. {
  1155.   InitCpu();//初始化CPU
  1156. Lcd_Reset(); //初始化LCD屏
  1157. delay(5000);
  1158. Lcd_Clear(0);//清屏
  1159. switch(Speed_tiaosu)
  1160. {
  1161.   case '1':
  1162.   Speed1();
  1163.   break;
  1164.   case '2':
  1165.   Speed2();
  1166.   break;
  1167.   case '3':
  1168.   Speed3();
  1169.   break;
  1170.   case '4':
  1171.   Speed4();
  1172.   break;
  1173.   default:
  1174.   Speed4();
  1175. }
  1176. switch(moshiceshi)
  1177. {
  1178.   case '1':
  1179.   moshi1();
  1180.   break;
  1181.   case '2':
  1182.   moshi2();
  1183.   break;
  1184.   default:
  1185.   moshi1();
  1186. }
  1187. GameOver();//游戏结束
  1188. }
复制代码



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:386631 发表于 2018-8-15 17:42 | 只看该作者
代码太长了,估计没几个人能看下去吧,发重点
回复

使用道具 举报

板凳
ID:385372 发表于 2018-8-18 17:46 | 只看该作者
同求 这么长的东西
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表