社区导航

 

搜索
楼主: 吴鉴鹰.

[原创] 资深工程师单片机实战项目精讲(连载),由易到难连续分享

  [复制链接]

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-26 13:44 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2014-12-26 13:49 编辑

28、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(一)——设计思路

这一连的几讲内容,鹰哥会向大家介绍贪吃蛇的设计思路,设计方法以及程序的编写,向大家详细介绍贪吃蛇的设计思路,让大家对如此神秘的贪吃蛇有深入的认识!




这是鹰哥大学的时候做的贪吃蛇游戏(图片1)

贪吃蛇介绍: 鹰哥首先来给大家介绍一下贪吃蛇,贪吃蛇是世界知名的益智类小游戏,鹰哥选择这个项目的原因是为了将我们自己的所学知识加以运用;另一方面,虽然我们很小就接触这个游戏,那时候用设计玩,觉得很有意思,但是它的制作方法对我们而言还是很神秘的。鹰哥希望通过自己的所学知识把它剖析开来,通过自己的动手实践,真正的了解它的本质和精髓。

这是鹰哥大学的时候做的贪吃蛇游戏(图片2)

希望通过这次实践,大家能从中提高自己的编程能力。并从中学会从零开始分析设计程序。
在以下一些列的章节中,会详细介绍贪吃蛇设计的每一个环节,对于大家如果有更好的方法或者建议,吴鉴鹰欢迎大家提供!


游戏整体流程:这个游戏流程图描述了整个游戏的总体运行过程。在开始游戏后对蛇与食物重绘,以及屏幕上的相关信息绘制。当蛇碰到石头或是咬到自己,就捕捉异常,游戏就结束。


游戏规则:游戏中玩家可以通过键盘控制游戏中的贪吃蛇的运动,当蛇头碰到系统产生的食物时加长蛇身。当蛇碰到石头或者自己的身体时,游戏结束。游戏玩家还可以通过鼠标来控制蛇的移动。
游戏规则:
1 玩家通过键盘控制蛇在游戏区中运动;
2 当蛇头碰到食物时,得分增加,蛇身增长一个单位;
3 当蛇头碰到蛇身或者石头,游戏结束;
要求实现以下功能:
玩家可以通过按键来控制贪吃蛇吃食物,游戏过程中还配有音效渲染气氛。





游戏设计思路:贪吃蛇游戏是一款非常经典的游戏,已经有很多版本的贪吃蛇游戏,游戏的玩法各版本大体相同。以下是本课题的贪吃蛇游戏设计的一些简单的说明: 1、 先设置一个主控面板;
2、 依次向面板中添加蛇,食物,石头;
3、 设法引导贪吃蛇吞掉食物以使它变得更长;
4、 添加监听程序,通过方向键来改变蛇的运动方向;
5、 添加监听程序,通过按键来改变蛇的运动方向;
6、 蛇不能吃到石头或是自己的身体,如果吃到石头或者自己的身体,游戏结束;
7、 蛇吃食物或者死掉的时候都有特定的音效产生,我们这里由于没有蜂鸣器,所以这个程序没加,感兴趣的读者可以自己加上去试试!



算法中的基本概念:
节:一条蛇可以看成由许多圆拼凑成,把它称作节。节是贪吃蛇身上最小的单位。
坐标系:坐标以左上角那点为(0,0),向右则x 递增,向下则y 递增。
链表:用来保存每一节的状态,链表的第一个元素表示蛇的头部结点。



蛇、石头、食物的表示:
我们可以把显示区域想象成一个大大的表格,里面的格子就是组成蛇的基本单位,一个格子可以代表一个食物,也可以代表一个石头,几块连在一起的石头就可以代表一条蛇。使用坐标来区分这些格子。
这里我们用一个集合来存储这些坐标,并且要求能够区分出蛇头和蛇尾。




蛇的移动:
蛇向前移动一步,可以看作是蛇头前面增加了一个节点,蛇的尾巴上少了一个节点(即去尾,加头)


存储蛇身的数据结构
由于要区分蛇头和蛇尾,我们必须用一个有顺序的数组表示,另一方面,我们需要经常的访问第一个和最后一个节点。




蛇的移动方向
这里讨论蛇的移动方向控制。
蛇下一步移动到哪里,是由方向来控制的。
这里我们用int型常量来表示蛇的移动方向。
因为我们是根据原蛇头的坐标和方向来确定新蛇头的坐标。在原坐标的基础上,根据蛇头的运动方向来确定新蛇头的坐标,比如向上移动就是y-1.

如何显示蛇身
显示蛇身,其实就是填充用颜色填充格子。
需要4个参数,像素坐标x,像素坐标y,格子宽度,格子高度。
像素坐标就是矩形左上角的坐标

蛇身的移动方向
1 相反方向
和上一次移动的方向相反的方向称为相反方向,这种输入应该忽略。这样可以防止蛇从自己的身体中穿过。
2 无效方向
在蛇的这一次移动之后和下一次移动之前这个时间间隔内输入了多个非相反方向,只有最后一个是有效方向,其他的都是无效方向。
蛇的最终运动方向以有效方向为准。

吃到食物判定
这里通过判定坐标是否重合来判断,只需要判断蛇头是否和食物重合就可以了,因为蛇的身体都是走蛇头走过的地方。
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-26 17:06 | 显示全部楼层
29、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(二)——贪吃蛇子程序
图片9.png
这是程序的设计思路: (1) 初始化蛇的相关信息; (2) 初始化食物的相关信息; (3)输出初始化分数; (4)当玩家没有按“ESC”键时,一直重复以下各步; (5) 当玩家不按任何键时,一直重复6—13各步骤; (6) 在屏幕画出食物; (7) 计算出蛇的每一节在屏幕中的位置; (8) 根据蛇的移动方向,计算出下一步蛇头的坐标位置; (9) 判断蛇头是不是撞上了自己的身体的任何一节,如果是,游戏结束; (10) 判断蛇头是不是撞到饿了任何一面的墙壁了,如果是,游戏结束; (11) 若(9)(10)都未发生,说明蛇活着,判断蛇是否吃到了食物,如果吃到了食物,则要先清除食物,并设置下一个食物的出现;同时,还要将蛇的身体增长一节;屏幕显示的分数还要增加。 (12) 将蛇在屏幕显示,然后游戏延迟一会儿,给玩家一点反应时间; (13) 蛇在移动的过程中,蛇头不断前进,末尾一节不断清除,这样才能保证蛇在移动的过程中的正确性; (14)当玩家按下一个键时,接收该按键,并判断是不是“ESC”;如果是,则退出游戏,如果不是则进行(15)步的判断;(15) 判断当前按键的方向是否与蛇头的方向相反,如果相反,则不做处理,因为蛇是不会退的,只要不是相反的,则就改变蛇的移动方向。回到(14)步去执行,一直循环往复,直到游戏结束。
图片10.png
  1. /****************************************************************************

  2. ** 函数名称: void Gluttonous_Snake(void)
  3. ** 功能描述: 贪吃蛇子程序
  4. ** 输 入:
  5. **
  6. **
  7. ** 输 出:
  8. **
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者: 吴鉴鹰
  13. ** 作者所在单位:鉴鹰电子工作室
  14. ** 日 期: 14.04.9
  15. ****************************************************************************/
  16. void Gluttonous_Snake(void)
  17. {
  18. uchar xdata SNK_BODY_Length[102]={0,8,1,8}; //存放蛇身的数组;
  19. uchar SNK_Food_Date[2]={12,8};
  20. uchar i,x,y;
  21. bit KEY_FLAG2,KEY_FLAG3,KEY_FLAG4;
  22. TMOD=1; //定时器工作方式
  23. IT0=1; //边延有效
  24. IT1=1;
  25. EA=1; //开CPU中断
  26. ET0=1; //开定时器中断
  27. EX0=1; //开外部中断
  28. EX1=1;
  29. TL0=0x00;
  30. TH0=0x00; //定时器初值
  31. TR0=1; //启动定时器

    SNAKE_GRADE_NUM=2;

  32. p=20;
  33. DIR_NUM_FLAG=1;
  34. KEY_FLAG5=0;

    CHOOSE_12864_SCREEN(2);

  35. CLEAR_12864_SCREEN();
  36. DRAW_TRANSVERSE_Line(1,61,30);
  37. DRAW_TRANSVERSE_Line(1,61,127);
  38. for(i=0;i<98;i++)
  39. {
  40. DRAW_DOT_HS(30+i,1);
  41. DRAW_DOT_HS(30+i,62);
  42. }
  43. Display_16_point(0,0,0,TCS_TAN);
  44. Display_16_point(0,0,1,TCS_CHI);
  45. Display_16_point(0,0,2,TCS_SHE);
  46. CHANGE_HS(SNK_BODY_Length,(SNK_BODY_Length+1));
  47. CHANGE_HS((SNK_BODY_Length+2),(SNK_BODY_Length+3));
  48. CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  49. for(;;)
  50. {
  51. do
  52. {
  53. first=1;
  54. while(KEY_FLAG5|!KEY_FLAG1);
  55. x=*(SNK_BODY_Length);
  56. y=*(SNK_BODY_Length+1);
  57. switch(DIR_NUM_FLAG) //右
  58. {
  59. case 1:
  60. {
  61. for(i=0;i {
  62. *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  63. *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  64. }
  65. (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))++;
  66. KEY_FLAG=0;
  67. break;
  68. }
  69. case 2: //下
  70. {
  71. for(i=0;i {
  72. *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  73. *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  74. }
  75. (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))++;
  76. KEY_FLAG=1;
  77. break;
  78. }
  79. case 3: //左
  80. {
  81. for(i=0;i {
  82. *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  83. *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  84. }
  85. (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))--;
  86. KEY_FLAG=0;
  87. break;
  88. }
  89. case 4:
  90. { //上
  91. for(i=0;i {
  92. *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  93. *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  94. }
  95. (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))--;
  96. KEY_FLAG=1;
  97. break;
  98. }
  99. }
  100. KEY_FLAG4=((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))==SNK_Food_Date[0])&&((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))==SNK_Food_Date[1]);
  101. if(KEY_FLAG4) //
  102. {
  103. for(i=SNAKE_GRADE_NUM;i>0;i--)
  104. {
  105. *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)-2);
  106. *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)-1);
  107. }
  108. *SNK_BODY_Length=x;
  109. *(SNK_BODY_Length+1)=y;
  110. SNAKE_GRADE_NUM++;
  111. do
  112. {
  113. KEY_FLAG3=0;
  114. SNK_Food_Date[0]=TL0%24;
  115. SNK_Food_Date[1]=TL0%15;
  116. for(i=0;i {
  117. if((*(SNK_BODY_Length+(i<<1)))==SNK_Food_Date[0]&&((*(SNK_BODY_Length+(i<<1)+1))==SNK_Food_Date[1]))
  118. {
  119. KEY_FLAG3=1;
  120. break;
  121. }
  122. }
  123. }while(KEY_FLAG3);
  124. CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  125. }
  126. KEY_FLAG2=1; //蛇头没有遇到蛇身
  127. for(i=0;i {
  128. if(*(SNK_BODY_Length+(i<<1))==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)&&(*(SNK_BODY_Length+(i<<1)+1)==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)))
  129. {
  130. KEY_FLAG2=0;
  131. break;
  132. }
  133. }
  134. KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)<24;//蛇头是否出边界
  135. KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)<15;
  136. if(KEY_FLAG2)
  137. {
  138. CLEAR_4DOT_HS(&x,&y);
  139. {
  140. CHANGE_HS(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2,SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1);
  141. }
  142. if(KEY_FLAG4)
  143. {
  144. CHANGE_HS(&x,&y);
  145. }
  146. KEY_FLAG1=0;
  147. Display_8_point(0,0,3,NUM0+((SNAKE_GRADE_NUM/10)<<4));
  148. Display_8_point(0,1,3,NUM0+(((SNAKE_GRADE_NUM)%10)<<4));
  149. }
  150. }
  151. while(KEY_FLAG2);
  152. delay1ms(450);
  153. delay1ms(450);
  154. CHOOSE_12864_SCREEN(2);
  155. CLEAR_12864_SCREEN();
  156. Display_16_point(0,4,1,GAME_OVER);
  157. Display_16_point(0,6,1,GAME_OVER+32);
  158. Display_16_point(1,0,1,GAME_OVER+64);
  159. Display_16_point(1,2,1,GAME_OVER+96);
  160. delay1ms(450);
  161. delay1ms(450);
  162. break;
  163. }
  164. }

复制代码
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-26 17:12 | 显示全部楼层
30、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(三)——贪吃蛇按键子程序
  1. /******************************************************
  2. *程序:独立式按键中断检测方法
  3. *
  4. ** 这一讲的主要内容: 独立式按键中断检测方法
  5. ** 功能描述: 独立式按键中断检测方法
  6. ** 输 入:
  7. ** 输 出:
  8. **
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者: 吴鉴鹰
  13. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  14. *******************************************************/
  15. #include //头文件
  16. #include
  17. #define uchar unsigned char //宏定义
  18. #define uint unsigned int
  19. sbit jdq=P3^5; //位声明,驱动继电器管脚
  20. sbit fmq=P3^4; //位声明,驱动蜂鸣器管脚
  21. code uchar table[]={0x3f,0x06,0x5b,//数码管显示的数值
  22. 0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
  23. 0x77,0x7c,0x39,0x5e,0x79,0x71};
  24. code uchar key_tab[17]={ //此数组为键盘编码
  25. 0xed,0x7e,0x7d,0x7b, // 0,1,2,3,
  26. 0xbe,0xbd,0xbb,0xde, // 4,5,6,7,
  27. 0xdd,0xdb,0x77,0xb7, // 8,9,a, b,
  28. 0xee,0xeb,0xd7,0xe7,0xff}; // c,d,e,f,
  29. uchar l_key=0x00; //定义变量,存放键值
  30. uchar l_keyold=0xff; //作为按键放开否的凭证
  31. void readkey(); //扫描键盘,获取键值
  32. void display(uchar *lp,uchar lc); //显示子函数
  33. void delay(); //延时子函数

    /******************************************************

  34. *程序:void main() //主函数
  35. *
  36. ** 这一讲的主要内容: 按键检测主函数
  37. ** 功能描述: 按键检测主函数
  38. ** 输 入:
  39. ** 输 出:
  40. **
  41. ** 全局变量:
  42. ** 调用模块:
  43. **
  44. ** 作 者: 吴鉴鹰
  45. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  46. *******************************************************/
  47. void main() //主函数
  48. {
  49.   EA=1; //打开总中断
  50.   EX0=1; //打开外部中断
  51.   P0=0xf0; //键值高4位为高电平,低4位为低电平
  52.   while(1)
  53.   {
  54.   display(&l_key,1); //调用显示子函数
  55.   if(l_key==14) //是否按下E键,是则关闭继电器
  56.   jdq=1;
  57.   if(l_key==12) //是否按下C键,是则打开继电器
  58.   jdq=0;
  59.   }
  60. }

  61. /******************************************************
  62. *程序:void key_scan() interrupt 0//外部中断0,0的优先级最高
  63. *
  64. ** 这一讲的主要内容: 响应外部中断
  65. ** 功能描述: 响应外部中断
  66. ** 输 入:
  67. ** 输 出:
  68. **
  69. ** 全局变量:
  70. ** 调用模块:
  71. **
  72. ** 作 者: 吴鉴鹰
  73. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  74. *******************************************************/
  75. void key_scan() interrupt 0//外部中断0,0的优先级最高
  76. {
  77. EX0=0; //在读键盘时,关闭外部中断,防止干扰带来的多次中断
  78. TMOD&=0xf1; //设置定时器为工作方式1
  79. TH0=0x2e; //设置初值,为12毫秒,十进制值为11776
  80. TL0=0x00;
  81. ET0=1; //开启定时器中断0
  82. TR0=1; //启动定时器计数
  83. }

    /******************************************************

  84. *程序:void time0() interrupt 1 //定时器0的中断函数
  85. *
  86. ** 这一讲的主要内容: 定时12ms后产生中断,调用此函数,读取键值
  87. ** 功能描述: 定时12ms后产生中断,调用此函数,读取键值
  88. ** 输 入:
  89. ** 输 出:
  90. **
  91. ** 全局变量:
  92. ** 调用模块:
  93. **
  94. ** 作 者: 吴鉴鹰
  95. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  96. *******************************************************/
  97. void time0() interrupt 1 //定时器0的中断函数
  98. {
  99. TR0=0; //关闭定时器0
  100. readkey(); //定时12ms后产生中断,调用此函数,读取键值
  101. }

  102. /******************************************************
  103. *程序:void readkey() //扫描键盘子函数
  104. *
  105. ** 这一讲的主要内容: //扫描键盘子函数
  106. ** 功能描述: //扫描键盘子函数
  107. ** 输 入:
  108. ** 输 出:
  109. **
  110. ** 全局变量:
  111. ** 调用模块:
  112. **
  113. ** 作 者: 吴鉴鹰
  114. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  115. *******************************************************/
  116. void readkey() //扫描键盘子函数
  117. {
  118. uchar i,j,key; //定义局部变量
  119. j=0xfe; //设定初值
  120. key=0xff;
  121. for(i=0;i<4;i++) // 逐列扫描键盘
  122. {
  123.   P0=j;
  124.   if((P0&0xf0)!=0xf0) //有按键按下,高4位不可能全为1
  125.    {
  126.    key=P0; //读取P0口的值,推出循环,否则循环下次
  127.    break;
  128.    }
  129.   j=_crol_(j,1); //此函数的功能是:左移循环
  130.  }
  131.   if(key==0xff) //如果读取不到P0口的值,如干扰,则返回
  132.   {
  133.   l_keyold=0xff;
  134.   P0=0xf0; // 恢复P0口的值,等待按键按下
  135.   fmq=1;
  136.   EX0=1; //在返回前,打开外部中断
  137.   return;
  138.   }
  139.   fmq=0; //有按键按下,打开蜂鸣器
  140.   if(l_keyold==key) // 检查按键放开否,如果相等表明没有放开
  141.   {
  142.  TH0=0x2e; //设置初值
  143.   TL0=0x00;
  144.  TR0=1; //继续启动定时器,检查按键放开否
  145.   return;
  146.   }
  147.   TH0=0x2e;
  148.   TL0=0;
  149.   TR0=1; //启动定时器
  150.   l_keyold=key; //获取键值,作为放开否的凭证
  151.   for(i=0;i<17;i++) //查表获得相应的16进制值存放到l_key中
  152.   {
  153.     if(key==key_tab)
  154.     {
  155.     l_key=i;
  156.     break;
  157.     }
  158. }
  159. //程序运行到此,就表明有键值存放到l_key中,主程序
  160. //就可以检测键盘值并作相应的处理
  161. }

  162. /******************************************************
  163. *程序:void display(uchar *lp,uchar lc) //显示子函数
  164. *
  165. ** 这一讲的主要内容: 显示子函数
  166. ** 功能描述: 显示子函数
  167. ** 输 入:
  168. ** 输 出:
  169. **
  170. ** 全局变量:
  171. ** 调用模块:
  172. **
  173. ** 作 者: 吴鉴鹰
  174. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  175. *******************************************************/
  176. void display(uchar *lp,uchar lc) //显示子函数
  177. {
  178.   uchar i; //定义局部变量
  179.   P1=0xf8; //点亮第一个数码管
  180.   P2=0; //P2口为输出值
  181.   for(i=0;i   {
  182.   P2=table[lp]; //查表获得相应的要显示的数字的数码段
  183.   delay(); //延时
  184.   P2=0; //清零,准备显示下一个数值
  185.   }
  186. }

    /******************************************************

  187. *程序:void delay() //延时子函数
  188. *
  189. ** 这一讲的主要内容: 延时子函数
  190. ** 功能描述: 延时子函数
  191. ** 输 入:
  192. ** 输 出:
  193. **
  194. ** 全局变量:

    ** 调用模块:

  195. **
  196. ** 作 者: 吴鉴鹰
  197. ** 日 期: 14.04.12

    备注:有什么错误的地方,欢迎各大烧友指正,感谢电子发烧友提供这个平台能跟各大烧友一同分享,一同进步

    O(∩_∩)O~

  198. *******************************************************/
  199. void delay() //延时子函数
  200. {
  201. _nop_();_nop_();_nop_();_nop_();_nop_();
  202. }

  203. /*以下是在贪吃蛇中的程序
  204. **功能:用中断法检测按键**
  205. *****************************/
  206. /****************************************************************************
  207. ** 函数名称: void dingshi() interrupt 1 using 1
  208. ** 功能描述: 定时程序.产生步进时间
  209. ** 输 入:
  210. **
  211. **
  212. ** 输 出:
  213. **
  214. ** 全局变量:
  215. ** 调用模块:
  216. **
  217. ** 作 者: 吴鉴鹰
  218. ** 作者所在单位:鉴鹰电子工作室
  219. ** 日 期: 14.04.9
  220. ****************************************************************************/
  221. void dingshi() interrupt 1 using 1 //定时程序.产生步进时间
  222. {
  223. if(p--)
  224. {
  225. TL0=0;
  226. TH0=0xa0;
  227. KEY_FLAG1=0;
  228. }
  229. else
  230. {
  231. KEY_FLAG1=1;
  232. TL0=0;
  233. TH0=0x00;
  234. p=20-(SNAKE_GRADE_NUM>>1);
  235. }
  236. }

  237. /****************************************************************************
  238. ** 函数名称: void zhongduan1() interrupt 2 using 2
  239. ** 功能描述: 开始确认暂停键的判断
  240. ** 输 入:
  241. **
  242. **
  243. ** 输 出:
  244. **
  245. ** 全局变量:
  246. ** 调用模块:
  247. **
  248. ** 作 者: 吴鉴鹰
  249. ** 作者所在单位:鉴鹰电子工作室
  250. ** 日 期: 14.04.9
  251. ****************************************************************************/
  252. void zhongduan1() interrupt 2 using 2
  253. {
  254. if(!KEY_FLAG5)
  255. {
  256. KEY_FLAG5=1;
  257. }
  258. else
  259. {
  260. KEY_FLAG5=0;
  261. }
  262. }

  263. /****************************************************************************
  264. ** 函数名称: void INTERRUPT_NUM0() interrupt 0 using 0
  265. ** 功能描述: 方向键的判断
  266. ** 输 入:
  267. **
  268. **
  269. ** 输 出:
  270. **
  271. ** 全局变量:
  272. ** 调用模块:
  273. **
  274. ** 作 者: 吴鉴鹰
  275. ** 作者所在单位:鉴鹰电子工作室
  276. ** 日 期: 14.04.9
  277. ****************************************************************************/
  278. void INTERRUPT_NUM0() interrupt 0 using 0
  279. {
  280. uchar i=0;
  281. if(first) //FIRST=1;打开方向按键判断标志
  282. {
  283. first=0;
  284. k=(P2>>6);
  285. k=k&0x03;
  286. if(KEY_FLAG)
  287. {
  288. if(k==1) DIR_NUM_FLAG=3;//左
  289. if(k==2) DIR_NUM_FLAG=1;//右
  290. }
  291. else
  292. {
  293. if(k==0) DIR_NUM_FLAG=4;//上
  294. if(k==3) DIR_NUM_FLAG=2;//下
  295. }
  296. }
  297. }

复制代码
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-26 17:24 | 显示全部楼层
31、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(四)——完整程序

这一连的几讲内容,鹰哥会向大家介绍贪吃蛇的设计思路,设计方法以及程序的编写,向大家详细介绍贪吃蛇的设计思路,让大家对如此神秘的贪吃蛇有深入的认识!


这是鹰哥大学的时候做的贪吃蛇游戏(图片1)

贪吃蛇介绍: 鹰哥首先来给大家介绍一下贪吃蛇,贪吃蛇是世界知名的益智类小游戏,鹰哥选择这个项目的原因是为了将我们自己的所学知识加以运用;另一方面,虽然我们很小就接触这个游戏,那时候用设计玩,觉得很有意思,但是它的制作方法对我们而言还是很神秘的。鹰哥希望通过自己的所学知识把它剖析开来,通过自己的动手实践,真正的了解它的本质和精髓。




这是鹰哥大学的时候做的贪吃蛇游戏(图片2)

希望通过这次实践,大家能从中提高自己的编程能力。并从中学会从零开始分析设计程序。
在以下一些列的章节中,会详细介绍贪吃蛇设计的每一个环节,对于大家如果有更好的方法或者建议,吴鉴鹰欢迎大家提供!




游戏整体流程:这个游戏流程图描述了整个游戏的总体运行过程。在开始游戏后对蛇与食物重绘,以及屏幕上的相关信息绘制。当蛇碰到石头或是咬到自己,就捕捉异常,游戏就结束。



游戏规则:游戏中玩家可以通过键盘控制游戏中的贪吃蛇的运动,当蛇头碰到系统产生的食物时加长蛇身。当蛇碰到石头或者自己的身体时,游戏结束。游戏玩家还可以通过鼠标来控制蛇的移动。
游戏规则:
1 玩家通过键盘控制蛇在游戏区中运动;
2 当蛇头碰到食物时,得分增加,蛇身增长一个单位;
3 当蛇头碰到蛇身或者石头,游戏结束;
要求实现以下功能:
玩家可以通过按键来控制贪吃蛇吃食物,游戏过程中还配有音效渲染气氛。



游戏设计思路:贪吃蛇游戏是一款非常经典的游戏,已经有很多版本的贪吃蛇游戏,游戏的玩法各版本大体相同。以下是本课题的贪吃蛇游戏设计的一些简单的说明: 1、 先设置一个主控面板;
2、 依次向面板中添加蛇,食物,石头;
3、 设法引导贪吃蛇吞掉食物以使它变得更长;
4、 添加监听程序,通过方向键来改变蛇的运动方向;
5、 添加监听程序,通过按键来改变蛇的运动方向;
6、 蛇不能吃到石头或是自己的身体,如果吃到石头或者自己的身体,游戏结束;
7、 蛇吃食物或者死掉的时候都有特定的音效产生,我们这里由于没有蜂鸣器,所以这个程序没加,感兴趣的读者可以自己加上去试试!






算法中的基本概念:
节:一条蛇可以看成由许多圆拼凑成,把它称作节。节是贪吃蛇身上最小的单位。
坐标系:坐标以左上角那点为(0,0),向右则x 递增,向下则y 递增。
链表:用来保存每一节的状态,链表的第一个元素表示蛇的头部结点。




蛇、石头、食物的表示:
我们可以把显示区域想象成一个大大的表格,里面的格子就是组成蛇的基本单位,一个格子可以代表一个食物,也可以代表一个石头,几块连在一起的石头就可以代表一条蛇。使用坐标来区分这些格子。
这里我们用一个集合来存储这些坐标,并且要求能够区分出蛇头和蛇尾。




蛇的移动:
蛇向前移动一步,可以看作是蛇头前面增加了一个节点,蛇的尾巴上少了一个节点(即去尾,加头)


存储蛇身的数据结构
由于要区分蛇头和蛇尾,我们必须用一个有顺序的数组表示,另一方面,我们需要经常的访问第一个和最后一个节点。


蛇的移动方向
这里讨论蛇的移动方向控制。
蛇下一步移动到哪里,是由方向来控制的。
这里我们用int型常量来表示蛇的移动方向。
因为我们是根据原蛇头的坐标和方向来确定新蛇头的坐标。在原坐标的基础上,根据蛇头的运动方向来确定新蛇头的坐标,比如向上移动就是y-1.

如何显示蛇身
显示蛇身,其实就是填充用颜色填充格子。
需要4个参数,像素坐标x,像素坐标y,格子宽度,格子高度。
像素坐标就是矩形左上角的坐标

蛇身的移动方向
1 相反方向
和上一次移动的方向相反的方向称为相反方向,这种输入应该忽略。这样可以防止蛇从自己的身体中穿过。
2 无效方向
在蛇的这一次移动之后和下一次移动之前这个时间间隔内输入了多个非相反方向,只有最后一个是有效方向,其他的都是无效方向。
蛇的最终运动方向以有效方向为准。

吃到食物判定
这里通过判定坐标是否重合来判断,只需要判断蛇头是否和食物重合就可以了,因为蛇的身体都是走蛇头走过的地方






这是程序的设计思路:
(1) 初始化蛇的相关信息;
(2) 初始化食物的相关信息;
(3)输出初始化分数;
(4)当玩家没有按“ESC”键时,一直重复以下各步;
(5) 当玩家不按任何键时,一直重复613各步骤;
(6) 在屏幕画出食物;
(7) 计算出蛇的每一节在屏幕中的位置;
(8) 根据蛇的移动方向,计算出下一步蛇头的坐标位置;
(9) 判断蛇头是不是撞上了自己的身体的任何一节,如果是,游戏结束;
(10) 判断蛇头是不是撞到饿了任何一面的墙壁了,如果是,游戏结束;
(11) 若(9)(10)都未发生,说明蛇活着,判断蛇是否吃到了食物,如果吃到了食物,则要先清除食物,并设置下一个食物的出现;同时,还要将蛇的身体增长一节;屏幕显示的分数还要增加。
(12) 将蛇在屏幕显示,然后游戏延迟一会儿,给玩家一点反应时间;
(13) 蛇在移动的过程中,蛇头不断前进,末尾一节不断清除,这样才能保证蛇在移动的过程中的正确性;
(14)当玩家按下一个键时,接收该按键,并判断是不是“ESC”;如果是,则退出游戏,如果不是则进行(15)步的判断;(15) 判断当前按键的方向是否与蛇头的方向相反,如果相反,则不做处理,因为蛇是不会退的,只要不是相反的,则就改变蛇的移动方向。回到(14)步去执行,一直循环往复,直到游戏结束。










/****************************************************************************
** 函数名称:  void Gluttonous_Snake(void)
** 功能描述:  贪吃蛇子程序
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void Gluttonous_Snake(void)                                                                                                           
{           
  uchar xdata SNK_BODY_Length[102]={0,8,1,8};         //存放蛇身的数组;
  uchar SNK_Food_Date[2]={12,8};
  uchar i,x,y;
  bit KEY_FLAG2,KEY_FLAG3,KEY_FLAG4;
  TMOD=1;          //定时器工作方式
  IT0=1;          //边延有效
  IT1=1;
  EA=1;                  //开CPU中断
  ET0=1;          //开定时器中断
  EX0=1;          //开外部中断
  EX1=1;
  TL0=0x00;
  TH0=0x00;          //定时器初值
  TR0=1;          //启动定时器
  SNAKE_GRADE_NUM=2;
  p=20;
  DIR_NUM_FLAG=1;
  KEY_FLAG5=0;
  CHOOSE_12864_SCREEN(2);
  CLEAR_12864_SCREEN();        
  DRAW_TRANSVERSE_Line(1,61,30);
  DRAW_TRANSVERSE_Line(1,61,127);
  for(i=0;i<98;i++)
  {
       DRAW_DOT_HS(30+i,1);
       DRAW_DOT_HS(30+i,62);
  }
  Display_16_point(0,0,0,TCS_TAN);
  Display_16_point(0,0,1,TCS_CHI);
  Display_16_point(0,0,2,TCS_SHE);
  CHANGE_HS(SNK_BODY_Length,(SNK_BODY_Length+1));
  CHANGE_HS((SNK_BODY_Length+2),(SNK_BODY_Length+3));
  CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  for(;;)
  {
    do
   {
    first=1;
    while(KEY_FLAG5|!KEY_FLAG1);
    x=*(SNK_BODY_Length);                              
    y=*(SNK_BODY_Length+1);
    switch(DIR_NUM_FLAG)                           //右
        {
          case 1:
            {
              for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
               (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))++;
                   KEY_FLAG=0;
                   break;
              }
                   case 2:                                          //下
                 {
              for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
                    (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))++;
                        KEY_FLAG=1;
                        break;
                  }
                case 3:                                        //左
                 {
               for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
               (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))--;
                   KEY_FLAG=0;
                   break;
                 }
                case 4:
                 {                        //上
                 for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
                    (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))--;
                        KEY_FLAG=1;
                        break;
                 }
         }
         KEY_FLAG4=((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))==SNK_Food_Date[0])&&((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))==SNK_Food_Date[1]);
         if(KEY_FLAG4)        //
         {
                for(i=SNAKE_GRADE_NUM;i>0;i--)
                {
                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)-2);
                  *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)-1);
                }
                *SNK_BODY_Length=x;
                *(SNK_BODY_Length+1)=y;
                SNAKE_GRADE_NUM++;
                do
                {
                  KEY_FLAG3=0;
                  SNK_Food_Date[0]=TL0%24;
              SNK_Food_Date[1]=TL0%15;
                  for(i=0;i                   {
                    if((*(SNK_BODY_Length+(i<<1)))==SNK_Food_Date[0]&&((*(SNK_BODY_Length+(i<<1)+1))==SNK_Food_Date[1]))
                        {
                          KEY_FLAG3=1;
                          break;
                         }
                  }
                }while(KEY_FLAG3);
                CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
         }
     KEY_FLAG2=1;          //蛇头没有遇到蛇身
         for(i=0;i         {
                   if(*(SNK_BODY_Length+(i<<1))==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)&&(*(SNK_BODY_Length+(i<<1)+1)==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)))
                   {
                     KEY_FLAG2=0;
                         break;
                        }
                }
          KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)<24;//蛇头是否出边界
          KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)<15;
          if(KEY_FLAG2)
           {
            CLEAR_4DOT_HS(&x,&y);
               
            
             {
               CHANGE_HS(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2,SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1);
             }
                 if(KEY_FLAG4)
                 {
                   CHANGE_HS(&x,&y);
                  }
            KEY_FLAG1=0;
            Display_8_point(0,0,3,NUM0+((SNAKE_GRADE_NUM/10)<<4));
            Display_8_point(0,1,3,NUM0+(((SNAKE_GRADE_NUM)%10)<<4));
           }
   }
   while(KEY_FLAG2);
   delay1ms(450);
   delay1ms(450);
   CHOOSE_12864_SCREEN(2);
   CLEAR_12864_SCREEN();
   Display_16_point(0,4,1,GAME_OVER);
   Display_16_point(0,6,1,GAME_OVER+32);
   Display_16_point(1,0,1,GAME_OVER+64);
   Display_16_point(1,2,1,GAME_OVER+96);
   delay1ms(450);
   delay1ms(450);
   break;
  }
}

/******************************************************
**作品:LCD12864贪吃蛇设计                                                           
**
** 这一讲的主要内容:  LCD12664液晶显示原理                                                                                       
** 功能描述:  对吴鉴鹰贪吃蛇设计的显示
** 输 入:
** 液晶:Proteus元件库—AMPIRE128X64(无字库)         
** 内容:LCD12864俄罗斯方块设计      
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.9
**作者所属单位:鉴鹰电子工作室
**交流QQ群: 第一群: 332164870  第二群:194314772   联系QQ:1123942529
**申明:转载请标明作品来源 知识产权归作者吴鉴鹰所有!
备注:有什么错误的地方,欢迎各大烧友指正
O(∩_∩)O~
*******************************************************/
#include
#include
#include
#include

#define uchar unsigned char
#define uint unsigned int           //宏定义  */
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
/*************************************
** 模块名称:LCD12864 端口定义
** 作用:定义液晶屏IO口的定义
** LCD_RS_OUT为0---命令;1----数据
** LCD_RW_OUT为1---写;0---读
** LCD_E_OUT使能端
** LCD_CS1_OUT片选1低电平有效,控制左半屏
** LCD_CS2_OUT片选1低电平有效,控制右半屏  
*************************************/
sbit LCD_E_OUT  = P2^0;   
sbit LCD_RW_OUT = P2^1;
sbit LCD_RS_OUT = P2^2;
sbit LCD_CS2_OUT = P2^3;
sbit LCD_CS1_OUT = P2^4;
#define LCD_12864_DATA  P0                        
uchar code NUM0[]={0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00};/*"0",0*/
uchar code NUM1[]={0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00};/*"1",0*/
uchar code NUM2[]={0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00};/*"2",0*/
uchar code NUM3[]={0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00};/*"3",0*/
uchar code NUM4[]={0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00};/*"4",0*/
uchar code NUM5[]={0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00};/*"5",0*/
uchar code NUM6[]={0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00};/*"6",0*/
uchar code NUM7[]={0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00};/*"7",0*/
uchar code NUM8[]={0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00};/*"8",0*/
uchar code NUM9[]={0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00};/*"9",0*/
uchar code GAME_OVER[]=
{
0x00,0x20,0x44,0x08,0x20,0xE0,0x92,0x94,0x10,0x28,0xAE,0x68,0x24,0x04,0x00,0x00,
0x00,0x0C,0x03,0x04,0x02,0x19,0x0C,0x03,0x02,0x12,0x22,0x1F,0x01,0x01,0x01,0x00,/*"游",0*/
0x00,0x20,0xA0,0x90,0x10,0xF0,0x00,0x40,0x7F,0xC0,0x20,0x24,0x88,0x00,0x00,0x00,
0x10,0x08,0x04,0x02,0x01,0x02,0x14,0x10,0x08,0x05,0x06,0x09,0x10,0x20,0x38,0x00,/*"戏",1*/
0x00,0x60,0x50,0xCC,0x40,0x30,0x40,0x40,0x40,0xFE,0x20,0x20,0x20,0x20,0x00,0x00,
0x00,0x12,0x13,0x0A,0x09,0x05,0x00,0x3A,0x2A,0x25,0x25,0x15,0x1D,0x00,0x00,0x00,/*"结",2*/
0x00,0x00,0x00,0x60,0xA8,0xA8,0xA8,0xFF,0x94,0x54,0x70,0x00,0x00,0x00,0x00,0x00,
0x10,0x10,0x08,0x08,0x04,0x02,0x01,0x7F,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x00 /*"束",3*/
};
uchar code TCS_TAN[]=
{
0x20,0x20,0x10,0x90,0xA8,0xA4,0xAA,0xB1,0xA2,0xE4,0xA8,0x88,0x10,0x30,0x10,0x00,
0x00,0x00,0x80,0x9F,0x40,0x20,0x10,0x0E,0x10,0x20,0x60,0xDF,0x00,0x00,0x00,0x00,/*"贪",0*/
};
uchar code TCS_CHI[]=
{
0x00,0xFC,0x04,0x04,0xFC,0x20,0x58,0x4F,0x4A,0x48,0x48,0xC8,0x08,0x08,0x08,0x00,
0x00,0x0F,0x02,0x02,0x07,0x00,0x30,0x48,0x44,0x42,0x41,0x40,0x40,0x40,0x70,0x00/*"吃",1*/
};
uchar code TCS_SHE[]=
{
0x00,0xF0,0x10,0xFF,0x10,0xF0,0x20,0x18,0xE8,0x09,0x0E,0x0A,0xA8,0x18,0x08,0x00,
0x20,0x23,0x21,0x1F,0x11,0x3B,0x10,0x00,0x3F,0x42,0x41,0x41,0x40,0x38,0x00,0x00/*"蛇",2*/
};
uchar code WJYZZ[]=
{
/*--  文字:  吴  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,0x00,
0x84,0x84,0x44,0x44,0x24,0x14,0x0C,0x07,0x0C,0x14,0x24,0x44,0x44,0x84,0x84,0x00,
/*--  文字:  鉴  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,
/*--  文字:  鹰  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,
/*--  文字:  制  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x50,0x4E,0x48,0x48,0xFF,0x48,0x48,0x48,0x40,0xF8,0x00,0x00,0xFF,0x00,0x00,
0x00,0x00,0x3E,0x02,0x02,0xFF,0x12,0x22,0x1E,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,
/*--  文字:  作  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,

};
uchar code wnl[]=
{0x00,0x02,0x02,0x02,0x02,0x82,0x7E,0x22,0x22,0x22,0x22,0xF2,0x22,0x02,0x02,0x00,
0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x20,0x60,0x20,0x1F,0x00,0x00,0x00,0x00,/*"万",0*/
0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,
0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00,/*"年",1*/
0x00,0x00,0xFE,0x02,0x22,0x22,0x22,0x22,0xFA,0x22,0x22,0x22,0xE2,0x02,0x02,0x00,
0x40,0x30,0x0F,0x00,0x40,0x20,0x18,0x06,0x01,0x00,0x20,0x60,0x3F,0x00,0x00,0x00};/*"历",2*/
uchar code moxing[]=
{0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,
0x11,0x12,0x10,0x13,0x01,0x31,0x11,0x21,0x11,0x12,0x10,0x13,0x01,0x31,0x11,0x21,
0x01,0x21,0x10,0x11,0x11,0x21,0x10,0x12,0x00,0x20,0x10,0x11,0x01,0x11,0x10,0x12,
0x10,0x21,0x20,0x22,0x01,0x21,0x20,0x11,0x11,0x22,0x10,0x12,0x10,0x30,0x20,0x11,
0x11,0x20,0x10,0x12,0x00,0x20,0x10,0x21,0x12,0x21,0x20,0x22,0x11,0x31,0x10,0x21,
0x11,0x21,0x10,0x22,0x01,0x20,0x10,0x11,0x11,0x21,0x10,0x22,0x01,0x20,0x10,0x11,
0x11,0x21,0x20,0x12,0x10,0x31,0x20,0x21,0x11,0x21,0x20,0x12,0x10,0x31,0x20,0x21
};

uchar code WJYW[]=
{
/*--  文字:  吴  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,0x00,
0x84,0x84,0x44,0x44,0x24,0x14,0x0C,0x07,0x0C,0x14,0x24,0x44,0x44,0x84,0x84,0x00,
};
uchar code WJYJ[]=
{
/*--  文字:  鉴  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,
};
uchar code WJYY[]=
{
/*--  文字:  鹰  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,
};
uchar code WJYZH[]=
{
/*--  文字:  制  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x50,0x4E,0x48,0x48,0xFF,0x48,0x48,0x48,0x40,0xF8,0x00,0x00,0xFF,0x00,0x00,
0x00,0x00,0x3E,0x02,0x02,0xFF,0x12,0x22,0x1E,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,
};

/*uchar code WJYZZ[]=
{
/*--  文字:  作  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
/*0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,
};
*/
uchar code WWJJYYJ[]=
{
/*--  文字:  鉴  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,
};
uchar code WWJJYYY[]=
{
/*--  文字:  鹰  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,
};
uchar code WWJJYYD[]=
{
/*--  文字:  电  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00,
0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,
};
uchar code WWJJYYZ[]=
{
/*--  文字:  子  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00,
0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};

uchar code WWJJYYG[]=
{
/*--  文字:  工  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x04,0x04,0x04,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
};
uchar code WWJJYYZ1[]=
{
/*--  文字:  作  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,
};
uchar code WWJJYYS[]=
{
/*--  文字:  室  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x0C,0x24,0x24,0xA4,0x64,0x25,0x26,0x24,0x24,0xA4,0x24,0x24,0x14,0x0C,0x00,
0x40,0x40,0x48,0x49,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x4B,0x48,0x40,0x40,0x00,
};

uchar code WWJJYYW[]=
{
/*--  调入了一幅图像:C:\Users\Administrator\Desktop\624814_225502035_2.bmp  --*/
/*--  宽度x高度=16x16  --*/
0xE0,0x18,0x0C,0x06,0x53,0xE9,0x49,0x01,0x01,0x49,0xE9,0x53,0x06,0x0C,0x38,0xF0,
0x0F,0x18,0x30,0x60,0x46,0xCC,0x98,0x98,0x98,0x98,0xCC,0xC6,0x60,0x30,0x18,0x0F,
};
uchar code WWJJYYWXTP[]=
{
/*--  调入了一幅图像:C:\Users\Administrator\Desktop\624814_225502035_2.bmp  --*/
/*--  宽度x高度=16x16  --*/
0xF0,0x18,0x0E,0x06,0x43,0xE9,0x49,0x01,0x01,0x49,0xE9,0x43,0x06,0x0C,0x38,0xF0,
0x0F,0x18,0x37,0x6F,0x5E,0xDC,0xB8,0xB8,0xB8,0xB8,0xDC,0xDE,0x6F,0x37,0x18,0x0F,
};
/******************************************************************
**        标题:鉴鹰电子欢乐多啊
**  功能:数组
*****************************************************************/
uchar code WWJJYYHH[] =
{
/*--  文字:  欢  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00,
0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00,
};
uchar code WWJJYYLE[]=
{
/*--  文字:  乐  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xE0,0x9C,0x84,0x84,0x84,0xF4,0x82,0x82,0x83,0x82,0x80,0x80,0x00,0x00,
0x00,0x20,0x10,0x08,0x06,0x40,0x80,0x7F,0x00,0x00,0x02,0x04,0x08,0x30,0x00,0x00,
};
uchar code WWJJYYDUO[]=
{
/*--  文字:  多  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0x10,0x10,0x98,0xA4,0x47,0x44,0xA4,0x54,0x0C,0x04,0x00,0x00,0x00,0x00,
0x00,0x81,0x89,0x89,0x44,0x44,0x4A,0x31,0x21,0x11,0x09,0x05,0x03,0x00,0x00,0x00,
};
uchar code WWJJYYAA[]=
{
/*--  文字:  啊  --*/
/*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
0xFC,0x04,0xFC,0x00,0xFE,0x42,0xBE,0x00,0xF2,0x12,0xF2,0x02,0xFE,0x02,0x00,0x00,
0x0F,0x04,0x0F,0x00,0xFF,0x10,0x0F,0x00,0x0F,0x04,0x4F,0x80,0x7F,0x00,0x00,0x00,
};
uchar code table[]={/*--  调入了一幅图像:C:\Users\Administrator\Desktop\7308055_142022128173_2.bmp  --*/
/*--  宽度x高度=128x64  --*/
0xFF,0x7F,0x7F,0xFF,0xF7,0xC3,0x87,0x07,0x0F,0x1F,0x1F,0x3F,0x7F,0x7F,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
0xFF,0x7F,0x7F,0x3F,0x1F,0x1F,0x0F,0x87,0x87,0xC3,0xE1,0x7F,0x7F,0x7F,0xBF,0xFF,
0xFF,0xFF,0xF6,0xF6,0xA4,0xA4,0xA5,0xA1,0x81,0x80,0x80,0x00,0x00,0x00,0x00,0x00,
0x01,0x01,0x03,0x03,0x00,0x03,0x07,0x07,0x0F,0x1F,0x0F,0x0F,0x1F,0x1F,0x3F,0x3F,
0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x3F,0x3F,0x3F,
0x3F,0x1F,0x1F,0x0F,0x0F,0x07,0x0F,0x0F,0x07,0x03,0x01,0x00,0x02,0x01,0x01,0x00,
0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xD0,0xD4,0xD2,0xD2,0xFB,0xFB,0xFB,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF0,
0xF0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0x07,0x07,0x0F,0x0F,0x1F,0x1F,0x3F,
0x7F,0x7F,0xFF,0xFF,0xFF,0xCF,0xEF,0xEF,0xC7,0x47,0x07,0x07,0x17,0x07,0x07,0x07,
0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x3F,0x1F,0x0F,
0x07,0x03,0x03,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xF0,0xF0,
0xF0,0xF8,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFE,0xFC,0xFC,0xF8,0xF0,0xF0,
0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x80,0xC0,0x80,0xA0,0xE0,0xE0,0xE0,0xE0,0xF0,
0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
0xFE,0xFE,0xFE,0xDC,0xDE,0xEC,0x8C,0xEC,0xE6,0x80,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,
0xE0,0xE0,0xE0,0xB0,0xD8,0xE0,0x80,0x8E,0xEC,0xDC,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,
0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0xFF,0x3F,0x3F,0xFF,0x3F,
0x3F,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
0xBF,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,
0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0x3F,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F,0xBF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0x7F,0x3F,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x98,0xD8,0x9F,0x88,0xA0,0x31,0x24,
0xAE,0x88,0xD2,0x96,0x9E,0xBE,0xFF,0xFF,0xFF,0xFF,0x00,0xFB,0xE1,0x20,0x39,0x20,
0x40,0x02,0xA0,0x20,0x22,0xA2,0xEE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x76,0x76,0x00,
0x00,0x76,0x76,0x76,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xEF,0xEF,0xEF,
0xEF,0x03,0x01,0xEC,0xEE,0xEE,0xEF,0xEF,0xEF,0xFF,0xFF,0xFF,0xFE,0xF2,0x26,0x06,
0x00,0x76,0xF1,0x70,0x06,0x06,0x36,0xF0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xE3,0x60,
0x28,0x2F,0xAF,0x00,0x00,0xEF,0xAF,0x2F,0x6F,0xEF,0xEF,0xFF,0xFF,0xFF,0xFF,0xCD,
0x4C,0x6E,0x2C,0x81,0x53,0x03,0x41,0xCC,0x5E,0x1F,0x9F,0xDF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFB,0xFA,0xF8,0xF8,0xFA,0xF8,0xF8,
0xFA,0xF8,0xF8,0xFA,0xFB,0xFB,0xFF,0xFF,0xFF,0xF8,0xF8,0xFB,0xFB,0xFA,0xFA,0xFA,
0xFA,0xFA,0xFA,0xFA,0xF6,0xF8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xF8,
0xF8,0xFB,0xFB,0xFB,0xFB,0xFB,0xF9,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,
0xFB,0xF8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFC,0xFE,0xFF,
0xFB,0xFA,0xF9,0xFC,0xFE,0xFF,0xFE,0xFC,0xF9,0xFB,0xFF,0xFF,0xFF,0xFD,0xFC,0xFC,
0xFE,0xFB,0xF3,0xF8,0xF8,0xFF,0xFF,0xFF,0xFE,0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xF3,
0xF3,0xFB,0xFB,0xFB,0xF9,0xF8,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
};

uchar k,DIR_NUM_FLAG;
bit KEY_FLAG;
bit KEY_FLAG5=0;                           //KEY_FLAG5是外部中断1的标志位 KEY_FLAG1是步进标志
uchar p,SNAKE_GRADE_NUM;               //定时次数
bit KEY_FLAG1=0;
//systemtime realtime;
bit first=1;                                   //中断次数控制

/****************************************************************************
** 函数名称:  void delay1ms(uint k)
** 功能描述:  1ms延时程序  
** 输 入:    uint k(需要延时的数量)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void delay1ms(uint k)
{
  k=k*125;
  while(k--);
}
/*******************************************************************************************
** 函数名称:  void Delay_S(void)   //延时1s误差 0us
** 功能描述:  精确延时函数,延时1秒,软件算得                                                
** 输 入:   
**         
**        
** 输 出:   
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void Delay_S(void)   //延时1s误差 0us
{
    unsigned char a,b,c;
    for(c=167;c>0;c--)
        for(b=171;b>0;b--)
            for(a=16;a>0;a--);
    _nop_();  //if Keil,require use intrins.h
}        
/****************************************************************************
** 函数名称:  void chekbusy12864(void)
** 功能描述:  12864判忙函数
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void chekbusy12864(void)
{
  uchar dat;
  EX0=0;
  LCD_RS_OUT=0;       //指令模式
  LCD_RW_OUT=1;       //读数据
do{
   P0=0x00;                         //
   LCD_E_OUT=1;
   dat=P0&0x80;
   LCD_E_OUT=0;
  }while(dat!=0x00);
  EX0=1;
}

/****************************************************************************
** 函数名称:  void CHOOSE_12864_SCREEN(uchar i)
** 功能描述:  选屏函数
** 输 入:    uchar i(i是要写的屏.0是左屏,1是右屏,2是双屏)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CHOOSE_12864_SCREEN(uchar i)  /*i是要写的屏.0是左屏,1是右屏,2是双屏;*/
{                                   /*此处在硬件上运行时i的电平全部与程序相反;*/
  switch (i)                           /*此版本为仿真版;*/
  {
    case 0: LCD_CS1_OUT=0;LCD_CS2_OUT=1;break;        //比如此处如果要在电路上运行则应该改为CS=1;LCD_CS2_OUT=0;   
    case 1: LCD_CS1_OUT=1;LCD_CS2_OUT=0;break;
    case 2: LCD_CS1_OUT=0;LCD_CS2_OUT=0;break;
    default: break;
  }
}

/****************************************************************************
** 函数名称:  void LCD_12864_CMD(uchar cmd)                //写命令
** 功能描述:  lcd12864写命令的函数
** 输 入:    uchar cmd(写入的命令)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void LCD_12864_CMD(uchar cmd)                //写命令
{
  chekbusy12864();
  EX0=0;
  LCD_RS_OUT=0;                    //指令模式
  LCD_RW_OUT=0;             //写模式
  LCD_E_OUT=1;
  P0=cmd;
  LCD_E_OUT=0;
  EX0=1;
}

/****************************************************************************
** 函数名称:  void  LCD_12864_DAT(uchar dat)                //写命令
** 功能描述:  lcd12864写数据的函数
** 输 入:    uchar dat(写入的数据)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void  LCD_12864_DAT(uchar dat)
{
  chekbusy12864();
  EX0=0;
  LCD_RS_OUT=1;
  LCD_RW_OUT=0;
  LCD_E_OUT=1;
  P0=dat;
  LCD_E_OUT=0;
  EX0=1;
}
/****************************************************************************
** 函数名称:  void CLEAR_12864_SCREEN(void)                //清屏函数
** 功能描述:  lcd12864清屏函数
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CLEAR_12864_SCREEN(void)
{
  uchar page,row;
  for(page=0xb8;page<0xc0;page++)
  {
    LCD_12864_CMD(page);
        LCD_12864_CMD(0x40);
        for(row=0;row<64;row++)
         {
           LCD_12864_DAT(0x00);          //对12864所有地址全部写零
         }
  }
}

/****************************************************************************
** 函数名称:  void Init_12864_HS(void)                //清屏函数
** 功能描述:  lcd12864初始化函数
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void Init_12864_HS(void)
{
  chekbusy12864();
  LCD_12864_CMD(0xc0);          //从第零行开始显示
  LCD_12864_CMD(0x3f);          //LCD显示RAM中的内容
}

/****************************************************************************
** 函数名称:  void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
** 功能描述:  lcd12864的8X16字符的显示
** 输 入:    uchar ch,uchar row,uchar page,uchar *p(屏数,列数,页数,还有显示的数组首地址)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/  
void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
{
  uchar i;
  CHOOSE_12864_SCREEN(ch);
  page=page<<1;                           //程序中采用的位移运算代替乘法运算,这样可以大大降低处理器的负担
  row=row<<3;
  LCD_12864_CMD(row+0x40);
  LCD_12864_CMD(page+0xb8);
  for(i=0;i<8;i++)
  {
    LCD_12864_DAT(*(adr+i));
  }
  LCD_12864_CMD(row+0x40);
  LCD_12864_CMD(page+0xb9);
  for(i=8;i<16;i++)
  {
    LCD_12864_DAT(*(adr+i));
  }
}

/****************************************************************************
** 函数名称:  void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
** 功能描述:  lcd12864的16X16显示字符的显示
** 输 入:    uchar ch,uchar row,uchar page,uchar *p(屏数,列数,页数,还有显示的数组首地址)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/  
void Display_16_point(uchar ch,uchar row,uchar page,uchar *adr)
{
  uchar i;
  CHOOSE_12864_SCREEN(ch);
  page=page<<1;                                          
  row=row<<3;
  LCD_12864_CMD(row+0x40);
  LCD_12864_CMD(page+0xb8);
  for(i=0;i<16;i++)
  {
    LCD_12864_DAT(*(adr+i));
  }
  LCD_12864_CMD(row+0x40);
  LCD_12864_CMD(page+0xb9);
  for(i=16;i<32;i++)
  {
    LCD_12864_DAT(*(adr+i));
  }
}

/****************************************************************************
** 函数名称:  uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
** 功能描述:  lcd12864的数据的读取
** 输 入:    uchar page,uchar arrange  (page页地址.arrange列地址)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
{
  uchar dat;
  chekbusy12864();
  EA=0;
  LCD_12864_CMD(page+0xb8);
  LCD_12864_CMD(arrange+0x40);
  EX0=0;                                                
  P0=0xff;
  LCD_RW_OUT=1;
  LCD_RS_OUT=1;
  LCD_E_OUT=1;
  LCD_E_OUT=0;                                 //12864读数据时第二次读才有效,第一次读取的值不采集
  LCD_E_OUT=1;
  dat=P0;
  LCD_E_OUT=0;
  EA=1;
  return(dat);
  //EX0=1;
}

/****************************************************************************
** 函数名称:  uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
** 功能描述:  lcd12864的反白显示
** 输 入:    uchar ch,uchar arrange,uchar page (屏数,列数,页数)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void Display_16_point_fb(uchar ch,uchar arrange,uchar page)
{
   uchar i;
   uchar xdata dat_fb[32];
   CHOOSE_12864_SCREEN(ch);
   for(i=0;i<16;i++)
   {
     dat_fb=~(DAT_READ_12864((page<<1),((arrange<<3)+i)));
         dat_fb[i+16]=~(DAT_READ_12864((page<<1)+1,((arrange<<3)+i)));
        }
   Display_16_point(ch,arrange,page,dat_fb);
}
/****************************************************************************
** 函数名称:  void DRAW_TRANSVERSE_Line(uchar y1,uchar y2,uchar x)//y1表示起点,y2表示终点
** 功能描述:  lcd12864的画竖线的函数
** 输 入:    uchar y1,uchar y2,uchar x(y1表示起点,y2表示终点)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void DRAW_TRANSVERSE_Line(uchar y1,uchar y2,uchar x)//y1表示起点,y2表示终点
{
  uchar i,sum=0;
  if(x>63)
   {
     CHOOSE_12864_SCREEN(1);                                         //y1比y2小,这里给出画竖线的函数而不用画点的方法
     x=x-64;                                                         //是为了减少单片机的处理负担。
   }
   else
   {
     CHOOSE_12864_SCREEN(0);
   }
  if((y1/8)!=(y2/8))
  {
   for(i=0;i<(8-y1%8);i++)         
   {
      sum=sum|((2<<((y1%8)+i)));
   }
  LCD_12864_CMD(x+0x40);
  LCD_12864_CMD(y1/8+0xb8);
  LCD_12864_DAT(sum);
  sum=0;
   for(i=0;i<(y2/8-y1/8-1);i++)
    {
     LCD_12864_CMD(x+0x40);
         LCD_12864_CMD((y1/8)+0xb9+i);
         LCD_12864_DAT(0xff);
    }
  for(i=0;i<=(y2%8);i++)
   {
     sum=sum|(2<    }
   LCD_12864_CMD(x+0x40);
   LCD_12864_CMD(y2/8+0xb8);
   LCD_12864_DAT(sum|1);
   sum=0;        
}
else
{
   for(i=0;i<=y2-y1;i++)
    {
          sum=sum|(2<<(i+(y1%8)));
        }
        LCD_12864_CMD(0x40|x);
        LCD_12864_CMD(0xb8|(y1/8));
        LCD_12864_DAT(sum);
}
}

/****************************************************************************
** 函数名称:  void DRAW_DOT_HS(uchar x,uchar y)
** 功能描述:  lcd12864的画点的函数
** 输 入:    uchar x,uchar y(x表示横坐标,y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void DRAW_DOT_HS(uchar x,uchar y)
{
  uchar dat;
  if(x>63)
  {
    CHOOSE_12864_SCREEN(1);
        x=x-64;
  }
  else
  {
    CHOOSE_12864_SCREEN(0);
  }
  dat=DAT_READ_12864(y/8,x);
  LCD_12864_CMD(0x40|x);
  LCD_12864_CMD(0xb8|y/8);
  LCD_12864_DAT((1<<(y%8))|dat);
}

/****************************************************************************
** 函数名称:  void CHANGE_HS(uchar *x,uchar *y)
** 功能描述:  lcd12864中将4X4个点合为一个
** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CHANGE_HS(uchar *x,uchar *y)     //x<24  y<15
{
  uchar i,m,n;                                           //24和15分别表示游戏的范围
  if(*x<24&&*y<15)                                   //这里的点是个有花色的点而不是一个实心的点
  {
   m=(*x)<<2;
   n=((*y)<<2)+2;
   for(i=0;i<4;i++)
   {
    DRAW_DOT_HS(31+m,n+i);
        DRAW_DOT_HS(34+m,n+i);
   }
   DRAW_DOT_HS(32+m,n);                 
   DRAW_DOT_HS(32+m,n+1);
   DRAW_DOT_HS(32+m,n+3);
   DRAW_DOT_HS(33+m,n);
   DRAW_DOT_HS(33+m,n+2);
   DRAW_DOT_HS(33+m,n+3);
  }
}

/****************************************************************************
** 函数名称:  void CLEAR_Dot_HS(uchar x,uchar y)
** 功能描述:  lcd12864的清点的函数
** 输 入:    uchar x,uchar y(x表示横坐标,y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CLEAR_Dot_HS(uchar x,uchar y)
{
  uchar dat,j;
  if(x>63)
  {
    CHOOSE_12864_SCREEN(1);
        x=x-64;
  }
  else
  {
    CHOOSE_12864_SCREEN(0);
  }
  dat=DAT_READ_12864(y/8,x);
  LCD_12864_CMD(0x40|x);
  LCD_12864_CMD(0xb8|(y/8));
  j=~(1<<(y%8));
  LCD_12864_DAT(dat&j);
}

/****************************************************************************
** 函数名称:  void clear(uchar *x,uchar *y)
** 功能描述:  lcd12864的清除一个4X4的点函数
** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CLEAR_4DOT_HS(uchar *x,uchar *y)
{
  uchar i,m,n;
  m=((*x)<<2)+31;
  n=((*y)<<2)+2;
  for(i=0;i<4;i++)
  {
    CLEAR_Dot_HS(m,n+i);
        CLEAR_Dot_HS(m+1,n+i);
        CLEAR_Dot_HS(m+2,n+i);
        CLEAR_Dot_HS(m+3,n+i);
  }
}  

/****************************************************************************
** 函数名称:  void CLEAR_4DOT_HS1(uchar *x,uchar *y)
** 功能描述:  lcd12864的清除一个4X4的点函数
** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void CLEAR_4DOT_HS1(uchar x,uchar y)
{
  uchar i,m,n;
  if(x>=0&&x<24&&y>=0&&y<15)
  {
   m=((x)<<2)+31;
   n=((y)<<2)+2;
   for(i=0;i<4;i++)
   {
    CLEAR_Dot_HS(m,n+i);
        CLEAR_Dot_HS(m+1,n+i);
        CLEAR_Dot_HS(m+2,n+i);
        CLEAR_Dot_HS(m+3,n+i);
   }
  }
}  

/****************************************************************************
** 函数名称:  bit readfk(char x,char y)
** 功能描述:  lcd12864的清除一个点函数
** 输 入:    char x,char y(x表示横坐标,y表示纵坐标)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
bit readfk(char x,char y)
{
  bit KEY_FLAGfk=0;
  uchar m,n;
  if(y>=0)
  {
  m=(x<<2)+31;
  n=(y<<2)+2;
  CHOOSE_12864_SCREEN(0);
  if(m>63)
  {
   m=m-64;
   CHOOSE_12864_SCREEN(1);
  }                                                                                                                                                               
  m = DAT_READ_12864(n>>3,m);
  if((n%8)==2)
  {
    if((m&0x3c)==0x3c)
        {
          KEY_FLAGfk=1;
         }
        else
        {
          KEY_FLAGfk=0;
        }
  }
   if((n%8)==6)
   {
    if((m&0xc0)==0xc0)
        {
           KEY_FLAGfk=1;
        }
        else
        {
          KEY_FLAGfk=0;
        }
   }
  }
  return(KEY_FLAGfk);
}
/****************************************************************************
** 函数名称:  void dingshi() interrupt 1  using 1
** 功能描述:  定时程序.产生步进时间
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void dingshi() interrupt 1  using 1  //定时程序.产生步进时间
{
   if(p--)
   {
    TL0=0;
        TH0=0xa0;
        KEY_FLAG1=0;
   }
   else
   {
     KEY_FLAG1=1;
         TL0=0;
         TH0=0x00;
         p=20-(SNAKE_GRADE_NUM>>1);
   }
}

/****************************************************************************
** 函数名称:  void zhongduan1() interrupt 2 using 2
** 功能描述:  开始确认暂停键的判断
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void zhongduan1() interrupt 2 using 2
{
   if(!KEY_FLAG5)
   {
     KEY_FLAG5=1;
   }
   else
   {
     KEY_FLAG5=0;
   }
}

/****************************************************************************
** 函数名称:  void INTERRUPT_NUM0() interrupt 0 using 0
** 功能描述:  方向键的判断
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void INTERRUPT_NUM0() interrupt 0 using 0
{
    uchar i=0;
        if(first)               //FIRST=1;打开方向按键判断标志
        {
        first=0;            
        k=(P2>>6);           
        k=k&0x03;                                
        if(KEY_FLAG)
          {
            if(k==1)     DIR_NUM_FLAG=3;//左
            if(k==2)         DIR_NUM_FLAG=1;//右
             }
          else
           {
            if(k==0)         DIR_NUM_FLAG=4;//上
            if(k==3)         DIR_NUM_FLAG=2;//下
             }
    }
}

/****************************************************************************
** 函数名称:  void Gluttonous_Snake(void)
** 功能描述:  贪吃蛇子程序
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void Gluttonous_Snake(void)                                                                                                           
{           
  uchar xdata SNK_BODY_Length[102]={0,8,1,8};         //存放蛇身的数组;
  uchar SNK_Food_Date[2]={12,8};
  uchar i,x,y;
  bit KEY_FLAG2,KEY_FLAG3,KEY_FLAG4;
  TMOD=1;          //定时器工作方式
  IT0=1;          //边延有效
  IT1=1;
  EA=1;                  //开CPU中断
  ET0=1;          //开定时器中断
  EX0=1;          //开外部中断
  EX1=1;
  TL0=0x00;
  TH0=0x00;          //定时器初值
  TR0=1;          //启动定时器
  SNAKE_GRADE_NUM=2;
  p=20;
  DIR_NUM_FLAG=1;
  KEY_FLAG5=0;
  CHOOSE_12864_SCREEN(2);
  CLEAR_12864_SCREEN();        
  DRAW_TRANSVERSE_Line(1,61,30);
  DRAW_TRANSVERSE_Line(1,61,127);
  for(i=0;i<98;i++)
  {
       DRAW_DOT_HS(30+i,1);
       DRAW_DOT_HS(30+i,62);
  }
  Display_16_point(0,0,0,TCS_TAN);
  Display_16_point(0,0,1,TCS_CHI);
  Display_16_point(0,0,2,TCS_SHE);
  CHANGE_HS(SNK_BODY_Length,(SNK_BODY_Length+1));
  CHANGE_HS((SNK_BODY_Length+2),(SNK_BODY_Length+3));
  CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  for(;;)
  {
    do
   {
    first=1;
    while(KEY_FLAG5|!KEY_FLAG1);
    x=*(SNK_BODY_Length);                              
    y=*(SNK_BODY_Length+1);
    switch(DIR_NUM_FLAG)                           //右
        {
          case 1:
            {
              for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
               (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))++;
                   KEY_FLAG=0;
                   break;
              }
                   case 2:                                          //下
                 {
              for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
                    (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))++;
                        KEY_FLAG=1;
                        break;
                  }
                case 3:                                        //左
                 {
               for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
               (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))--;
                   KEY_FLAG=0;
                   break;
                 }
                case 4:
                 {                        //上
                 for(i=0;i                {
                 *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
                     *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
               }
                    (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))--;
                        KEY_FLAG=1;
                        break;
                 }
         }
         KEY_FLAG4=((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))==SNK_Food_Date[0])&&((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))==SNK_Food_Date[1]);
         if(KEY_FLAG4)        //
         {
                for(i=SNAKE_GRADE_NUM;i>0;i--)
                {
                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)-2);
                  *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)-1);
                }
                *SNK_BODY_Length=x;
                *(SNK_BODY_Length+1)=y;
                SNAKE_GRADE_NUM++;
                do
                {
                  KEY_FLAG3=0;
                  SNK_Food_Date[0]=TL0%24;
              SNK_Food_Date[1]=TL0%15;
                  for(i=0;i                   {
                    if((*(SNK_BODY_Length+(i<<1)))==SNK_Food_Date[0]&&((*(SNK_BODY_Length+(i<<1)+1))==SNK_Food_Date[1]))
                        {
                          KEY_FLAG3=1;
                          break;
                         }
                  }
                }while(KEY_FLAG3);
                CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
         }
     KEY_FLAG2=1;          //蛇头没有遇到蛇身
         for(i=0;i         {
                   if(*(SNK_BODY_Length+(i<<1))==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)&&(*(SNK_BODY_Length+(i<<1)+1)==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)))
                   {
                     KEY_FLAG2=0;
                         break;
                        }
                }
          KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)<24;//蛇头是否出边界
          KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)<15;
          if(KEY_FLAG2)
           {
            CLEAR_4DOT_HS(&x,&y);
               
            
             {
               CHANGE_HS(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2,SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1);
             }
                 if(KEY_FLAG4)
                 {
                   CHANGE_HS(&x,&y);
                  }
            KEY_FLAG1=0;
            Display_8_point(0,0,3,NUM0+((SNAKE_GRADE_NUM/10)<<4));
            Display_8_point(0,1,3,NUM0+(((SNAKE_GRADE_NUM)%10)<<4));
           }
   }
   while(KEY_FLAG2);
   delay1ms(450);
   delay1ms(450);
   CHOOSE_12864_SCREEN(2);
   CLEAR_12864_SCREEN();
   Display_16_point(0,4,1,GAME_OVER);
   Display_16_point(0,6,1,GAME_OVER+32);
   Display_16_point(1,0,1,GAME_OVER+64);
   Display_16_point(1,2,1,GAME_OVER+96);
   delay1ms(450);
   delay1ms(450);
   break;
  }
}
/*******************************************************************************************
** 函数名称:  void CHECK_busy()
** 功能描述:  读“忙”函数,判断液晶当前是否忙碌  
** 输 入:     
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void CHECK_busy()//读“忙”函数-----数据线的最高位DB71则busy               
{
        P0=0x00;
           LCD_RS_OUT=0;  
           LCD_RW_OUT=1;
        LCD_E_OUT=1;
        while(P0 & 0x80);
        LCD_E_OUT=0;
}
/*******************************************************************************************
** 函数名称:  void LCD_COM_WRI(uchar value)
** 功能描述:  LCD液晶写命令函数  
** 输 入:    uchar value(向LCD写入的命令)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void LCD_COM_WRI(uchar value)        //写命令函数
{
   CHECK_busy();                                                //对LCD的每次读写都要读忙
   LCD_RS_OUT=0;                                                         //选择命令
   LCD_RW_OUT=0;                                                         //读操作
   LCD_12864_DATA = value;
   LCD_E_OUT=1;                                                        //LCD_EN_OUT由1----0锁存有效数据
   _nop_();
   _nop_();
   LCD_E_OUT=0;
}
/*******************************************************************************************
** 函数名称:  void LCD_DATA_WRI(uchar value)
** 功能描述:  LCD液晶写数据的函数  
** 输 入:    uchar value(向LCD写入的数据)
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void LCD_DATA_WRI(uchar value)//写数据函数        
{
   CHECK_busy();
   LCD_RS_OUT=1;                                                 //选择数据
   LCD_RW_OUT=0;        
   LCD_12864_DATA = value;
   LCD_E_OUT=1;                                                //LCD_EN_OUT由1----0锁存有效数据
   _nop_();               
   _nop_();
   LCD_E_OUT=0;
}
/*******************************************************************************************
** 函数名称:  void CHOOSE_COLUMN(uchar column)
** 功能描述:  设置显示的列
** 输 入:    uchar column(设置显示的列)
**         
**        
** 输 出:   
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void CHOOSE_COLUMN(uchar column)        //设置显示的列        
{
  column=column &0x3f;                         //列的最大值为64
  column= 0x40|column;                         //列的首地址为0x40
  LCD_COM_WRI(column);        //规定显示的列的位置
}
/*******************************************************************************************
** 函数名称:  void CHOOSE_PG(uchar page)
** 功能描述:  设置“页”LCD12864共8页,一页是8行点阵点
** 输 入:    uchar page(送入设置的页数)
**         
**        
** 输 出:   
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void CHOOSE_PG(uchar page)                //设置“页”LCD12864共8页,一页是8行点阵点        
{
  page=0xb8|page;                                 //页的首地址为0xB8
  LCD_COM_WRI(page);
}
/*******************************************************************************************
** 函数名称:  void SEL_SCREN(uchar screen)
** 功能描述:  LCD选择屏幕  
** 输 入:    uchar screen(选择屏幕0:全屏  1:左半屏 2:右半屏)  
**         
**        
** 输 出:   
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.03.26
********************************************************************************************/
void SEL_SCREN(uchar screen)        //选择屏幕
{                                                  
   switch(screen)
   {
            case 0: LCD_CS1_OUT=0;LCD_CS2_OUT=0;break; //全屏     
     case 1: LCD_CS1_OUT=0;LCD_CS2_OUT=1;break;//左半屏        
     case 2: LCD_CS1_OUT=1;LCD_CS2_OUT=0;break;//右半屏      
     default:break;
   }
}
/*******************************************************************************************
** 函数名称:  void Display_picture(uchar a[][64])
** 功能描述:  显示图片的函数  
** 输 入:    uchar a[][64](存放图片的数组)  
**         
**        
** 输 出:   
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 日 期:     14.04.09
********************************************************************************************/
void GUI_CLEAR(uchar a[][64])//显示图形—128*64大小
{
        uchar i,j;
        
        for(j=0;j<8;j++)
        {        
                SEL_SCREN(1);
                CHOOSE_PG(j);
                CHOOSE_COLUMN(0);
                for(i=0;i<64;i++)
                {
                        LCD_DATA_WRI(a[2*j]);//每隔一行取一次数组中的数据
                }
                SEL_SCREN(2);
                CHOOSE_PG(j);
                CHOOSE_COLUMN(0);
                for(i=0;i<64;i++)
                {
                        LCD_DATA_WRI(a[2*j+1]);//每隔一行取一次数组中的数据
                }        
        }        
}

/****************************************************************************
** 函数名称:  void main(void)
** 功能描述:  贪吃蛇主函数
** 输 入:   
**         
**        
** 输 出:
**         
** 全局变量:
** 调用模块:
**
** 作 者:    吴鉴鹰
** 作者所在单位:鉴鹰电子工作室
** 日 期:     14.04.9
****************************************************************************/
void main()
{
          uchar i;
          uchar count=0;   
          P2=0xff;
          EA=1;                  //开CPU中断
          //ET0=1;          //开定时器中断
          EX0=1;          //开外部中断
          EX1=1;
          CHOOSE_12864_SCREEN(2);
          Init_12864_HS();
          CLEAR_12864_SCREEN();
         
         
         ////////////////////
         Display_16_point(0,4,0,TCS_TAN);
         Display_16_point(0,6,0,TCS_CHI);
         Display_16_point(1,0,0,TCS_SHE);
         ///////////////////
         Display_16_point(0,2,1,WJYZZ);
         Display_16_point(0,4,1,WJYZZ+32);
         Display_16_point(0,6,1,WJYZZ+64);
         for(i=0;i<2;i++)
         {
           Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
         }
        Display_16_point(0,0,0,WWJJYYWXTP);
        Display_16_point(0,2,0,WWJJYYWXTP);
        Display_16_point(1,2,0,WWJJYYWXTP);
        Display_16_point(1,4,0,WWJJYYWXTP);
        Display_16_point(1,6,0,WWJJYYWXTP);
        
        Display_16_point(0,0,1,WWJJYYWXTP);
        Display_16_point(1,4,1,WWJJYYWXTP);
        Display_16_point(1,6,1,WWJJYYWXTP);
        
        
         //////////////////
        for(i=0;i<4;i++)
        {
            Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
        }
        for(i=0;i<4;i++)
        {
            Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
        }

        for(i=0;i<4;i++)
        {
            Display_16_point(0,i<<1,3,(WWJJYYJ+(i<<5))) ;
        }
        for(i=0;i<4;i++)
        {
            Display_16_point(1,i<<1,3,(WWJJYYHH+(i<<5))) ;
        }
            Delay_S(); Delay_S();Delay_S();
         GUI_CLEAR(table);
         // while(1);
         Delay_S(); Delay_S();Delay_S();
     Delay_S(); Delay_S();Delay_S();
         //Display_16_point(0,4,2,wnl);
         //Display_16_point(0,6,2,wnl+32);
         //Display_16_point(1,0,2,wnl+64);
         
         //////////////////
   for(;;)
  {
    if((k==0x03)&&((P3&0x04)==0x04))
   {
        count++;
        k=0;
        if(count==4)
        count=1;
        switch(count)
        {
          case 1:
     {
                 /*Display_16_point(0,4,2,wnl);
         Display_16_point(0,6,2,wnl+32);
         Display_16_point(1,0,2,wnl+64);
                  Display_16_point_fb(0,4,0);
         Display_16_point_fb(0,6,0);
         Display_16_point_fb(1,0,0); */
                 for(i=0;i<4;i++)
            {
                Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
            }
                for(i=0;i<4;i++)
            {
                Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
               }
         };break;
          case 2:
          {
                 Display_16_point(0,4,0,TCS_TAN);
             Display_16_point(0,6,0,TCS_CHI);
             Display_16_point(1,0,0,TCS_SHE);
                 Display_16_point_fb(0,4,1);
             Display_16_point_fb(0,6,1);
             for(i=0;i<3;i++)
             {
               Display_16_point_fb(1,i<<1,1);
              }
            };break;
          case 3:
      {         
             Display_16_point(0,2,1,WJYZZ);
                 Display_16_point(0,4,1,WJYZZ+32);
                 Display_16_point(0,6,1,WJYZZ+64);
                 for(i=0;i<2;i++)
                 {
                   Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
                 }
                 Display_16_point_fb(0,4,2);
         Display_16_point_fb(0,6,2);
         Display_16_point_fb(1,0,2);
      };break;
        default:break;
        }
  }
  if(P3&0x04)
  first=1;
  if(KEY_FLAG5)
  {
     KEY_FLAG5=0;Gluttonous_Snake();count=0;KEY_FLAG5=0;k=0;
     switch(count)
        {
           case 0:count=0;k=3;KEY_FLAG5=0;break;
           case 1:KEY_FLAG5=0;Gluttonous_Snake();count=0;KEY_FLAG5=0;k=0;break;
           //case 2:KEY_FLAG5=0;fangkuai();count=0;KEY_FLAG5=0; k=0;break;
           //case 3:KEY_FLAG5=0;wannianli();count=0;KEY_FLAG5=0;k=0;break;
           default:count=0;k=3;KEY_FLAG5=0;break;
        }        
         CHOOSE_12864_SCREEN(2);
     Init_12864_HS();
     CLEAR_12864_SCREEN();
/////////////////////////////////////
     Display_16_point(0,4,0,TCS_TAN);
     Display_16_point(0,6,0,TCS_CHI);
     Display_16_point(1,0,0,TCS_SHE);
////////////////////////////////////
     Display_16_point(0,2,1,WJYZZ);
         Display_16_point(0,4,1,WJYZZ+32);
         Display_16_point(0,6,1,WJYZZ+64);
         for(i=0;i<2;i++)
         {
           Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
         }
     /*Display_16_point(0,4,1,WJYZZ);
     Display_16_point(0,6,1,WJYZZ+32);
     for(i=0;i<3;i++)
     {
       Display_16_point(1,i<<1,1,(WJYZZ+64+(i<<5)));
     } */
//////////////////
     //Display_16_point(0,4,2,wnl);
     // Display_16_point(0,6,2,wnl+32);
     //Display_16_point(1,0,2,wnl+64);
//////////////////
  }
}
}


为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-29 23:43 | 显示全部楼层
31、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(四)——完整程序


这一连的几讲内容,鹰哥会向大家介绍贪吃蛇的设计思路,设计方法以及程序的编写,向大家详细介绍贪吃蛇的设计思路,让大家对如此神秘的贪吃蛇有深入的认识!

这是鹰哥大学的时候做的贪吃蛇游戏(图片1)

贪吃蛇介绍: 鹰哥首先来给大家介绍一下贪吃蛇,贪吃蛇是世界知名的益智类小游戏,鹰哥选择这个项目的原因是为了将我们自己的所学知识加以运用;另一方面,虽然我们很小就接触这个游戏,那时候用设计玩,觉得很有意思,但是它的制作方法对我们而言还是很神秘的。鹰哥希望通过自己的所学知识把它剖析开来,通过自己的动手实践,真正的了解它的本质和精髓。


这是鹰哥大学的时候做的贪吃蛇游戏(图片2)

希望通过这次实践,大家能从中提高自己的编程能力。并从中学会从零开始分析设计程序。
在以下一些列的章节中,会详细介绍贪吃蛇设计的每一个环节,对于大家如果有更好的方法或者建议,吴鉴鹰欢迎大家提供!



游戏整体流程:这个游戏流程图描述了整个游戏的总体运行过程。在开始游戏后对蛇与食物重绘,以及屏幕上的相关信息绘制。当蛇碰到石头或是咬到自己,就捕捉异常,游戏就结束。




游戏规则:游戏中玩家可以通过键盘控制游戏中的贪吃蛇的运动,当蛇头碰到系统产生的食物时加长蛇身。当蛇碰到石头或者自己的身体时,游戏结束。游戏玩家还可以通过鼠标来控制蛇的移动。
游戏规则:
1、 玩家通过键盘控制蛇在游戏区中运动;
2、 当蛇头碰到食物时,得分增加,蛇身增长一个单位;
3、 当蛇头碰到蛇身或者石头,游戏结束;
要求实现以下功能:
玩家可以通过按键来控制贪吃蛇吃食物,游戏过程中还配有音效渲染气氛。


游戏设计思路:贪吃蛇游戏是一款非常经典的游戏,已经有很多版本的贪吃蛇游戏,游戏的玩法各版本大体相同。以下是本课题的贪吃蛇游戏设计的一些简单的说明: 1、 先设置一个主控面板;
2、 依次向面板中添加蛇,食物,石头;
3、 设法引导贪吃蛇吞掉食物以使它变得更长;
4、 添加监听程序,通过方向键来改变蛇的运动方向;
5、 添加监听程序,通过按键来改变蛇的运动方向;
6、 蛇不能吃到石头或是自己的身体,如果吃到石头或者自己的身体,游戏结束;
7、 蛇吃食物或者死掉的时候都有特定的音效产生,我们这里由于没有蜂鸣器,所以这个程序没加,感兴趣的读者可以自己加上去试试!





算法中的基本概念:
节:一条蛇可以看成由许多圆拼凑成,把它称作节。节是贪吃蛇身上最小的单位。
坐标系:坐标以左上角那点为(0,0),向右则x 递增,向下则y 递增。
链表:用来保存每一节的状态,链表的第一个元素表示蛇的头部结点。



蛇、石头、食物的表示:
我们可以把显示区域想象成一个大大的表格,里面的格子就是组成蛇的基本单位,一个格子可以代表一个食物,也可以代表一个石头,几块连在一起的石头就可以代表一条蛇。使用坐标来区分这些格子。
这里我们用一个集合来存储这些坐标,并且要求能够区分出蛇头和蛇尾。



蛇的移动:
蛇向前移动一步,可以看作是蛇头前面增加了一个节点,蛇的尾巴上少了一个节点(即去尾,加头)


存储蛇身的数据结构
由于要区分蛇头和蛇尾,我们必须用一个有顺序的数组表示,另一方面,我们需要经常的访问第一个和最后一个节点。


蛇的移动方向
这里讨论蛇的移动方向控制。
蛇下一步移动到哪里,是由方向来控制的。
这里我们用int型常量来表示蛇的移动方向。
因为我们是根据原蛇头的坐标和方向来确定新蛇头的坐标。在原坐标的基础上,根据蛇头的运动方向来确定新蛇头的坐标,比如向上移动就是y-1.

如何显示蛇身
显示蛇身,其实就是填充用颜色填充格子。
需要4个参数,像素坐标x,像素坐标y,格子宽度,格子高度。
像素坐标就是矩形左上角的坐标

蛇身的移动方向
1 相反方向
和上一次移动的方向相反的方向称为相反方向,这种输入应该忽略。这样可以防止蛇从自己的身体中穿过。
2 无效方向
在蛇的这一次移动之后和下一次移动之前这个时间间隔内输入了多个非相反方向,只有最后一个是有效方向,其他的都是无效方向。
蛇的最终运动方向以有效方向为准。

吃到食物判定
这里通过判定坐标是否重合来判断,只需要判断蛇头是否和食物重合就可以了,因为蛇的身体都是走蛇头走过的地方



这是程序的设计思路:
(1) 初始化蛇的相关信息;
(2) 初始化食物的相关信息;
(3)输出初始化分数;
(4)当玩家没有按“ESC”键时,一直重复以下各步;
(5) 当玩家不按任何键时,一直重复6—13各步骤;
(6) 在屏幕画出食物;
(7) 计算出蛇的每一节在屏幕中的位置;
(8) 根据蛇的移动方向,计算出下一步蛇头的坐标位置;
(9) 判断蛇头是不是撞上了自己的身体的任何一节,如果是,游戏结束;
(10) 判断蛇头是不是撞到饿了任何一面的墙壁了,如果是,游戏结束;
(11) 若(9)(10)都未发生,说明蛇活着,判断蛇是否吃到了食物,如果吃到了食物,则要先清除食物,并设置下一个食物的出现;同时,还要将蛇的身体增长一节;屏幕显示的分数还要增加。
(12) 将蛇在屏幕显示,然后游戏延迟一会儿,给玩家一点反应时间;
(13) 蛇在移动的过程中,蛇头不断前进,末尾一节不断清除,这样才能保证蛇在移动的过程中的正确性;
(14)当玩家按下一个键时,接收该按键,并判断是不是“ESC”;如果是,则退出游戏,如果不是则进行(15)步的判断;(15) 判断当前按键的方向是否与蛇头的方向相反,如果相反,则不做处理,因为蛇是不会退的,只要不是相反的,则就改变蛇的移动方向。回到(14)步去执行,一直循环往复,直到游戏结束。


程序代码:
  1. /****************************************************************************
  2. ** 函数名称:  void Gluttonous_Snake(void)
  3. ** 功能描述:  贪吃蛇子程序
  4. ** 输 入:   
  5. **         
  6. **        
  7. ** 输 出:
  8. **         
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者:    吴鉴鹰
  13. ** 作者所在单位:鉴鹰电子工作室
  14. ** 日 期:     14.04.9
  15. ****************************************************************************/
  16. void Gluttonous_Snake(void)                                                                                                           
  17. {           
  18.   uchar xdata SNK_BODY_Length[102]={0,8,1,8};         //存放蛇身的数组;
  19.   uchar SNK_Food_Date[2]={12,8};
  20.   uchar i,x,y;
  21.   bit KEY_FLAG2,KEY_FLAG3,KEY_FLAG4;
  22.   TMOD=1;          //定时器工作方式
  23.   IT0=1;          //边延有效
  24.   IT1=1;
  25.   EA=1;                  //开CPU中断
  26.   ET0=1;          //开定时器中断
  27.   EX0=1;          //开外部中断
  28.   EX1=1;
  29.   TL0=0x00;
  30.   TH0=0x00;          //定时器初值
  31.   TR0=1;          //启动定时器

  32.   SNAKE_GRADE_NUM=2;
  33.   p=20;
  34.   DIR_NUM_FLAG=1;
  35.   KEY_FLAG5=0;

  36.   CHOOSE_12864_SCREEN(2);
  37.   CLEAR_12864_SCREEN();        
  38.   DRAW_TRANSVERSE_Line(1,61,30);
  39.   DRAW_TRANSVERSE_Line(1,61,127);
  40.   for(i=0;i<98;i++)
  41.   {
  42.        DRAW_DOT_HS(30+i,1);
  43.        DRAW_DOT_HS(30+i,62);
  44.   }
  45.   Display_16_point(0,0,0,TCS_TAN);
  46.   Display_16_point(0,0,1,TCS_CHI);
  47.   Display_16_point(0,0,2,TCS_SHE);
  48.   CHANGE_HS(SNK_BODY_Length,(SNK_BODY_Length+1));
  49.   CHANGE_HS((SNK_BODY_Length+2),(SNK_BODY_Length+3));
  50.   CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  51.   for(;;)
  52.   {
  53.     do
  54.    {
  55.     first=1;
  56.     while(KEY_FLAG5|!KEY_FLAG1);
  57.     x=*(SNK_BODY_Length);                              
  58.     y=*(SNK_BODY_Length+1);
  59.     switch(DIR_NUM_FLAG)                           //右
  60.         {
  61.           case 1:
  62.             {
  63.               for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  64.                {
  65.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  66.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  67.                }
  68.                (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))++;
  69.                    KEY_FLAG=0;
  70.                    break;
  71.               }
  72.                    case 2:                                          //下
  73.                  {
  74.               for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  75.                {
  76.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  77.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  78.                }
  79.                     (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))++;
  80.                         KEY_FLAG=1;
  81.                         break;
  82.                   }
  83.                 case 3:                                        //左
  84.                  {
  85.                for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  86.                {
  87.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  88.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  89.                }
  90.                (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))--;
  91.                    KEY_FLAG=0;
  92.                    break;
  93.                  }
  94.                 case 4:
  95.                  {                        //上
  96.                  for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  97.                {
  98.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  99.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  100.                }
  101.                     (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))--;
  102.                         KEY_FLAG=1;
  103.                         break;
  104.                  }
  105.          }
  106.          KEY_FLAG4=((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))==SNK_Food_Date[0])&&((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))==SNK_Food_Date[1]);
  107.          if(KEY_FLAG4)        //
  108.          {
  109.                 for(i=SNAKE_GRADE_NUM;i>0;i--)
  110.                 {
  111.                   *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)-2);
  112.                   *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)-1);
  113.                 }
  114.                 *SNK_BODY_Length=x;
  115.                 *(SNK_BODY_Length+1)=y;
  116.                 SNAKE_GRADE_NUM++;
  117.                 do
  118.                 {
  119.                   KEY_FLAG3=0;
  120.                   SNK_Food_Date[0]=TL0%24;
  121.               SNK_Food_Date[1]=TL0%15;
  122.                   for(i=0;i<SNAKE_GRADE_NUM-1;i++)         //食物是否在蛇身身上
  123.                   {
  124.                     if((*(SNK_BODY_Length+(i<<1)))==SNK_Food_Date[0]&&((*(SNK_BODY_Length+(i<<1)+1))==SNK_Food_Date[1]))
  125.                         {
  126.                           KEY_FLAG3=1;
  127.                           break;
  128.                          }
  129.                   }
  130.                 }while(KEY_FLAG3);
  131.                 CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  132.          }
  133.      KEY_FLAG2=1;          //蛇头没有遇到蛇身
  134.          for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  135.         {
  136.                    if(*(SNK_BODY_Length+(i<<1))==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)&&(*(SNK_BODY_Length+(i<<1)+1)==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)))
  137.                    {
  138.                      KEY_FLAG2=0;
  139.                          break;
  140.                         }
  141.                 }
  142.           KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)<24;//蛇头是否出边界
  143.           KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)<15;
  144.           if(KEY_FLAG2)
  145.            {
  146.             CLEAR_4DOT_HS(&x,&y);
  147.                
  148.             
  149.              {
  150.                CHANGE_HS(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2,SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1);
  151.              }
  152.                  if(KEY_FLAG4)
  153.                  {
  154.                    CHANGE_HS(&x,&y);
  155.                   }
  156.             KEY_FLAG1=0;
  157.             Display_8_point(0,0,3,NUM0+((SNAKE_GRADE_NUM/10)<<4));
  158.             Display_8_point(0,1,3,NUM0+(((SNAKE_GRADE_NUM)%10)<<4));
  159.            }
  160.    }
  161.    while(KEY_FLAG2);
  162.    delay1ms(450);
  163.    delay1ms(450);
  164.    CHOOSE_12864_SCREEN(2);
  165.    CLEAR_12864_SCREEN();
  166.    Display_16_point(0,4,1,GAME_OVER);
  167.    Display_16_point(0,6,1,GAME_OVER+32);
  168.    Display_16_point(1,0,1,GAME_OVER+64);
  169.    Display_16_point(1,2,1,GAME_OVER+96);
  170.    delay1ms(450);
  171.    delay1ms(450);
  172.    break;
  173.   }
  174. }


  175. /******************************************************
  176. **作品:LCD12864贪吃蛇设计                                                           
  177. **
  178. ** 这一讲的主要内容:  LCD12664液晶显示原理                                                                                       
  179. ** 功能描述:  对吴鉴鹰贪吃蛇设计的显示
  180. ** 输 入:
  181. ** 液晶:Proteus元件库—AMPIRE128X64(无字库)         
  182. ** 内容:LCD12864俄罗斯方块设计      
  183. ** 输 出:
  184. **         
  185. ** 全局变量:
  186. ** 调用模块:
  187. **
  188. ** 作 者:    吴鉴鹰
  189. ** 日 期:     14.04.9
  190. **作者所属单位:鉴鹰电子工作室
  191. **交流QQ群: 第一群: 332164870  第二群:194314772   联系QQ:1123942529
  192. **申明:转载请标明作品来源 知识产权归作者吴鉴鹰所有!

  193. 备注:有什么错误的地方,欢迎各大烧友指正

  194. O(∩_∩)O~
  195. *******************************************************/

  196. #include <at89x51.h>
  197. #include <intrins.h>
  198. #include<stdlib.h>
  199. #include<math.h>


  200. #define uchar unsigned char
  201. #define uint unsigned int           //宏定义  */
  202. #define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};

  203. /*************************************
  204. ** 模块名称:LCD12864 端口定义
  205. ** 作用:定义液晶屏IO口的定义
  206. ** LCD_RS_OUT为0---命令;1----数据
  207. ** LCD_RW_OUT为1---写;0---读
  208. ** LCD_E_OUT使能端
  209. ** LCD_CS1_OUT片选1低电平有效,控制左半屏
  210. ** LCD_CS2_OUT片选1低电平有效,控制右半屏  
  211. *************************************/
  212. sbit LCD_E_OUT  = P2^0;   
  213. sbit LCD_RW_OUT = P2^1;
  214. sbit LCD_RS_OUT = P2^2;
  215. sbit LCD_CS2_OUT = P2^3;
  216. sbit LCD_CS1_OUT = P2^4;

  217. #define LCD_12864_DATA  P0                        

  218. uchar code NUM0[]={0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00};/*"0",0*/
  219. uchar code NUM1[]={0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00};/*"1",0*/
  220. uchar code NUM2[]={0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00};/*"2",0*/
  221. uchar code NUM3[]={0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00};/*"3",0*/
  222. uchar code NUM4[]={0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00};/*"4",0*/
  223. uchar code NUM5[]={0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00};/*"5",0*/
  224. uchar code NUM6[]={0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00};/*"6",0*/
  225. uchar code NUM7[]={0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00};/*"7",0*/
  226. uchar code NUM8[]={0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00};/*"8",0*/
  227. uchar code NUM9[]={0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00};/*"9",0*/

  228. uchar code GAME_OVER[]=
  229. {
  230. 0x00,0x20,0x44,0x08,0x20,0xE0,0x92,0x94,0x10,0x28,0xAE,0x68,0x24,0x04,0x00,0x00,
  231. 0x00,0x0C,0x03,0x04,0x02,0x19,0x0C,0x03,0x02,0x12,0x22,0x1F,0x01,0x01,0x01,0x00,/*"游",0*/
  232. 0x00,0x20,0xA0,0x90,0x10,0xF0,0x00,0x40,0x7F,0xC0,0x20,0x24,0x88,0x00,0x00,0x00,
  233. 0x10,0x08,0x04,0x02,0x01,0x02,0x14,0x10,0x08,0x05,0x06,0x09,0x10,0x20,0x38,0x00,/*"戏",1*/
  234. 0x00,0x60,0x50,0xCC,0x40,0x30,0x40,0x40,0x40,0xFE,0x20,0x20,0x20,0x20,0x00,0x00,
  235. 0x00,0x12,0x13,0x0A,0x09,0x05,0x00,0x3A,0x2A,0x25,0x25,0x15,0x1D,0x00,0x00,0x00,/*"结",2*/
  236. 0x00,0x00,0x00,0x60,0xA8,0xA8,0xA8,0xFF,0x94,0x54,0x70,0x00,0x00,0x00,0x00,0x00,
  237. 0x10,0x10,0x08,0x08,0x04,0x02,0x01,0x7F,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x00 /*"束",3*/
  238. };
  239. uchar code TCS_TAN[]=
  240. {
  241. 0x20,0x20,0x10,0x90,0xA8,0xA4,0xAA,0xB1,0xA2,0xE4,0xA8,0x88,0x10,0x30,0x10,0x00,
  242. 0x00,0x00,0x80,0x9F,0x40,0x20,0x10,0x0E,0x10,0x20,0x60,0xDF,0x00,0x00,0x00,0x00,/*"贪",0*/
  243. };
  244. uchar code TCS_CHI[]=
  245. {
  246. 0x00,0xFC,0x04,0x04,0xFC,0x20,0x58,0x4F,0x4A,0x48,0x48,0xC8,0x08,0x08,0x08,0x00,
  247. 0x00,0x0F,0x02,0x02,0x07,0x00,0x30,0x48,0x44,0x42,0x41,0x40,0x40,0x40,0x70,0x00/*"吃",1*/
  248. };
  249. uchar code TCS_SHE[]=
  250. {
  251. 0x00,0xF0,0x10,0xFF,0x10,0xF0,0x20,0x18,0xE8,0x09,0x0E,0x0A,0xA8,0x18,0x08,0x00,
  252. 0x20,0x23,0x21,0x1F,0x11,0x3B,0x10,0x00,0x3F,0x42,0x41,0x41,0x40,0x38,0x00,0x00/*"蛇",2*/
  253. };

  254. uchar code WJYZZ[]=
  255. {
  256. /*--  文字:  吴  --*/
  257. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  258. 0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,0x00,
  259. 0x84,0x84,0x44,0x44,0x24,0x14,0x0C,0x07,0x0C,0x14,0x24,0x44,0x44,0x84,0x84,0x00,

  260. /*--  文字:  鉴  --*/
  261. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  262. 0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
  263. 0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,

  264. /*--  文字:  鹰  --*/
  265. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  266. 0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
  267. 0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,

  268. /*--  文字:  制  --*/
  269. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  270. 0x40,0x50,0x4E,0x48,0x48,0xFF,0x48,0x48,0x48,0x40,0xF8,0x00,0x00,0xFF,0x00,0x00,
  271. 0x00,0x00,0x3E,0x02,0x02,0xFF,0x12,0x22,0x1E,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,

  272. /*--  文字:  作  --*/
  273. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  274. 0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
  275. 0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,


  276. };
  277. uchar code wnl[]=
  278. {0x00,0x02,0x02,0x02,0x02,0x82,0x7E,0x22,0x22,0x22,0x22,0xF2,0x22,0x02,0x02,0x00,
  279. 0x00,0x40,0x20,0x10,0x0C,0x03,0x00,0x00,0x20,0x60,0x20,0x1F,0x00,0x00,0x00,0x00,/*"万",0*/

  280. 0x40,0x20,0x10,0x0C,0xE3,0x22,0x22,0x22,0xFE,0x22,0x22,0x22,0x22,0x02,0x00,0x00,
  281. 0x04,0x04,0x04,0x04,0x07,0x04,0x04,0x04,0xFF,0x04,0x04,0x04,0x04,0x04,0x04,0x00,/*"年",1*/

  282. 0x00,0x00,0xFE,0x02,0x22,0x22,0x22,0x22,0xFA,0x22,0x22,0x22,0xE2,0x02,0x02,0x00,
  283. 0x40,0x30,0x0F,0x00,0x40,0x20,0x18,0x06,0x01,0x00,0x20,0x60,0x3F,0x00,0x00,0x00};/*"历",2*/
  284. uchar code moxing[]=
  285. {0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,0x10,0x21,0x20,0x11,
  286. 0x11,0x12,0x10,0x13,0x01,0x31,0x11,0x21,0x11,0x12,0x10,0x13,0x01,0x31,0x11,0x21,
  287. 0x01,0x21,0x10,0x11,0x11,0x21,0x10,0x12,0x00,0x20,0x10,0x11,0x01,0x11,0x10,0x12,
  288. 0x10,0x21,0x20,0x22,0x01,0x21,0x20,0x11,0x11,0x22,0x10,0x12,0x10,0x30,0x20,0x11,
  289. 0x11,0x20,0x10,0x12,0x00,0x20,0x10,0x21,0x12,0x21,0x20,0x22,0x11,0x31,0x10,0x21,
  290. 0x11,0x21,0x10,0x22,0x01,0x20,0x10,0x11,0x11,0x21,0x10,0x22,0x01,0x20,0x10,0x11,
  291. 0x11,0x21,0x20,0x12,0x10,0x31,0x20,0x21,0x11,0x21,0x20,0x12,0x10,0x31,0x20,0x21
  292. };


  293. uchar code WJYW[]=
  294. {
  295. /*--  文字:  吴  --*/
  296. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  297. 0x00,0x00,0x80,0x9E,0x92,0x92,0x92,0x92,0x92,0x92,0x92,0x9E,0x80,0x00,0x00,0x00,
  298. 0x84,0x84,0x44,0x44,0x24,0x14,0x0C,0x07,0x0C,0x14,0x24,0x44,0x44,0x84,0x84,0x00,
  299. };

  300. uchar code WJYJ[]=
  301. {
  302. /*--  文字:  鉴  --*/
  303. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  304. 0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
  305. 0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,
  306. };

  307. uchar code WJYY[]=
  308. {
  309. /*--  文字:  鹰  --*/
  310. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  311. 0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
  312. 0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,
  313. };

  314. uchar code WJYZH[]=
  315. {
  316. /*--  文字:  制  --*/
  317. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  318. 0x40,0x50,0x4E,0x48,0x48,0xFF,0x48,0x48,0x48,0x40,0xF8,0x00,0x00,0xFF,0x00,0x00,
  319. 0x00,0x00,0x3E,0x02,0x02,0xFF,0x12,0x22,0x1E,0x00,0x0F,0x40,0x80,0x7F,0x00,0x00,
  320. };


  321. /*uchar code WJYZZ[]=
  322. {
  323. /*--  文字:  作  --*/
  324. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  325. /*0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
  326. 0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,
  327. };
  328. */

  329. uchar code WWJJYYJ[]=
  330. {
  331. /*--  文字:  鉴  --*/
  332. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  333. 0x00,0x00,0x3E,0x00,0x80,0xBF,0x40,0x20,0x58,0x87,0x84,0x0C,0x34,0x04,0x00,0x00,
  334. 0x02,0x42,0x49,0x49,0x5A,0x6A,0x4A,0x7E,0x4A,0x6A,0x5A,0x49,0x49,0x42,0x02,0x00,
  335. };

  336. uchar code WWJJYYY[]=
  337. {
  338. /*--  文字:  鹰  --*/
  339. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  340. 0x00,0x00,0xFE,0x22,0x12,0xFA,0x26,0x12,0xFB,0xAE,0xAA,0xFE,0xAA,0xAA,0x02,0x00,
  341. 0x40,0x30,0x0F,0x40,0x40,0x5E,0x52,0x53,0x56,0x52,0x1A,0x56,0x90,0x70,0x00,0x00,
  342. };

  343. uchar code WWJJYYD[]=
  344. {
  345. /*--  文字:  电  --*/
  346. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  347. 0x00,0x00,0xF8,0x88,0x88,0x88,0x88,0xFF,0x88,0x88,0x88,0x88,0xF8,0x00,0x00,0x00,
  348. 0x00,0x00,0x1F,0x08,0x08,0x08,0x08,0x7F,0x88,0x88,0x88,0x88,0x9F,0x80,0xF0,0x00,
  349. };

  350. uchar code WWJJYYZ[]=
  351. {
  352. /*--  文字:  子  --*/
  353. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  354. 0x80,0x82,0x82,0x82,0x82,0x82,0x82,0xE2,0xA2,0x92,0x8A,0x86,0x82,0x80,0x80,0x00,
  355. 0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  356. };


  357. uchar code WWJJYYG[]=
  358. {
  359. /*--  文字:  工  --*/
  360. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  361. 0x00,0x04,0x04,0x04,0x04,0x04,0x04,0xFC,0x04,0x04,0x04,0x04,0x04,0x04,0x00,0x00,
  362. 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x00,
  363. };
  364. uchar code WWJJYYZ1[]=
  365. {
  366. /*--  文字:  作  --*/
  367. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  368. 0x00,0x80,0x60,0xF8,0x07,0x40,0x30,0x0F,0xF8,0x88,0x88,0x88,0x88,0x08,0x08,0x00,
  369. 0x01,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0xFF,0x08,0x08,0x08,0x08,0x08,0x00,0x00,
  370. };

  371. uchar code WWJJYYS[]=
  372. {
  373. /*--  文字:  室  --*/
  374. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  375. 0x10,0x0C,0x24,0x24,0xA4,0x64,0x25,0x26,0x24,0x24,0xA4,0x24,0x24,0x14,0x0C,0x00,
  376. 0x40,0x40,0x48,0x49,0x49,0x49,0x49,0x7F,0x49,0x49,0x49,0x4B,0x48,0x40,0x40,0x00,
  377. };


  378. uchar code WWJJYYW[]=
  379. {
  380. /*--  调入了一幅图像:C:\Users\Administrator\Desktop\624814_225502035_2.bmp  --*/
  381. /*--  宽度x高度=16x16  --*/
  382. 0xE0,0x18,0x0C,0x06,0x53,0xE9,0x49,0x01,0x01,0x49,0xE9,0x53,0x06,0x0C,0x38,0xF0,
  383. 0x0F,0x18,0x30,0x60,0x46,0xCC,0x98,0x98,0x98,0x98,0xCC,0xC6,0x60,0x30,0x18,0x0F,
  384. };

  385. uchar code WWJJYYWXTP[]=
  386. {
  387. /*--  调入了一幅图像:C:\Users\Administrator\Desktop\624814_225502035_2.bmp  --*/
  388. /*--  宽度x高度=16x16  --*/
  389. 0xF0,0x18,0x0E,0x06,0x43,0xE9,0x49,0x01,0x01,0x49,0xE9,0x43,0x06,0x0C,0x38,0xF0,
  390. 0x0F,0x18,0x37,0x6F,0x5E,0xDC,0xB8,0xB8,0xB8,0xB8,0xDC,0xDE,0x6F,0x37,0x18,0x0F,
  391. };

  392. /******************************************************************
  393. **        标题:鉴鹰电子欢乐多啊
  394. **  功能:数组
  395. *****************************************************************/

  396. uchar code WWJJYYHH[] =
  397. {
  398. /*--  文字:  欢  --*/
  399. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  400. 0x04,0x24,0x44,0x84,0x64,0x9C,0x40,0x30,0x0F,0xC8,0x08,0x08,0x28,0x18,0x00,0x00,
  401. 0x10,0x08,0x06,0x01,0x82,0x4C,0x20,0x18,0x06,0x01,0x06,0x18,0x20,0x40,0x80,0x00,
  402. };

  403. uchar code WWJJYYLE[]=
  404. {
  405. /*--  文字:  乐  --*/
  406. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  407. 0x00,0x00,0xE0,0x9C,0x84,0x84,0x84,0xF4,0x82,0x82,0x83,0x82,0x80,0x80,0x00,0x00,
  408. 0x00,0x20,0x10,0x08,0x06,0x40,0x80,0x7F,0x00,0x00,0x02,0x04,0x08,0x30,0x00,0x00,
  409. };

  410. uchar code WWJJYYDUO[]=
  411. {
  412. /*--  文字:  多  --*/
  413. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  414. 0x00,0x00,0x10,0x10,0x98,0xA4,0x47,0x44,0xA4,0x54,0x0C,0x04,0x00,0x00,0x00,0x00,
  415. 0x00,0x81,0x89,0x89,0x44,0x44,0x4A,0x31,0x21,0x11,0x09,0x05,0x03,0x00,0x00,0x00,
  416. };

  417. uchar code WWJJYYAA[]=
  418. {
  419. /*--  文字:  啊  --*/
  420. /*--  楷体_GB231212;  此字体下对应的点阵为:宽x高=16x16   --*/
  421. 0xFC,0x04,0xFC,0x00,0xFE,0x42,0xBE,0x00,0xF2,0x12,0xF2,0x02,0xFE,0x02,0x00,0x00,
  422. 0x0F,0x04,0x0F,0x00,0xFF,0x10,0x0F,0x00,0x0F,0x04,0x4F,0x80,0x7F,0x00,0x00,0x00,
  423. };

  424. uchar code table[]={/*--  调入了一幅图像:C:\Users\Administrator\Desktop\7308055_142022128173_2.bmp  --*/
  425. /*--  宽度x高度=128x64  --*/
  426. 0xFF,0x7F,0x7F,0xFF,0xF7,0xC3,0x87,0x07,0x0F,0x1F,0x1F,0x3F,0x7F,0x7F,0xFF,0xFF,
  427. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  428. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  429. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  430. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  431. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  432. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,
  433. 0xFF,0x7F,0x7F,0x3F,0x1F,0x1F,0x0F,0x87,0x87,0xC3,0xE1,0x7F,0x7F,0x7F,0xBF,0xFF,
  434. 0xFF,0xFF,0xF6,0xF6,0xA4,0xA4,0xA5,0xA1,0x81,0x80,0x80,0x00,0x00,0x00,0x00,0x00,
  435. 0x01,0x01,0x03,0x03,0x00,0x03,0x07,0x07,0x0F,0x1F,0x0F,0x0F,0x1F,0x1F,0x3F,0x3F,
  436. 0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  437. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  438. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  439. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x3F,0x3F,0x3F,
  440. 0x3F,0x1F,0x1F,0x0F,0x0F,0x07,0x0F,0x0F,0x07,0x03,0x01,0x00,0x02,0x01,0x01,0x00,
  441. 0x00,0x00,0x00,0x00,0x00,0x81,0x81,0xC0,0xD0,0xD4,0xD2,0xD2,0xFB,0xFB,0xFB,0xFF,
  442. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,0xF8,0xF8,0xF0,
  443. 0xF0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  444. 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x03,0x03,0x07,0x07,0x0F,0x0F,0x1F,0x1F,0x3F,
  445. 0x7F,0x7F,0xFF,0xFF,0xFF,0xCF,0xEF,0xEF,0xC7,0x47,0x07,0x07,0x17,0x07,0x07,0x07,
  446. 0x0F,0x1F,0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x3F,0x1F,0x0F,
  447. 0x07,0x03,0x03,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  448. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xF0,0xF0,
  449. 0xF0,0xF8,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  450. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  451. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFE,0xFC,0xFC,0xF8,0xF0,0xF0,
  452. 0xF0,0xE0,0xE0,0xC0,0xC0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,
  453. 0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  454. 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
  455. 0x00,0x80,0x00,0x00,0x00,0x80,0x80,0x80,0xC0,0x80,0xA0,0xE0,0xE0,0xE0,0xE0,0xF0,
  456. 0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  457. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  458. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  459. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  460. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,
  461. 0xFE,0xFE,0xFE,0xDC,0xDE,0xEC,0x8C,0xEC,0xE6,0x80,0xF0,0xF0,0xF0,0xE0,0xE0,0xE0,
  462. 0xE0,0xE0,0xE0,0xB0,0xD8,0xE0,0x80,0x8E,0xEC,0xDC,0xFE,0xFC,0xFE,0xFE,0xFE,0xFE,
  463. 0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  464. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  465. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  466. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0xFF,0x3F,0x3F,0xFF,0x3F,
  467. 0x3F,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,
  468. 0xBF,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,
  469. 0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x7F,0x7F,0x7F,
  470. 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  471. 0xFF,0xFF,0xFF,0x3F,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,
  472. 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x3F,0xBF,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  473. 0xFF,0xFF,0x7F,0x3F,0x3F,0x7F,0x7F,0x7F,0x7F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
  474. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0x98,0xD8,0x9F,0x88,0xA0,0x31,0x24,
  475. 0xAE,0x88,0xD2,0x96,0x9E,0xBE,0xFF,0xFF,0xFF,0xFF,0x00,0xFB,0xE1,0x20,0x39,0x20,
  476. 0x40,0x02,0xA0,0x20,0x22,0xA2,0xEE,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x76,0x76,0x00,
  477. 0x00,0x76,0x76,0x76,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xEF,0xEF,0xEF,0xEF,
  478. 0xEF,0x03,0x01,0xEC,0xEE,0xEE,0xEF,0xEF,0xEF,0xFF,0xFF,0xFF,0xFE,0xF2,0x26,0x06,
  479. 0x00,0x76,0xF1,0x70,0x06,0x06,0x36,0xF0,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xE3,0x60,
  480. 0x28,0x2F,0xAF,0x00,0x00,0xEF,0xAF,0x2F,0x6F,0xEF,0xEF,0xFF,0xFF,0xFF,0xFF,0xCD,
  481. 0x4C,0x6E,0x2C,0x81,0x53,0x03,0x41,0xCC,0x5E,0x1F,0x9F,0xDF,0xFF,0xFF,0xFF,0xFF,
  482. 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFB,0xFA,0xF8,0xF8,0xFA,0xF8,0xF8,
  483. 0xFA,0xF8,0xF8,0xFA,0xFB,0xFB,0xFF,0xFF,0xFF,0xF8,0xF8,0xFB,0xFB,0xFA,0xFA,0xFA,
  484. 0xFA,0xFA,0xFA,0xFA,0xF6,0xF8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFF,0xFF,0xF8,
  485. 0xF8,0xFB,0xFB,0xFB,0xFB,0xFB,0xF9,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,
  486. 0xFB,0xF8,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFC,0xFE,0xFF,
  487. 0xFB,0xFA,0xF9,0xFC,0xFE,0xFF,0xFE,0xFC,0xF9,0xFB,0xFF,0xFF,0xFF,0xFD,0xFC,0xFC,
  488. 0xFE,0xFB,0xF3,0xF8,0xF8,0xFF,0xFF,0xFF,0xFE,0xFC,0xFD,0xFF,0xFF,0xFF,0xFF,0xF3,
  489. 0xF3,0xFB,0xFB,0xFB,0xF9,0xF8,0xFC,0xFC,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,

  490. };


  491. uchar k,DIR_NUM_FLAG;
  492. bit KEY_FLAG;
  493. bit KEY_FLAG5=0;                           //KEY_FLAG5是外部中断1的标志位 KEY_FLAG1是步进标志
  494. uchar p,SNAKE_GRADE_NUM;               //定时次数
  495. bit KEY_FLAG1=0;
  496. //systemtime realtime;
  497. bit first=1;                                   //中断次数控制


  498. /****************************************************************************
  499. ** 函数名称:  void delay1ms(uint k)
  500. ** 功能描述:  1ms延时程序  
  501. ** 输 入:    uint k(需要延时的数量)
  502. **         
  503. **        
  504. ** 输 出:
  505. **         
  506. ** 全局变量:
  507. ** 调用模块:
  508. **
  509. ** 作 者:    吴鉴鹰
  510. ** 作者所在单位:鉴鹰电子工作室
  511. ** 日 期:     14.04.9
  512. ****************************************************************************/
  513. void delay1ms(uint k)
  514. {
  515.   k=k*125;
  516.   while(k--);
  517. }

  518. /*******************************************************************************************
  519. ** 函数名称:  void Delay_S(void)   //延时1s误差 0us
  520. ** 功能描述:  精确延时函数,延时1秒,软件算得                                                
  521. ** 输 入:   
  522. **         
  523. **        
  524. ** 输 出:   
  525. **         
  526. ** 全局变量:
  527. ** 调用模块:
  528. **
  529. ** 作 者:    吴鉴鹰
  530. ** 日 期:     14.04.09
  531. ********************************************************************************************/
  532. void Delay_S(void)   //延时1s误差 0us
  533. {
  534.     unsigned char a,b,c;
  535.     for(c=167;c>0;c--)
  536.         for(b=171;b>0;b--)
  537.             for(a=16;a>0;a--);
  538.     _nop_();  //if Keil,require use intrins.h
  539. }        

  540. /****************************************************************************
  541. ** 函数名称:  void chekbusy12864(void)
  542. ** 功能描述:  12864判忙函数
  543. ** 输 入:   
  544. **         
  545. **        
  546. ** 输 出:
  547. **         
  548. ** 全局变量:
  549. ** 调用模块:
  550. **
  551. ** 作 者:    吴鉴鹰
  552. ** 作者所在单位:鉴鹰电子工作室
  553. ** 日 期:     14.04.9
  554. ****************************************************************************/

  555. void chekbusy12864(void)
  556. {
  557.   uchar dat;
  558.   EX0=0;
  559.   LCD_RS_OUT=0;       //指令模式
  560.   LCD_RW_OUT=1;       //读数据
  561. do{
  562.    P0=0x00;                         //
  563.    LCD_E_OUT=1;
  564.    dat=P0&0x80;
  565.    LCD_E_OUT=0;
  566.   }while(dat!=0x00);
  567.   EX0=1;
  568. }


  569. /****************************************************************************
  570. ** 函数名称:  void CHOOSE_12864_SCREEN(uchar i)
  571. ** 功能描述:  选屏函数
  572. ** 输 入:    uchar i(i是要写的屏.0是左屏,1是右屏,2是双屏)
  573. **         
  574. **        
  575. ** 输 出:
  576. **         
  577. ** 全局变量:
  578. ** 调用模块:
  579. **
  580. ** 作 者:    吴鉴鹰
  581. ** 作者所在单位:鉴鹰电子工作室
  582. ** 日 期:     14.04.9
  583. ****************************************************************************/
  584. void CHOOSE_12864_SCREEN(uchar i)  /*i是要写的屏.0是左屏,1是右屏,2是双屏;*/
  585. {                                   /*此处在硬件上运行时i的电平全部与程序相反;*/
  586.   switch (i)                           /*此版本为仿真版;*/
  587.   {
  588.     case 0: LCD_CS1_OUT=0;LCD_CS2_OUT=1;break;        //比如此处如果要在电路上运行则应该改为CS=1;LCD_CS2_OUT=0;   
  589.     case 1: LCD_CS1_OUT=1;LCD_CS2_OUT=0;break;
  590.     case 2: LCD_CS1_OUT=0;LCD_CS2_OUT=0;break;
  591.     default: break;
  592.   }
  593. }


  594. /****************************************************************************
  595. ** 函数名称:  void LCD_12864_CMD(uchar cmd)                //写命令
  596. ** 功能描述:  lcd12864写命令的函数
  597. ** 输 入:    uchar cmd(写入的命令)
  598. **         
  599. **        
  600. ** 输 出:
  601. **         
  602. ** 全局变量:
  603. ** 调用模块:
  604. **
  605. ** 作 者:    吴鉴鹰
  606. ** 作者所在单位:鉴鹰电子工作室
  607. ** 日 期:     14.04.9
  608. ****************************************************************************/
  609. void LCD_12864_CMD(uchar cmd)                //写命令
  610. {
  611.   chekbusy12864();
  612.   EX0=0;
  613.   LCD_RS_OUT=0;                    //指令模式
  614.   LCD_RW_OUT=0;             //写模式
  615.   LCD_E_OUT=1;
  616.   P0=cmd;
  617.   LCD_E_OUT=0;
  618.   EX0=1;
  619. }


  620. /****************************************************************************
  621. ** 函数名称:  void  LCD_12864_DAT(uchar dat)                //写命令
  622. ** 功能描述:  lcd12864写数据的函数
  623. ** 输 入:    uchar dat(写入的数据)
  624. **         
  625. **        
  626. ** 输 出:
  627. **         
  628. ** 全局变量:
  629. ** 调用模块:
  630. **
  631. ** 作 者:    吴鉴鹰
  632. ** 作者所在单位:鉴鹰电子工作室
  633. ** 日 期:     14.04.9
  634. ****************************************************************************/
  635. void  LCD_12864_DAT(uchar dat)
  636. {
  637.   chekbusy12864();
  638.   EX0=0;
  639.   LCD_RS_OUT=1;
  640.   LCD_RW_OUT=0;
  641.   LCD_E_OUT=1;
  642.   P0=dat;
  643.   LCD_E_OUT=0;
  644.   EX0=1;
  645. }

  646. /****************************************************************************
  647. ** 函数名称:  void CLEAR_12864_SCREEN(void)                //清屏函数
  648. ** 功能描述:  lcd12864清屏函数
  649. ** 输 入:   
  650. **         
  651. **        
  652. ** 输 出:
  653. **         
  654. ** 全局变量:
  655. ** 调用模块:
  656. **
  657. ** 作 者:    吴鉴鹰
  658. ** 作者所在单位:鉴鹰电子工作室
  659. ** 日 期:     14.04.9
  660. ****************************************************************************/
  661. void CLEAR_12864_SCREEN(void)
  662. {
  663.   uchar page,row;
  664.   for(page=0xb8;page<0xc0;page++)
  665.   {
  666.     LCD_12864_CMD(page);
  667.         LCD_12864_CMD(0x40);
  668.         for(row=0;row<64;row++)
  669.          {
  670.            LCD_12864_DAT(0x00);          //对12864所有地址全部写零
  671.          }
  672.   }
  673. }


  674. /****************************************************************************
  675. ** 函数名称:  void Init_12864_HS(void)                //清屏函数
  676. ** 功能描述:  lcd12864初始化函数
  677. ** 输 入:   
  678. **         
  679. **        
  680. ** 输 出:
  681. **         
  682. ** 全局变量:
  683. ** 调用模块:
  684. **
  685. ** 作 者:    吴鉴鹰
  686. ** 作者所在单位:鉴鹰电子工作室
  687. ** 日 期:     14.04.9
  688. ****************************************************************************/
  689. void Init_12864_HS(void)
  690. {
  691.   chekbusy12864();
  692.   LCD_12864_CMD(0xc0);          //从第零行开始显示
  693.   LCD_12864_CMD(0x3f);          //LCD显示RAM中的内容
  694. }


  695. /****************************************************************************
  696. ** 函数名称:  void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
  697. ** 功能描述:  lcd12864的8X16字符的显示
  698. ** 输 入:    uchar ch,uchar row,uchar page,uchar *p(屏数,列数,页数,还有显示的数组首地址)
  699. **         
  700. **        
  701. ** 输 出:
  702. **         
  703. ** 全局变量:
  704. ** 调用模块:
  705. **
  706. ** 作 者:    吴鉴鹰
  707. ** 作者所在单位:鉴鹰电子工作室
  708. ** 日 期:     14.04.9
  709. ****************************************************************************/  
  710. void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
  711. {
  712.   uchar i;
  713.   CHOOSE_12864_SCREEN(ch);
  714.   page=page<<1;                           //程序中采用的位移运算代替乘法运算,这样可以大大降低处理器的负担
  715.   row=row<<3;
  716.   LCD_12864_CMD(row+0x40);
  717.   LCD_12864_CMD(page+0xb8);
  718.   for(i=0;i<8;i++)
  719.   {
  720.     LCD_12864_DAT(*(adr+i));
  721.   }
  722.   LCD_12864_CMD(row+0x40);
  723.   LCD_12864_CMD(page+0xb9);
  724.   for(i=8;i<16;i++)
  725.   {
  726.     LCD_12864_DAT(*(adr+i));
  727.   }
  728. }


  729. /****************************************************************************
  730. ** 函数名称:  void Display_8_point(uchar ch,uchar row,uchar page,uchar *adr)
  731. ** 功能描述:  lcd12864的16X16显示字符的显示
  732. ** 输 入:    uchar ch,uchar row,uchar page,uchar *p(屏数,列数,页数,还有显示的数组首地址)
  733. **         
  734. **        
  735. ** 输 出:
  736. **         
  737. ** 全局变量:
  738. ** 调用模块:
  739. **
  740. ** 作 者:    吴鉴鹰
  741. ** 作者所在单位:鉴鹰电子工作室
  742. ** 日 期:     14.04.9
  743. ****************************************************************************/  
  744. void Display_16_point(uchar ch,uchar row,uchar page,uchar *adr)
  745. {
  746.   uchar i;
  747.   CHOOSE_12864_SCREEN(ch);
  748.   page=page<<1;                                          
  749.   row=row<<3;
  750.   LCD_12864_CMD(row+0x40);
  751.   LCD_12864_CMD(page+0xb8);
  752.   for(i=0;i<16;i++)
  753.   {
  754.     LCD_12864_DAT(*(adr+i));
  755.   }
  756.   LCD_12864_CMD(row+0x40);
  757.   LCD_12864_CMD(page+0xb9);
  758.   for(i=16;i<32;i++)
  759.   {
  760.     LCD_12864_DAT(*(adr+i));
  761.   }
  762. }


  763. /****************************************************************************
  764. ** 函数名称:  uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
  765. ** 功能描述:  lcd12864的数据的读取
  766. ** 输 入:    uchar page,uchar arrange  (page页地址.arrange列地址)
  767. **         
  768. **        
  769. ** 输 出:
  770. **         
  771. ** 全局变量:
  772. ** 调用模块:
  773. **
  774. ** 作 者:    吴鉴鹰
  775. ** 作者所在单位:鉴鹰电子工作室
  776. ** 日 期:     14.04.9
  777. ****************************************************************************/
  778. uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
  779. {
  780.   uchar dat;
  781.   chekbusy12864();
  782.   EA=0;
  783.   LCD_12864_CMD(page+0xb8);
  784.   LCD_12864_CMD(arrange+0x40);
  785.   EX0=0;                                                
  786.   P0=0xff;
  787.   LCD_RW_OUT=1;
  788.   LCD_RS_OUT=1;
  789.   LCD_E_OUT=1;
  790.   LCD_E_OUT=0;                                 //12864读数据时第二次读才有效,第一次读取的值不采集
  791.   LCD_E_OUT=1;
  792.   dat=P0;
  793.   LCD_E_OUT=0;
  794.   EA=1;
  795.   return(dat);
  796.   //EX0=1;

  797. }


  798. /****************************************************************************
  799. ** 函数名称:  uchar DAT_READ_12864(uchar page,uchar arrange)  //page页地址.arrange列地址)
  800. ** 功能描述:  lcd12864的反白显示
  801. ** 输 入:    uchar ch,uchar arrange,uchar page (屏数,列数,页数)
  802. **         
  803. **        
  804. ** 输 出:
  805. **         
  806. ** 全局变量:
  807. ** 调用模块:
  808. **
  809. ** 作 者:    吴鉴鹰
  810. ** 作者所在单位:鉴鹰电子工作室
  811. ** 日 期:     14.04.9
  812. ****************************************************************************/
  813. void Display_16_point_fb(uchar ch,uchar arrange,uchar page)
  814. {
  815.    uchar i;
  816.    uchar xdata dat_fb[32];
  817.    CHOOSE_12864_SCREEN(ch);
  818.    for(i=0;i<16;i++)
  819.    {
  820.      dat_fb=~(DAT_READ_12864((page<<1),((arrange<<3)+i)));
  821.          dat_fb[i+16]=~(DAT_READ_12864((page<<1)+1,((arrange<<3)+i)));
  822.         }
  823.    Display_16_point(ch,arrange,page,dat_fb);
  824. }

  825. /****************************************************************************
  826. ** 函数名称:  void DRAW_TRANSVERSE_Line(uchar y1,uchar y2,uchar x)//y1表示起点,y2表示终点
  827. ** 功能描述:  lcd12864的画竖线的函数
  828. ** 输 入:    uchar y1,uchar y2,uchar x(y1表示起点,y2表示终点)
  829. **         
  830. **        
  831. ** 输 出:
  832. **         
  833. ** 全局变量:
  834. ** 调用模块:
  835. **
  836. ** 作 者:    吴鉴鹰
  837. ** 作者所在单位:鉴鹰电子工作室
  838. ** 日 期:     14.04.9
  839. ****************************************************************************/
  840. void DRAW_TRANSVERSE_Line(uchar y1,uchar y2,uchar x)//y1表示起点,y2表示终点
  841. {
  842.   uchar i,sum=0;
  843.   if(x>63)
  844.    {
  845.      CHOOSE_12864_SCREEN(1);                                         //y1比y2小,这里给出画竖线的函数而不用画点的方法
  846.      x=x-64;                                                         //是为了减少单片机的处理负担。
  847.    }
  848.    else
  849.    {
  850.      CHOOSE_12864_SCREEN(0);
  851.    }
  852.   if((y1/8)!=(y2/8))
  853.   {
  854.    for(i=0;i<(8-y1%8);i++)         
  855.    {
  856.       sum=sum|((2<<((y1%8)+i)));
  857.    }
  858.   LCD_12864_CMD(x+0x40);
  859.   LCD_12864_CMD(y1/8+0xb8);
  860.   LCD_12864_DAT(sum);
  861.   sum=0;
  862.    for(i=0;i<(y2/8-y1/8-1);i++)
  863.     {
  864.      LCD_12864_CMD(x+0x40);
  865.          LCD_12864_CMD((y1/8)+0xb9+i);
  866.          LCD_12864_DAT(0xff);
  867.     }
  868.   for(i=0;i<=(y2%8);i++)
  869.    {
  870.      sum=sum|(2<<i);
  871.    }
  872.    LCD_12864_CMD(x+0x40);
  873.    LCD_12864_CMD(y2/8+0xb8);
  874.    LCD_12864_DAT(sum|1);
  875.    sum=0;        
  876. }
  877. else
  878. {
  879.    for(i=0;i<=y2-y1;i++)
  880.     {
  881.           sum=sum|(2<<(i+(y1%8)));
  882.         }
  883.         LCD_12864_CMD(0x40|x);
  884.         LCD_12864_CMD(0xb8|(y1/8));
  885.         LCD_12864_DAT(sum);
  886. }
  887. }


  888. /****************************************************************************
  889. ** 函数名称:  void DRAW_DOT_HS(uchar x,uchar y)
  890. ** 功能描述:  lcd12864的画点的函数
  891. ** 输 入:    uchar x,uchar y(x表示横坐标,y表示纵坐标)
  892. **         
  893. **        
  894. ** 输 出:
  895. **         
  896. ** 全局变量:
  897. ** 调用模块:
  898. **
  899. ** 作 者:    吴鉴鹰
  900. ** 作者所在单位:鉴鹰电子工作室
  901. ** 日 期:     14.04.9
  902. ****************************************************************************/
  903. void DRAW_DOT_HS(uchar x,uchar y)
  904. {
  905.   uchar dat;
  906.   if(x>63)
  907.   {
  908.     CHOOSE_12864_SCREEN(1);
  909.         x=x-64;
  910.   }
  911.   else
  912.   {
  913.     CHOOSE_12864_SCREEN(0);
  914.   }
  915.   dat=DAT_READ_12864(y/8,x);
  916.   LCD_12864_CMD(0x40|x);
  917.   LCD_12864_CMD(0xb8|y/8);
  918.   LCD_12864_DAT((1<<(y%8))|dat);
  919. }



  920. /****************************************************************************
  921. ** 函数名称:  void CHANGE_HS(uchar *x,uchar *y)
  922. ** 功能描述:  lcd12864中将4X4个点合为一个
  923. ** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
  924. **         
  925. **        
  926. ** 输 出:
  927. **         
  928. ** 全局变量:
  929. ** 调用模块:
  930. **
  931. ** 作 者:    吴鉴鹰
  932. ** 作者所在单位:鉴鹰电子工作室
  933. ** 日 期:     14.04.9
  934. ****************************************************************************/
  935. void CHANGE_HS(uchar *x,uchar *y)     //x<24  y<15
  936. {
  937.   uchar i,m,n;                                           //24和15分别表示游戏的范围
  938.   if(*x<24&&*y<15)                                   //这里的点是个有花色的点而不是一个实心的点
  939.   {
  940.    m=(*x)<<2;
  941.    n=((*y)<<2)+2;
  942.    for(i=0;i<4;i++)
  943.    {
  944.     DRAW_DOT_HS(31+m,n+i);
  945.         DRAW_DOT_HS(34+m,n+i);
  946.    }
  947.    DRAW_DOT_HS(32+m,n);                 
  948.    DRAW_DOT_HS(32+m,n+1);
  949.    DRAW_DOT_HS(32+m,n+3);
  950.    DRAW_DOT_HS(33+m,n);
  951.    DRAW_DOT_HS(33+m,n+2);
  952.    DRAW_DOT_HS(33+m,n+3);
  953.   }
  954. }


  955. /****************************************************************************
  956. ** 函数名称:  void CLEAR_Dot_HS(uchar x,uchar y)
  957. ** 功能描述:  lcd12864的清点的函数
  958. ** 输 入:    uchar x,uchar y(x表示横坐标,y表示纵坐标)
  959. **         
  960. **        
  961. ** 输 出:
  962. **         
  963. ** 全局变量:
  964. ** 调用模块:
  965. **
  966. ** 作 者:    吴鉴鹰
  967. ** 作者所在单位:鉴鹰电子工作室
  968. ** 日 期:     14.04.9
  969. ****************************************************************************/
  970. void CLEAR_Dot_HS(uchar x,uchar y)
  971. {
  972.   uchar dat,j;
  973.   if(x>63)
  974.   {
  975.     CHOOSE_12864_SCREEN(1);
  976.         x=x-64;
  977.   }
  978.   else
  979.   {
  980.     CHOOSE_12864_SCREEN(0);
  981.   }
  982.   dat=DAT_READ_12864(y/8,x);
  983.   LCD_12864_CMD(0x40|x);
  984.   LCD_12864_CMD(0xb8|(y/8));
  985.   j=~(1<<(y%8));
  986.   LCD_12864_DAT(dat&j);
  987. }


  988. /****************************************************************************
  989. ** 函数名称:  void clear(uchar *x,uchar *y)
  990. ** 功能描述:  lcd12864的清除一个4X4的点函数
  991. ** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
  992. **         
  993. **        
  994. ** 输 出:
  995. **         
  996. ** 全局变量:
  997. ** 调用模块:
  998. **
  999. ** 作 者:    吴鉴鹰
  1000. ** 作者所在单位:鉴鹰电子工作室
  1001. ** 日 期:     14.04.9
  1002. ****************************************************************************/
  1003. void CLEAR_4DOT_HS(uchar *x,uchar *y)
  1004. {
  1005.   uchar i,m,n;
  1006.   m=((*x)<<2)+31;
  1007.   n=((*y)<<2)+2;
  1008.   for(i=0;i<4;i++)
  1009.   {
  1010.     CLEAR_Dot_HS(m,n+i);
  1011.         CLEAR_Dot_HS(m+1,n+i);
  1012.         CLEAR_Dot_HS(m+2,n+i);
  1013.         CLEAR_Dot_HS(m+3,n+i);
  1014.   }
  1015. }  


  1016. /****************************************************************************
  1017. ** 函数名称:  void CLEAR_4DOT_HS1(uchar *x,uchar *y)
  1018. ** 功能描述:  lcd12864的清除一个4X4的点函数
  1019. ** 输 入:    uchar *x,uchar *y(*x表示横坐标,*y表示纵坐标)
  1020. **         
  1021. **        
  1022. ** 输 出:
  1023. **         
  1024. ** 全局变量:
  1025. ** 调用模块:
  1026. **
  1027. ** 作 者:    吴鉴鹰
  1028. ** 作者所在单位:鉴鹰电子工作室
  1029. ** 日 期:     14.04.9
  1030. ****************************************************************************/
  1031. void CLEAR_4DOT_HS1(uchar x,uchar y)
  1032. {
  1033.   uchar i,m,n;
  1034.   if(x>=0&&x<24&&y>=0&&y<15)
  1035.   {
  1036.    m=((x)<<2)+31;
  1037.    n=((y)<<2)+2;
  1038.    for(i=0;i<4;i++)
  1039.    {
  1040.     CLEAR_Dot_HS(m,n+i);
  1041.         CLEAR_Dot_HS(m+1,n+i);
  1042.         CLEAR_Dot_HS(m+2,n+i);
  1043.         CLEAR_Dot_HS(m+3,n+i);
  1044.    }
  1045.   }
  1046. }  


  1047. /****************************************************************************
  1048. ** 函数名称:  bit readfk(char x,char y)
  1049. ** 功能描述:  lcd12864的清除一个点函数
  1050. ** 输 入:    char x,char y(x表示横坐标,y表示纵坐标)
  1051. **         
  1052. **        
  1053. ** 输 出:
  1054. **         
  1055. ** 全局变量:
  1056. ** 调用模块:
  1057. **
  1058. ** 作 者:    吴鉴鹰
  1059. ** 作者所在单位:鉴鹰电子工作室
  1060. ** 日 期:     14.04.9
  1061. ****************************************************************************/
  1062. bit readfk(char x,char y)
  1063. {
  1064.   bit KEY_FLAGfk=0;
  1065.   uchar m,n;
  1066.   if(y>=0)
  1067.   {
  1068.   m=(x<<2)+31;
  1069.   n=(y<<2)+2;
  1070.   CHOOSE_12864_SCREEN(0);
  1071.   if(m>63)
  1072.   {
  1073.    m=m-64;
  1074.    CHOOSE_12864_SCREEN(1);
  1075.   }                                                                                                                                                               
  1076.   m = DAT_READ_12864(n>>3,m);
  1077.   if((n%8)==2)
  1078.   {
  1079.     if((m&0x3c)==0x3c)
  1080.         {
  1081.           KEY_FLAGfk=1;
  1082.          }
  1083.         else
  1084.         {
  1085.           KEY_FLAGfk=0;
  1086.         }
  1087.   }
  1088.    if((n%8)==6)
  1089.    {
  1090.     if((m&0xc0)==0xc0)
  1091.         {
  1092.            KEY_FLAGfk=1;
  1093.         }
  1094.         else
  1095.         {
  1096.           KEY_FLAGfk=0;
  1097.         }
  1098.    }
  1099.   }
  1100.   return(KEY_FLAGfk);

  1101. }

  1102. /****************************************************************************
  1103. ** 函数名称:  void dingshi() interrupt 1  using 1
  1104. ** 功能描述:  定时程序.产生步进时间
  1105. ** 输 入:   
  1106. **         
  1107. **        
  1108. ** 输 出:
  1109. **         
  1110. ** 全局变量:
  1111. ** 调用模块:
  1112. **
  1113. ** 作 者:    吴鉴鹰
  1114. ** 作者所在单位:鉴鹰电子工作室
  1115. ** 日 期:     14.04.9
  1116. ****************************************************************************/
  1117. void dingshi() interrupt 1  using 1  //定时程序.产生步进时间
  1118. {
  1119.    if(p--)
  1120.    {
  1121.     TL0=0;
  1122.         TH0=0xa0;
  1123.         KEY_FLAG1=0;
  1124.    }
  1125.    else
  1126.    {
  1127.      KEY_FLAG1=1;
  1128.          TL0=0;
  1129.          TH0=0x00;
  1130.          p=20-(SNAKE_GRADE_NUM>>1);
  1131.    }
  1132. }


  1133. /****************************************************************************
  1134. ** 函数名称:  void zhongduan1() interrupt 2 using 2
  1135. ** 功能描述:  开始确认暂停键的判断
  1136. ** 输 入:   
  1137. **         
  1138. **        
  1139. ** 输 出:
  1140. **         
  1141. ** 全局变量:
  1142. ** 调用模块:
  1143. **
  1144. ** 作 者:    吴鉴鹰
  1145. ** 作者所在单位:鉴鹰电子工作室
  1146. ** 日 期:     14.04.9
  1147. ****************************************************************************/
  1148. void zhongduan1() interrupt 2 using 2
  1149. {
  1150.    if(!KEY_FLAG5)
  1151.    {
  1152.      KEY_FLAG5=1;
  1153.    }
  1154.    else
  1155.    {
  1156.      KEY_FLAG5=0;
  1157.    }
  1158. }


  1159. /****************************************************************************
  1160. ** 函数名称:  void INTERRUPT_NUM0() interrupt 0 using 0
  1161. ** 功能描述:  方向键的判断
  1162. ** 输 入:   
  1163. **         
  1164. **        
  1165. ** 输 出:
  1166. **         
  1167. ** 全局变量:
  1168. ** 调用模块:
  1169. **
  1170. ** 作 者:    吴鉴鹰
  1171. ** 作者所在单位:鉴鹰电子工作室
  1172. ** 日 期:     14.04.9
  1173. ****************************************************************************/
  1174. void INTERRUPT_NUM0() interrupt 0 using 0
  1175. {
  1176.     uchar i=0;
  1177.         if(first)               //FIRST=1;打开方向按键判断标志
  1178.         {
  1179.         first=0;            
  1180.         k=(P2>>6);           
  1181.         k=k&0x03;                                
  1182.         if(KEY_FLAG)
  1183.           {
  1184.             if(k==1)     DIR_NUM_FLAG=3;//左
  1185.             if(k==2)         DIR_NUM_FLAG=1;//右
  1186.              }
  1187.           else
  1188.            {
  1189.             if(k==0)         DIR_NUM_FLAG=4;//上
  1190.             if(k==3)         DIR_NUM_FLAG=2;//下
  1191.              }
  1192.     }
  1193. }



  1194. /****************************************************************************
  1195. ** 函数名称:  void Gluttonous_Snake(void)
  1196. ** 功能描述:  贪吃蛇子程序
  1197. ** 输 入:   
  1198. **         
  1199. **        
  1200. ** 输 出:
  1201. **         
  1202. ** 全局变量:
  1203. ** 调用模块:
  1204. **
  1205. ** 作 者:    吴鉴鹰
  1206. ** 作者所在单位:鉴鹰电子工作室
  1207. ** 日 期:     14.04.9
  1208. ****************************************************************************/
  1209. void Gluttonous_Snake(void)                                                                                                           
  1210. {           
  1211.   uchar xdata SNK_BODY_Length[102]={0,8,1,8};         //存放蛇身的数组;
  1212.   uchar SNK_Food_Date[2]={12,8};
  1213.   uchar i,x,y;
  1214.   bit KEY_FLAG2,KEY_FLAG3,KEY_FLAG4;
  1215.   TMOD=1;          //定时器工作方式
  1216.   IT0=1;          //边延有效
  1217.   IT1=1;
  1218.   EA=1;                  //开CPU中断
  1219.   ET0=1;          //开定时器中断
  1220.   EX0=1;          //开外部中断
  1221.   EX1=1;
  1222.   TL0=0x00;
  1223.   TH0=0x00;          //定时器初值
  1224.   TR0=1;          //启动定时器

  1225.   SNAKE_GRADE_NUM=2;
  1226.   p=20;
  1227.   DIR_NUM_FLAG=1;
  1228.   KEY_FLAG5=0;

  1229.   CHOOSE_12864_SCREEN(2);
  1230.   CLEAR_12864_SCREEN();        
  1231.   DRAW_TRANSVERSE_Line(1,61,30);
  1232.   DRAW_TRANSVERSE_Line(1,61,127);
  1233.   for(i=0;i<98;i++)
  1234.   {
  1235.        DRAW_DOT_HS(30+i,1);
  1236.        DRAW_DOT_HS(30+i,62);
  1237.   }
  1238.   Display_16_point(0,0,0,TCS_TAN);
  1239.   Display_16_point(0,0,1,TCS_CHI);
  1240.   Display_16_point(0,0,2,TCS_SHE);
  1241.   CHANGE_HS(SNK_BODY_Length,(SNK_BODY_Length+1));
  1242.   CHANGE_HS((SNK_BODY_Length+2),(SNK_BODY_Length+3));
  1243.   CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  1244.   for(;;)
  1245.   {
  1246.     do
  1247.    {
  1248.     first=1;
  1249.     while(KEY_FLAG5|!KEY_FLAG1);
  1250.     x=*(SNK_BODY_Length);                              
  1251.     y=*(SNK_BODY_Length+1);
  1252.     switch(DIR_NUM_FLAG)                           //右
  1253.         {
  1254.           case 1:
  1255.             {
  1256.               for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  1257.                {
  1258.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  1259.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  1260.                }
  1261.                (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))++;
  1262.                    KEY_FLAG=0;
  1263.                    break;
  1264.               }
  1265.                    case 2:                                          //下
  1266.                  {
  1267.               for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  1268.                {
  1269.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  1270.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  1271.                }
  1272.                     (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))++;
  1273.                         KEY_FLAG=1;
  1274.                         break;
  1275.                   }
  1276.                 case 3:                                        //左
  1277.                  {
  1278.                for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  1279.                {
  1280.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  1281.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  1282.                }
  1283.                (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))--;
  1284.                    KEY_FLAG=0;
  1285.                    break;
  1286.                  }
  1287.                 case 4:
  1288.                  {                        //上
  1289.                  for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  1290.                {
  1291.                  *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)+2);
  1292.                      *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)+3);
  1293.                }
  1294.                     (*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))--;
  1295.                         KEY_FLAG=1;
  1296.                         break;
  1297.                  }
  1298.          }
  1299.          KEY_FLAG4=((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2))==SNK_Food_Date[0])&&((*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1))==SNK_Food_Date[1]);
  1300.          if(KEY_FLAG4)        //
  1301.          {
  1302.                 for(i=SNAKE_GRADE_NUM;i>0;i--)
  1303.                 {
  1304.                   *(SNK_BODY_Length+(i<<1))=*(SNK_BODY_Length+(i<<1)-2);
  1305.                   *(SNK_BODY_Length+(i<<1)+1)=*(SNK_BODY_Length+(i<<1)-1);
  1306.                 }
  1307.                 *SNK_BODY_Length=x;
  1308.                 *(SNK_BODY_Length+1)=y;
  1309.                 SNAKE_GRADE_NUM++;
  1310.                 do
  1311.                 {
  1312.                   KEY_FLAG3=0;
  1313.                   SNK_Food_Date[0]=TL0%24;
  1314.               SNK_Food_Date[1]=TL0%15;
  1315.                   for(i=0;i<SNAKE_GRADE_NUM-1;i++)         //食物是否在蛇身身上
  1316.                   {
  1317.                     if((*(SNK_BODY_Length+(i<<1)))==SNK_Food_Date[0]&&((*(SNK_BODY_Length+(i<<1)+1))==SNK_Food_Date[1]))
  1318.                         {
  1319.                           KEY_FLAG3=1;
  1320.                           break;
  1321.                          }
  1322.                   }
  1323.                 }while(KEY_FLAG3);
  1324.                 CHANGE_HS(SNK_Food_Date,SNK_Food_Date+1);
  1325.          }
  1326.      KEY_FLAG2=1;          //蛇头没有遇到蛇身
  1327.          for(i=0;i<SNAKE_GRADE_NUM-1;i++)
  1328.         {
  1329.                    if(*(SNK_BODY_Length+(i<<1))==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)&&(*(SNK_BODY_Length+(i<<1)+1)==*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)))
  1330.                    {
  1331.                      KEY_FLAG2=0;
  1332.                          break;
  1333.                         }
  1334.                 }
  1335.           KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2)<24;//蛇头是否出边界
  1336.           KEY_FLAG2=KEY_FLAG2&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)>=0&&*(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1)<15;
  1337.           if(KEY_FLAG2)
  1338.            {
  1339.             CLEAR_4DOT_HS(&x,&y);
  1340.                
  1341.             
  1342.              {
  1343.                CHANGE_HS(SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-2,SNK_BODY_Length+(SNAKE_GRADE_NUM<<1)-1);
  1344.              }
  1345.                  if(KEY_FLAG4)
  1346.                  {
  1347.                    CHANGE_HS(&x,&y);
  1348.                   }
  1349.             KEY_FLAG1=0;
  1350.             Display_8_point(0,0,3,NUM0+((SNAKE_GRADE_NUM/10)<<4));
  1351.             Display_8_point(0,1,3,NUM0+(((SNAKE_GRADE_NUM)%10)<<4));
  1352.            }
  1353.    }
  1354.    while(KEY_FLAG2);
  1355.    delay1ms(450);
  1356.    delay1ms(450);
  1357.    CHOOSE_12864_SCREEN(2);
  1358.    CLEAR_12864_SCREEN();
  1359.    Display_16_point(0,4,1,GAME_OVER);
  1360.    Display_16_point(0,6,1,GAME_OVER+32);
  1361.    Display_16_point(1,0,1,GAME_OVER+64);
  1362.    Display_16_point(1,2,1,GAME_OVER+96);
  1363.    delay1ms(450);
  1364.    delay1ms(450);
  1365.    break;
  1366.   }
  1367. }

  1368. /*******************************************************************************************
  1369. ** 函数名称:  void CHECK_busy()
  1370. ** 功能描述:  读“忙”函数,判断液晶当前是否忙碌  
  1371. ** 输 入:     
  1372. **         
  1373. **        
  1374. ** 输 出:
  1375. **         
  1376. ** 全局变量:
  1377. ** 调用模块:
  1378. **
  1379. ** 作 者:    吴鉴鹰
  1380. ** 日 期:     14.04.09
  1381. ********************************************************************************************/
  1382. void CHECK_busy()//读“忙”函数-----数据线的最高位DB71则busy               
  1383. {
  1384.         P0=0x00;
  1385.            LCD_RS_OUT=0;  
  1386.            LCD_RW_OUT=1;
  1387.         LCD_E_OUT=1;
  1388.         while(P0 & 0x80);
  1389.         LCD_E_OUT=0;
  1390. }

  1391. /*******************************************************************************************
  1392. ** 函数名称:  void LCD_COM_WRI(uchar value)
  1393. ** 功能描述:  LCD液晶写命令函数  
  1394. ** 输 入:    uchar value(向LCD写入的命令)
  1395. **         
  1396. **        
  1397. ** 输 出:
  1398. **         
  1399. ** 全局变量:
  1400. ** 调用模块:
  1401. **
  1402. ** 作 者:    吴鉴鹰
  1403. ** 日 期:     14.04.09
  1404. ********************************************************************************************/
  1405. void LCD_COM_WRI(uchar value)        //写命令函数
  1406. {
  1407.    CHECK_busy();                                                //对LCD的每次读写都要读忙
  1408.    LCD_RS_OUT=0;                                                         //选择命令
  1409.    LCD_RW_OUT=0;                                                         //读操作
  1410.    LCD_12864_DATA = value;
  1411.    LCD_E_OUT=1;                                                        //LCD_EN_OUT由1----0锁存有效数据
  1412.    _nop_();
  1413.    _nop_();
  1414.    LCD_E_OUT=0;
  1415. }

  1416. /*******************************************************************************************
  1417. ** 函数名称:  void LCD_DATA_WRI(uchar value)
  1418. ** 功能描述:  LCD液晶写数据的函数  
  1419. ** 输 入:    uchar value(向LCD写入的数据)
  1420. **         
  1421. **        
  1422. ** 输 出:
  1423. **         
  1424. ** 全局变量:
  1425. ** 调用模块:
  1426. **
  1427. ** 作 者:    吴鉴鹰
  1428. ** 日 期:     14.04.09
  1429. ********************************************************************************************/
  1430. void LCD_DATA_WRI(uchar value)//写数据函数        
  1431. {
  1432.    CHECK_busy();
  1433.    LCD_RS_OUT=1;                                                 //选择数据
  1434.    LCD_RW_OUT=0;        
  1435.    LCD_12864_DATA = value;
  1436.    LCD_E_OUT=1;                                                //LCD_EN_OUT由1----0锁存有效数据
  1437.    _nop_();               
  1438.    _nop_();
  1439.    LCD_E_OUT=0;
  1440. }

  1441. /*******************************************************************************************
  1442. ** 函数名称:  void CHOOSE_COLUMN(uchar column)
  1443. ** 功能描述:  设置显示的列
  1444. ** 输 入:    uchar column(设置显示的列)
  1445. **         
  1446. **        
  1447. ** 输 出:   
  1448. **         
  1449. ** 全局变量:
  1450. ** 调用模块:
  1451. **
  1452. ** 作 者:    吴鉴鹰
  1453. ** 日 期:     14.04.09
  1454. ********************************************************************************************/
  1455. void CHOOSE_COLUMN(uchar column)        //设置显示的列        
  1456. {
  1457.   column=column &0x3f;                         //列的最大值为64
  1458.   column= 0x40|column;                         //列的首地址为0x40
  1459.   LCD_COM_WRI(column);        //规定显示的列的位置
  1460. }

  1461. /*******************************************************************************************
  1462. ** 函数名称:  void CHOOSE_PG(uchar page)
  1463. ** 功能描述:  设置“页”LCD12864共8页,一页是8行点阵点
  1464. ** 输 入:    uchar page(送入设置的页数)
  1465. **         
  1466. **        
  1467. ** 输 出:   
  1468. **         
  1469. ** 全局变量:
  1470. ** 调用模块:
  1471. **
  1472. ** 作 者:    吴鉴鹰
  1473. ** 日 期:     14.04.09
  1474. ********************************************************************************************/
  1475. void CHOOSE_PG(uchar page)                //设置“页”LCD12864共8页,一页是8行点阵点        
  1476. {
  1477.   page=0xb8|page;                                 //页的首地址为0xB8
  1478.   LCD_COM_WRI(page);
  1479. }

  1480. /*******************************************************************************************
  1481. ** 函数名称:  void SEL_SCREN(uchar screen)
  1482. ** 功能描述:  LCD选择屏幕  
  1483. ** 输 入:    uchar screen(选择屏幕0:全屏  1:左半屏 2:右半屏)  
  1484. **         
  1485. **        
  1486. ** 输 出:   
  1487. **         
  1488. ** 全局变量:
  1489. ** 调用模块:
  1490. **
  1491. ** 作 者:    吴鉴鹰
  1492. ** 日 期:     14.03.26
  1493. ********************************************************************************************/
  1494. void SEL_SCREN(uchar screen)        //选择屏幕
  1495. {                                                  
  1496.    switch(screen)
  1497.    {
  1498.             case 0: LCD_CS1_OUT=0;LCD_CS2_OUT=0;break; //全屏     
  1499.      case 1: LCD_CS1_OUT=0;LCD_CS2_OUT=1;break;//左半屏        
  1500.      case 2: LCD_CS1_OUT=1;LCD_CS2_OUT=0;break;//右半屏      
  1501.      default:break;
  1502.    }
  1503. }

  1504. /*******************************************************************************************
  1505. ** 函数名称:  void Display_picture(uchar a[][64])
  1506. ** 功能描述:  显示图片的函数  
  1507. ** 输 入:    uchar a[][64](存放图片的数组)  
  1508. **         
  1509. **        
  1510. ** 输 出:   
  1511. **         
  1512. ** 全局变量:
  1513. ** 调用模块:
  1514. **
  1515. ** 作 者:    吴鉴鹰
  1516. ** 日 期:     14.04.09
  1517. ********************************************************************************************/
  1518. void GUI_CLEAR(uchar a[][64])//显示图形—128*64大小
  1519. {
  1520.         uchar i,j;
  1521.         
  1522.         for(j=0;j<8;j++)
  1523.         {        
  1524.                 SEL_SCREN(1);
  1525.                 CHOOSE_PG(j);
  1526.                 CHOOSE_COLUMN(0);
  1527.                 for(i=0;i<64;i++)
  1528.                 {
  1529.                         LCD_DATA_WRI(a[2*j]);//每隔一行取一次数组中的数据
  1530.                 }
  1531.                 SEL_SCREN(2);
  1532.                 CHOOSE_PG(j);
  1533.                 CHOOSE_COLUMN(0);
  1534.                 for(i=0;i<64;i++)
  1535.                 {
  1536.                         LCD_DATA_WRI(a[2*j+1]);//每隔一行取一次数组中的数据
  1537.                 }        
  1538.         }        
  1539. }


  1540. /****************************************************************************
  1541. ** 函数名称:  void main(void)
  1542. ** 功能描述:  贪吃蛇主函数
  1543. ** 输 入:   
  1544. **         
  1545. **        
  1546. ** 输 出:
  1547. **         
  1548. ** 全局变量:
  1549. ** 调用模块:
  1550. **
  1551. ** 作 者:    吴鉴鹰
  1552. ** 作者所在单位:鉴鹰电子工作室
  1553. ** 日 期:     14.04.9
  1554. ****************************************************************************/
  1555. void main()
  1556. {
  1557.           uchar i;
  1558.           uchar count=0;   
  1559.           P2=0xff;
  1560.           EA=1;                  //开CPU中断
  1561.           //ET0=1;          //开定时器中断
  1562.           EX0=1;          //开外部中断
  1563.           EX1=1;
  1564.           CHOOSE_12864_SCREEN(2);
  1565.           Init_12864_HS();
  1566.           CLEAR_12864_SCREEN();

  1567.          
  1568.          
  1569.          ////////////////////
  1570.          Display_16_point(0,4,0,TCS_TAN);
  1571.          Display_16_point(0,6,0,TCS_CHI);
  1572.          Display_16_point(1,0,0,TCS_SHE);
  1573.          ///////////////////
  1574.          Display_16_point(0,2,1,WJYZZ);
  1575.          Display_16_point(0,4,1,WJYZZ+32);
  1576.          Display_16_point(0,6,1,WJYZZ+64);
  1577.          for(i=0;i<2;i++)
  1578.          {
  1579.            Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
  1580.          }

  1581.         Display_16_point(0,0,0,WWJJYYWXTP);
  1582.         Display_16_point(0,2,0,WWJJYYWXTP);
  1583.         Display_16_point(1,2,0,WWJJYYWXTP);
  1584.         Display_16_point(1,4,0,WWJJYYWXTP);
  1585.         Display_16_point(1,6,0,WWJJYYWXTP);
  1586.         
  1587.         Display_16_point(0,0,1,WWJJYYWXTP);
  1588.         Display_16_point(1,4,1,WWJJYYWXTP);
  1589.         Display_16_point(1,6,1,WWJJYYWXTP);
  1590.         
  1591.         
  1592.          //////////////////
  1593.         for(i=0;i<4;i++)
  1594.         {
  1595.             Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
  1596.         }
  1597.         for(i=0;i<4;i++)
  1598.         {
  1599.             Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
  1600.         }


  1601.         for(i=0;i<4;i++)
  1602.         {
  1603.             Display_16_point(0,i<<1,3,(WWJJYYJ+(i<<5))) ;
  1604.         }
  1605.         for(i=0;i<4;i++)
  1606.         {
  1607.             Display_16_point(1,i<<1,3,(WWJJYYHH+(i<<5))) ;
  1608.         }
  1609.             Delay_S(); Delay_S();Delay_S();
  1610.          GUI_CLEAR(table);
  1611.          // while(1);
  1612.          Delay_S(); Delay_S();Delay_S();
  1613.      Delay_S(); Delay_S();Delay_S();
  1614.          //Display_16_point(0,4,2,wnl);
  1615.          //Display_16_point(0,6,2,wnl+32);
  1616.          //Display_16_point(1,0,2,wnl+64);
  1617.          
  1618.          //////////////////
  1619.    for(;;)
  1620.   {
  1621.     if((k==0x03)&&((P3&0x04)==0x04))
  1622.    {
  1623.         count++;
  1624.         k=0;
  1625.         if(count==4)
  1626.         count=1;
  1627.         switch(count)
  1628.         {
  1629.           case 1:
  1630.      {
  1631.                  /*Display_16_point(0,4,2,wnl);
  1632.          Display_16_point(0,6,2,wnl+32);
  1633.          Display_16_point(1,0,2,wnl+64);
  1634.                   Display_16_point_fb(0,4,0);
  1635.          Display_16_point_fb(0,6,0);
  1636.          Display_16_point_fb(1,0,0); */
  1637.                  for(i=0;i<4;i++)
  1638.             {
  1639.                 Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
  1640.             }
  1641.                 for(i=0;i<4;i++)
  1642.             {
  1643.                 Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
  1644.                }
  1645.          };break;
  1646.           case 2:
  1647.           {
  1648.                  Display_16_point(0,4,0,TCS_TAN);
  1649.              Display_16_point(0,6,0,TCS_CHI);
  1650.              Display_16_point(1,0,0,TCS_SHE);
  1651.                  Display_16_point_fb(0,4,1);
  1652.              Display_16_point_fb(0,6,1);
  1653.              for(i=0;i<3;i++)
  1654.              {
  1655.                Display_16_point_fb(1,i<<1,1);
  1656.               }
  1657.             };break;
  1658.           case 3:
  1659.       {         
  1660.              Display_16_point(0,2,1,WJYZZ);
  1661.                  Display_16_point(0,4,1,WJYZZ+32);
  1662.                  Display_16_point(0,6,1,WJYZZ+64);
  1663.                  for(i=0;i<2;i++)
  1664.                  {
  1665.                    Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
  1666.                  }
  1667.                  Display_16_point_fb(0,4,2);
  1668.          Display_16_point_fb(0,6,2);
  1669.          Display_16_point_fb(1,0,2);
  1670.       };break;
  1671.         default:break;
  1672.         }
  1673.   }
  1674.   if(P3&0x04)
  1675.   first=1;
  1676.   if(KEY_FLAG5)
  1677.   {
  1678.      KEY_FLAG5=0;Gluttonous_Snake();count=0;KEY_FLAG5=0;k=0;
  1679.      switch(count)
  1680.         {
  1681.            case 0:count=0;k=3;KEY_FLAG5=0;break;
  1682.            case 1:KEY_FLAG5=0;Gluttonous_Snake();count=0;KEY_FLAG5=0;k=0;break;
  1683.            //case 2:KEY_FLAG5=0;fangkuai();count=0;KEY_FLAG5=0; k=0;break;
  1684.            //case 3:KEY_FLAG5=0;wannianli();count=0;KEY_FLAG5=0;k=0;break;
  1685.            default:count=0;k=3;KEY_FLAG5=0;break;
  1686.         }        
  1687.          CHOOSE_12864_SCREEN(2);
  1688.      Init_12864_HS();
  1689.      CLEAR_12864_SCREEN();
  1690. /////////////////////////////////////
  1691.      Display_16_point(0,4,0,TCS_TAN);
  1692.      Display_16_point(0,6,0,TCS_CHI);
  1693.      Display_16_point(1,0,0,TCS_SHE);
  1694. ////////////////////////////////////
  1695.      Display_16_point(0,2,1,WJYZZ);
  1696.          Display_16_point(0,4,1,WJYZZ+32);
  1697.          Display_16_point(0,6,1,WJYZZ+64);
  1698.          for(i=0;i<2;i++)
  1699.          {
  1700.            Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
  1701.          }
  1702.      /*Display_16_point(0,4,1,WJYZZ);
  1703.      Display_16_point(0,6,1,WJYZZ+32);
  1704.      for(i=0;i<3;i++)
  1705.      {
  1706.        Display_16_point(1,i<<1,1,(WJYZZ+64+(i<<5)));
  1707.      } */
  1708. //////////////////

  1709.      //Display_16_point(0,4,2,wnl);
  1710.      // Display_16_point(0,6,2,wnl+32);
  1711.      //Display_16_point(1,0,2,wnl+64);
  1712. //////////////////
  1713.   }
  1714. }

  1715. }
复制代码



为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-29 23:50 | 显示全部楼层
32、吴鉴鹰12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲(五)——完整资料




原理图下载:
吴鉴12864系列(连载)之基于12864的贪吃蛇游戏的设计详精讲.pdf (258.47 KB, 下载次数: 100)
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

132

TA的帖子

0

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2014-12-30 08:28 | 显示全部楼层
谢谢楼主分享。。。。。。。。。

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-30 20:15 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2014-12-30 20:20 编辑

33.吴鉴鹰总结的Keil编译常见问题(一)

相关文档下载:
Keil编译常见问题(一).pdf (526.21 KB, 下载次数: 135)
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2014-12-30 20:24 | 显示全部楼层
34、吴鉴鹰总结的Keil编译常见问题(二)

相关资料点击下载:
吴鉴鹰总结的Keil编译常见问题(二)_eeworld上传的.pdf (518.17 KB, 下载次数: 117)
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

67

TA的帖子

2

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2015-1-4 08:12 | 显示全部楼层
支持版主真正无私奉献。

点评

谢谢大力支持!  详情 回复 发表于 2015-1-4 21:42

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-4 21:42 | 显示全部楼层
qiang7260 发表于 2015-1-4 08:12
支持版主真正无私奉献。



谢谢大力支持!
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-7 09:53 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2015-1-7 09:56 编辑

35、吴鉴鹰12864系列(连载)之基于12864的俄罗斯方块游戏的设计详精讲(一)——思路简单介绍



    当年吴鉴鹰还是很小的时候,有一种掌上游戏机,里面有一款游戏叫做俄罗斯方块,那时的我们只是简单的按照游戏规则进行“堆积木”,而其中的原理却很少有人去思考,毕竟当时的我们都还很年幼。我相信大家一定见识过不同种类的俄罗斯方块吧!




    基于单片机课程设计的机会,我们这个小组将使用51单片机和12864的组合,来实现比较简单的俄罗斯方块设计。
    此次设计初期是在keil和proteus联合仿真中进行,C51编程!



游戏是人们活动中一项非常重要的内容,有人认为如果哪一天人类对所有的游戏都失去兴趣,恐怕世界的末日就要到了。电脑对游戏的贡献有目共睹,现在摸过电脑的人很少有没玩过电脑游戏的,喜欢游戏的人也很少有不玩电脑的。




俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它曾经造成的轰动与造成的经济价值可以说是游戏史上的一件大事。这款游戏最初是由苏联的游戏制作人Alex Pajitnov制作的,它看似简单但却变化无穷,令人上瘾。相信大多数用户都还记得为它痴迷得茶不思饭不想的那个俄罗斯方块时代。






究其历史,俄罗斯方块最早还是出现在PC机上,而我国的用户都是通过红白机了解、喜欢上它的。现在联众又将重新掀起这股让人沉迷的俄罗斯方块风潮。







对一般用户来说,它的规则简单,容易上手,且游戏过程变化无穷,而在"联众俄罗斯方块"中,更有一些联众网络游戏所独有的魅力――有单机作战与两人在线对战两种模式,用户可任选一种进行游戏。网络模式还增加了积分制,使用户既能感受到游戏中的乐趣,也给用户提供了一个展现自己高超技艺的场所。







俄罗斯方块游戏可以说是随计算机的发展而发展,并不断推陈出新演变出各种类似游戏, 深受广大玩家喜爱。这个游戏有的简单, 有的复杂, 但其根本原理是一样的都是对运动的方块进行组合, 来训练玩家的反应能力。本文利用单片机进行俄罗斯方块设计,采用C51语言进行编程




现今国内外的俄罗斯方块游戏设计主要有基于PC机上Windows平台的俄罗斯方块游戏、基于手机平台的智能俄罗斯方块游戏以及基于单片机平台的俄罗斯方块游戏等。




前两种属于高端游机,性能优越,但成本高,而且计算机编程已不是新命题,VB、VC、Delphi版本的俄罗斯方块游戏都有发布[9]





从学术角度来看,针对俄罗斯方块游戏的开发,国内外也有不少学者展开过研究,比如Niko将进化算法引入到俄罗斯方块中并验证了其有效性,Hoogeboom探讨了俄罗斯方块游戏的构造问题,王宇等针对存在于俄罗斯方块中的两个数学问题提出解决方案,高凌琴探讨游戏功能要求、数据结构、图形旋转、坐标变换等关键技术,胡代弟在SPCE061A单片机实现了俄罗斯方块游戏[10]

综上,国内外的研究多着重于游戏数学原理的讨论,也有部分文献涉及游戏的具体实现,但多是在Windows操作系统下实现的,在单片机平台下的开发俄罗斯方块游戏鲜少有文献刊载。而单片机由于具有体积小、性能突出、价格低廉等特点,应用领域不断扩大,除了工业控制、智能化仪表、家用电器外,在智能化高档电子玩具产品也大量采用单片机芯片作为核心控制部件。曾经80年代非常流行的掌上游戏机便是单片机在电子玩具中的应用之一,其中的俄罗斯方块游戏现已被我们所熟知。




本文探讨基于8051单片机硬件平台和RTX51 Tiny多任务实时操作系统的俄罗斯方块游戏的设计与实现,将理论与实践相结合。其主要目标是再现经典的俄罗斯方块游戏,并在此基础上实现双人单机对战游戏模式,以丰富产品功能,增强游戏的趣味性。


为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

32

TA的帖子

0

TA的资源

一粒金砂(初级)

Rank: 1

发表于 2015-1-8 23:19 | 显示全部楼层
要是当年有LZ多好呀。

点评

吴鉴鹰现在来了也不迟嘛,哈哈  详情 回复 发表于 2015-1-10 14:20

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-10 14:20 | 显示全部楼层
3108009356 发表于 2015-1-8 23:19
要是当年有LZ多好呀。


吴鉴鹰现在来了也不迟嘛,哈哈

为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-10 14:29 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2015-1-10 14:36 编辑

36、吴鉴鹰12864系列(连载)之基于12864的俄罗斯方块游戏的设计详精讲(二)——俄罗斯方块旋转算法的坐标实现


1 引言
大家都知道!俄罗斯方块游戏是一个古老而著名的益智游戏。它的知名度迎来了无数程序员青睐。旋转算法是该游戏实现的一个关键技术,现有的大多数算法都是以数组为基本数据结构来实现方块的旋转。吴鉴鹰本文探讨了俄罗斯方块的另一种实现方式,即尽量不用或着是少用数组的概念,而是用坐标来取代。并重点探讨一种算法叫做旋转算法。

2 程序基础
基块是本程序的最基本单位。程序的实现都是通过对基块的操作实现的。基块为一个小正方形,其边长可设为bs(basesize)。而bs 就是本程序的粒度大小。设正方形的中心代表整个方块。设游戏区为一个坐标区,则可通过一个坐标(X,Y)就可以来定位基块,这里的坐标就是基块的中心坐标。由于基块是正方形的,又一般画图函数都是以左上和右下定位图形,所以换算出左上角坐标(X-1/2*bs,Y+1/2*bs)和右下角坐标(X+1/2*bs,Y-1/2*bs)就可以画出基块。因而定义一个接受X,Y 值的函数就可实现基块的定位及绘图。俄罗斯方块的7 类方块都可以由基块组合而成,当然开发更多更具创意的方块也就比较容易了。
下面讨论程序的两个重要概念。定义2.1 绝对坐标系为上文提到的游戏区,坐标原点和XY 轴方向都是固定的。它在整个游戏过程中为基块提供确切的坐标。
定义2.2 相对坐标系。它的引入是为了简化旋转算法的实现。从下文旋转算法可知,只要将该坐标系的原点和XY 轴方向改变,就可实现方块的旋转。故相对坐
标系的坐标原点,XY 轴方向都是可以改变的。该类坐标系原点逻辑原点坐标为O(其在程序中透明),故实现时主要使用它的实际原点坐标(该原点在绝对坐标系中的坐标)。现假设其实际原点坐标为(X,Y),设在该相对坐标系内的一点坐标为(x,y),则该点的绝对坐标为(X+x,Y+y)。
图1 俄罗斯游戏中的7 类方块
首先为了说明的方便将7 类方块编号如图1 所示。



1.png

                       图1
由于5 号方块的旋转只有一种状态,为了提高程序效率,
将其单独分为一类。其余方块另为一类。
现在通过实现俄罗斯方块的移动来看看上述设置
是如何运作的。现假设要移动的方块为田字类型。为其建立一个相对坐标系,设其原点实际坐标为 ,将 , 值及方块的类型传递到一个处理函数。该函数根据坐标原点,方块类型,计算出组成该方块的四个基块的中心坐标,再将该四个坐标分别传递给四个基块处理函数,这样便可画出该类型的方块。现将方块向右移动。就是整个相对坐标系向右移动一个bs 的距离,即原点实际坐标变为(X+1,Y),再按刚才的方法处理就可画出移动后的方块。至于前一个方块,可以通过设置的
NOTXOR 绘图模式,再重绘前一个方块来实现。这样
7 类方块的左移,右移,下移便可简单的实现了。下面
讨论7 类方块的旋转算法。

3 旋转算法的实现
旋转算法是游戏实现的一个关键技术,下面就讨论
俄罗斯方块旋转算法的实现。
五号方块只有一种状态,所以,旋转函数收到5 号
方块时,不需做任何处理就可退出函数。是这7 类中最简单的一种类型。
其他方块的旋转要分三步,第一步,将它们所在的
坐标系逆时针旋转90°,第二步,将坐标原点向右偏移
一定的距离,使整个方块在绝对坐标系里的位置保持不
变。第三步,将旋转后的方块画出后,再将相对坐标原
点移回到原来的位置。

第一步的实现,主要使用坐标旋转公式
xl=cos(angle)*x-sin(angle)*y;yl=cos(angle)*y+sin(angle)
*x;
由于angle=90°,故xl=-y,yl=x。则处理函数将原
坐标的x 轴作为旋转后的y 轴,原坐标的-y 做为旋转后
x 轴坐标。
第二步的实现,先计算出旋转后该方块4 个坐标 分
量的绝对值的最大值减1 作为原坐标向右的偏移量(减
1 是因为坐标原点没有旋转)。这样处理函数通过坐标原点的值和转变后的坐标就可以画出旋转后方块的形状。
第三步,只需将坐标原点向左偏移刚才向右的偏移量即可。
每次旋转都按相同的操作执行,其中第三步的是为了下次旋转作准备。
下面通过旋转1 号方块来验证该算法。




2.png
                                      图 2
初始状态第一步:坐标系逆时针旋转90°第二步:
将坐标原点向右偏移
第三步,将旋转后的方块画出后,再将相对坐标


3.png

                                   图 3

原点再移回原来的位置
      图2 旋转算法的实现步骤图
当方块处于初始状态时,其相对坐标为(0,0)(, 1,0),
(2,0)(, 0,1),设其原点坐标为(1,1),则绝对坐标为(1,1),
(2,1),(3,1),(1,2)。第一步后,坐标变为(0,0),(0,1),
(0,2)(, -1,0),向右偏移量为2-1=1,原点坐标变为(2,1),
(2,2),(2,3),(1,1),它就是旋转后方块的绝对坐标。
再把这四个坐标分别传递到基块处理函数中,旋转后的
方块就可以画出。最后,将坐标原点变为原来的(1,1),
准备下次的旋转。
以上就是方块的旋转算法。

4 小结
本文讨论了使用坐标的转换来实现俄罗斯方块游戏的重要算法——旋转算法。将俄罗斯方块分解成四个的独立基块,由于基块可用坐标简单的定位,从而可实现
方块的定位。故方块就可用四个坐标来简化。从而方块的旋转就可以通过坐标轴的旋转来实现。

为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-10 14:39 | 显示全部楼层

37、吴鉴鹰12864系列(连载)之基于12864的俄罗斯方块游戏的设计详精讲(二)——俄罗斯算法程序

  1. /****************************************************************************
  2. ** 函数名称:  void Russia_Box_Fuction(void)
  3. ** 功能描述:  俄罗斯方块子程序
  4. ** 输 入:   
  5. **         
  6. **        
  7. ** 输 出:
  8. **         
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者:    吴鉴鹰
  13. ** 作者所在单位:鉴鹰电子工作室
  14. ** 日 期: 2014.05.10
  15. ****************************************************************************/
  16. void Russia_Box_Fuction(void)
  17. {
  18.   uchar fenshu=0;
  19.   char offsety,offsetx;
  20.   char offsety_buff,offsetx_buff;
  21.   uchar buff=0x10;                 
  22.   bit ting=0;                                                               
  23.   uchar i;
  24.   //flag5=1;
  25.   TMOD=1;          //定时器工作方式
  26.   IT0=1;          //边延有效
  27.   IT1=1;
  28.   EA=1;                  //开CPU中断
  29.   ET0=1;          //开定时器中断
  30.   EX0=1;          //开外部中断
  31.   EX1=1;
  32.   TL0=0x00;
  33.   TH0=0x00;          //定时器初值
  34.   TR0=1;          //启动定时器
  35.   k=5;
  36.   Choice_12864_Screen(2);
  37.   Clear_12864_Screen();
  38.   Display_16_point(0,0,0,WJYJ);
  39.   Display_16_point(0,0,1,WJYJ+32);
  40.   Display_16_point(0,0,2,RussiaBOX);
  41.   Display_16_point(0,2,0,RussiaBOX+32);
  42.   Display_16_point(0,2,1,RussiaBOX+64);
  43.   Display_16_point(0,2,2,RussiaBOX+96);
  44.   Display_16_point(0,2,3,RussiaBOX+128);
  45.   Display_8_point(0,0,3,Num0);
  46.   Display_8_point(0,1,3,Num0);
  47.   Draw_Vertical_line(1,60,30);
  48.   Draw_Vertical_line(1,60,127);
  49.   for(i=0;i<98;i++)
  50.   {
  51.     Draw_dot_Hs(30+i,1);
  52.         Draw_dot_Hs(30+i,62);
  53.   }
  54.   offsety=7;
  55.   offsetx=-3;
  56.   for(;;)
  57. {
  58.    if(P3&0x04)
  59.    first=1;
  60.    if((k==0x02)&&((P3&0x04)==0x04))
  61.    {
  62.      offsety_buff=offsety;
  63.          ting=Stop_Dir_Right(buff,offsetx,offsety);
  64.         if(!ting)
  65.          {
  66.           if(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0x0f)+offsety)
  67.       offsety--;
  68.           Clear_bufF_Fuc(buff,offsetx_buff,offsety_buff);
  69.           Play_Buf_Model(buff,offsetx,offsety);
  70.           offsety_buff=offsety;
  71.          
  72.     }
  73.           k=5;
  74.    }
  75.    if((k==0x01)&&((P3&0x04)==0x04))
  76.    {

  77.      offsety_buff=offsety;
  78.          ting=Stop_Dir_Left(buff,offsetx,offsety);
  79.          if(!ting)
  80.         {
  81.           if(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0x0f)+offsety<=13)
  82.      offsety++;
  83.          k=5;
  84.          Clear_bufF_Fuc(buff,offsetx_buff,offsety_buff);
  85.          Play_Buf_Model(buff,offsetx,offsety);
  86.          offsety_buff=offsety;
  87.         }
  88.    }
  89.    if((k==0x03)&&((P3&0x04)==0x04))
  90.    {
  91.      dengji=36;/////////////
  92.          k=5;
  93.    }
  94.    if((k==0x00)&&((P3&0x04)==0x04))
  95.    {
  96.       uchar i;
  97.           k=5;
  98.           i=buff;
  99.           buff++;
  100.           if((buff&0x0f)>=4)
  101.           buff=buff&0xf0;
  102.          
  103.           //Change_4_Dot1(0,14);
  104.       if(((*(((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0x0f)+offsety)>14)
  105.        {
  106.              do
  107.                   {
  108.                           offsety--;
  109.                   }while((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0x0f)+offsety)>14);
  110.                  
  111.            }
  112.           if(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0x0f)+offsety<0)
  113.           {
  114.             do
  115.                 {
  116.                   offsety++;
  117.                 }while(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0x0f)+offsety);
  118.           }
  119.           Clear_bufF_Fuc(i,offsetx_buff,offsety_buff);
  120.           Play_Buf_Model(buff,offsetx,offsety);
  121.    }
  122.    ting=Stop_Dir_Down(buff,offsetx,offsety);
  123.    while(flag5);
  124.    if(flag1)
  125.    {
  126.      offsetx_buff=offsetx;
  127.          offsety_buff=offsety;
  128.      offsetx++;
  129.          Clear_bufF_Fuc(buff,offsetx_buff,offsety_buff);
  130.          Play_Buf_Model(buff,offsetx,offsety);
  131.      offsetx_buff=offsetx;
  132.          flag1=0;
  133.     }
  134.    if((((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+1)))&0xf0)>>4)+offsetx)>22)|ting)
  135.    {
  136.     uchar i=0;
  137.         if(Line_Disapp_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+1)))&0xf0)>>4)+offsetx))
  138.         {Elim_Line_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+1)))&0xf0)>>4)+offsetx);fenshu++;i++;}
  139.    
  140.         if((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0xf0)>>4)+offsetx>=(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0xf0)>>4)+offsetx)         //x2>=x3
  141.         {
  142.          if((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2))+1)))&0xf0)>>4)+offsetx)        //x2<x1
  143.          {
  144.            if(Line_Disapp_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+2)))&0xf0)>>4)+offsetx+i))
  145.            {Elim_Line_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+2)))&0xf0)>>4)+offsetx+i);fenshu++;i++;}
  146.          }
  147.          if((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0xf0)>>4)+offsetx)         //x3<x2
  148.           {
  149.            if(Line_Disapp_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+3)))&0xf0)>>4)+offsetx+i))
  150.            {Elim_Line_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+3)))&0xf0)>>4)+offsetx+i);fenshu++;i++;}
  151.           }
  152.          if((((*(Model+((buff&0xf0)|((buff&0x0f)<<2))))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0xf0)>>4)+offsetx)         //x0<x3
  153.          {
  154.            if(Line_Disapp_Fu((((*(Model+((buff&0xf0)+((buff&0x0f)<<2))))&0xf0)>>4)+offsetx+i))
  155.            {Elim_Line_Fu((((*(Model+((buff&0xf0)+((buff&0x0f)<<2))))&0xf0)>>4)+offsetx+i);fenshu++;i++;}
  156.          }
  157.         }
  158.         if((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0xf0)>>4)+offsetx) //x2<x3
  159.         {
  160.            if((((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+3))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2))+1)))&0xf0)>>4)+offsetx)
  161.            {
  162.               if(Line_Disapp_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+3)))&0xf0)>>4)+offsetx+i))
  163.               {
  164.                Elim_Line_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+3)))&0xf0)>>4)+offsetx+i);fenshu++;i++;
  165.               }
  166.            }
  167.            if(Line_Disapp_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+2)))&0xf0)>>4)+offsetx+i))
  168.            {
  169.              Elim_Line_Fu((((*((Model+((buff&0xf0)+((buff&0x0f)<<2))+2)))&0xf0)>>4)+offsetx+i);fenshu++;i++;
  170.            }
  171.            if((((*(Model+((buff&0xf0)|((buff&0x0f)<<2))))&0xf0)>>4)+offsetx<(((*((Model+((buff&0xf0)|((buff&0x0f)<<2)))+2))&0xf0)>>4)+offsetx)
  172.            {
  173.               if(Line_Disapp_Fu((((*(Model+((buff&0xf0)+((buff&0x0f)<<2))))&0xf0)>>4)+offsetx+i))
  174.               {
  175.                Elim_Line_Fu((((*(Model+((buff&0xf0)+((buff&0x0f)<<2))))&0xf0)>>4)+offsetx+i);fenshu++;i++;
  176.                }
  177.            }
  178.         }
  179.          
  180.         Display_8_point(0,0,3,Num0+((fenshu/10)<<4));
  181.         Display_8_point(0,1,3,Num0+((fenshu%10)<<4));
  182.         dengji=fenshu/5;
  183.         if(((((*(Model+((buff&0xf0)+((buff&0x0f)<<2))))&0xf0)>>4)+offsetx)<1)
  184.         {

  185.           Delay_1ms(450);
  186.       Delay_1ms(450);
  187.       Choice_12864_Screen(2);
  188.       Clear_12864_Screen();
  189.       Display_16_point(0,4,1,Game_Over);
  190.       Display_16_point(0,6,1,Game_Over+32);
  191.       Display_16_point(1,0,1,Game_Over+64);
  192.       Display_16_point(1,2,1,Game_Over+96);
  193.       Delay_1ms(450);
  194.       Delay_1ms(450);
  195.       break;
  196.         }        
  197.         buff=(((TL0%7)<<4)|(TH0%4));
  198.         //buff=0x11;
  199.     offsety=7;
  200.     offsetx=-3;
  201.         offsetx_buff=-9;
  202.         offsety_buff=-9;
  203.         }
  204. }

  205. }
复制代码




为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-12 13:26 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2015-1-14 09:30 编辑
38、吴鉴鹰12864系列(连载)之基于12864的俄罗斯方块游戏的设计详精讲(四)——底层程序讲解
  1. /****************************************************************************

  2. ** 函数名称: void Draw_dot_Hs(uchar x,uchar y)
  3. ** 功能描述: 画点函数
  4. ** 输 入: uchar x,uchar y 画点的x和y坐标
  5. **
  6. **
  7. ** 输 出:
  8. **
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者: 吴鉴鹰
  13. ** 作者所在单位:鉴鹰电子工作室
  14. ** 日 期: 14.05.10
  15. ****************************************************************************/
  16. /**点的显示**/
  17. void Draw_dot_Hs(uchar x,uchar y)
  18. {
  19. uchar dat;
  20. if(x>63)
  21. {
  22. Choice_12864_Screen(1);
  23. x=x-64;
  24. }
  25. else
  26. {
  27. Choice_12864_Screen(0);
  28. }
  29. dat=Lcd_Data_Write(y/8,x);
  30. Cmd_Write_12864(0x40|x);
  31. Cmd_Write_12864(0xb8|y/8);
  32. Dat_Write_12864((1<<(y%8))|dat);
  33. }

    /****************************************************************************

  34. ** 函数名称: Clear_8_Dot(uchar x,uchar y,uchar ch)
  35. ** 功能描述: 清点函数
  36. ** 输 入: uchar x,uchar y 清点的x和y坐标
  37. **
  38. **
  39. ** 输 出:
  40. **
  41. ** 全局变量:
  42. ** 调用模块:
  43. **
  44. ** 作 者: 吴鉴鹰
  45. ** 作者所在单位:鉴鹰电子工作室
  46. ** 日 期: 14.05.10
  47. ****************************************************************************/
  48. Clear_8_Dot(uchar x,uchar y,uchar ch)
  49. {
  50. uchar i;
  51. Choice_12864_Screen(ch);
  52. Cmd_Write_12864(x*8+0x40);
  53. Cmd_Write_12864(y+0xb8);
  54. for(i=0;i<8;i++)
  55. {
  56. Dat_Write_12864(0x00);
  57. }
  58. Cmd_Write_12864(x*8+0x40);
  59. Cmd_Write_12864(y+0xb9);
  60. for(i=0;i<16;i++)
  61. {
  62. Dat_Write_12864(0x00);
  63. }
  64. }

    /****************************************************************************

  65. ** 函数名称: void Change_4_Dot(uchar *x,uchar *y) //x<24 y<15
  66. ** 功能描述: 4X4个点合为一个
  67. ** 输 入: uchar *x,uchar *y 合点的首地址
  68. **
  69. **
  70. ** 输 出:
  71. **
  72. ** 全局变量:
  73. ** 调用模块:
  74. **
  75. ** 作 者: 吴鉴鹰
  76. ** 作者所在单位:鉴鹰电子工作室
  77. ** 日 期: 14.05.10
  78. ****************************************************************************/
  79. void Change_4_Dot(uchar *x,uchar *y) //x<24 y<15
  80. {
  81. uchar i,m,n; //24和15分别表示游戏的范围
  82. if(*x<24&&*y<15) //这里的点是个有花色的点而不是一个实心的点
  83. {
  84. m=(*x)<<2;
  85. n=((*y)<<2)+2;
  86. for(i=0;i<4;i++)
  87. {
  88. Draw_dot_Hs(31+m,n+i);
  89. Draw_dot_Hs(34+m,n+i);
  90. }
  91. Draw_dot_Hs(32+m,n);
  92. Draw_dot_Hs(32+m,n+1);
  93. Draw_dot_Hs(32+m,n+3);
  94. Draw_dot_Hs(33+m,n);
  95. Draw_dot_Hs(33+m,n+2);
  96. Draw_dot_Hs(33+m,n+3);
  97. }
  98. }

  99. /****************************************************************************
  100. ** 函数名称: void Change_4_Dot(uchar *x,uchar *y) //x<24 y<15
  101. ** 功能描述: 4X4个点合为一个
  102. ** 输 入: uchar *x,uchar *y 合点的首地址
  103. **
  104. **
  105. ** 输 出:
  106. **
  107. ** 全局变量:
  108. ** 调用模块:
  109. **
  110. ** 作 者: 吴鉴鹰
  111. ** 作者所在单位:鉴鹰电子工作室
  112. ** 日 期: 14.05.10
  113. ****************************************************************************/
  114. void Change_4_Dot1(uchar x,uchar y) //x<24 y<15
  115. {

    uchar i,m,n;

  116. EA=0; //24和15分别表示游戏的范围
  117. if(x<24&&y<15) //这里的点是个有花色的点而不是一个实心的点
  118. {
  119. m=(x)<<2;
  120. n=(y<<2)+2;
  121. for(i=0;i<4;i++)
  122. {
  123. Draw_dot_Hs(31+m,n+i);
  124. Draw_dot_Hs(34+m,n+i);
  125. }
  126. Draw_dot_Hs(32+m,n);
  127. Draw_dot_Hs(32+m,n+1);
  128. Draw_dot_Hs(32+m,n+3);
  129. Draw_dot_Hs(33+m,n);
  130. Draw_dot_Hs(33+m,n+2);
  131. Draw_dot_Hs(33+m,n+3);
  132. }
  133. EA=1;

    }

  134. /****************************************************************************
  135. ** 函数名称: void cleardot(uchar x,uchar y)
  136. ** 功能描述: 清点函数
  137. ** 输 入: uchar x,uchar y 需要清点的地址
  138. **
  139. **
  140. ** 输 出:
  141. **
  142. ** 全局变量:
  143. ** 调用模块:
  144. **
  145. ** 作 者: 吴鉴鹰
  146. ** 作者所在单位:鉴鹰电子工作室
  147. ** 日 期: 14.05.10
  148. ****************************************************************************/
  149. void Clear_Dot_Hs(uchar x,uchar y)
  150. {
  151. uchar dat,j;
  152. if(x>63)
  153. {
  154. Choice_12864_Screen(1);
  155. x=x-64;
  156. }
  157. else
  158. {
  159. Choice_12864_Screen(0);
  160. }
  161. dat=Lcd_Data_Write(y/8,x);
  162. Cmd_Write_12864(0x40|x);
  163. Cmd_Write_12864(0xb8|(y/8));
  164. j=~(1<<(y%8));
  165. Dat_Write_12864(dat&j);
  166. }

    /****************************************************************************

  167. ** 函数名称: void Clear_Dot_four(uchar *x,uchar *y)
  168. ** 功能描述: 清除一个4X4的点
  169. ** 输 入: uchar *x,uchar *y 需要清点的地址指针
  170. **
  171. **
  172. ** 输 出:
  173. **
  174. ** 全局变量:
  175. ** 调用模块:
  176. **
  177. ** 作 者: 吴鉴鹰
  178. ** 作者所在单位:鉴鹰电子工作室
  179. ** 日 期: 14.05.10
  180. ****************************************************************************/
  181. void Clear_Dot_four(uchar *x,uchar *y)
  182. {
  183. uchar i,m,n;
  184. m=((*x)<<2)+31;
  185. n=((*y)<<2)+2;
  186. for(i=0;i<4;i++)
  187. {
  188. Clear_Dot_Hs(m,n+i);
  189. Clear_Dot_Hs(m+1,n+i);
  190. Clear_Dot_Hs(m+2,n+i);
  191. Clear_Dot_Hs(m+3,n+i);
  192. }
  193. }

    /****************************************************************************

  194. ** 函数名称: void Clear_Dot_four(uchar *x,uchar *y)
  195. ** 功能描述: 清除一个4X4的点
  196. ** 输 入: uchar x,uchar y 需要清点的地址
  197. **
  198. **
  199. ** 输 出:
  200. **
  201. ** 全局变量:
  202. ** 调用模块:
  203. **
  204. ** 作 者: 吴鉴鹰
  205. ** 作者所在单位:鉴鹰电子工作室
  206. ** 日 期: 14.05.10
  207. ****************************************************************************/
  208. void Clear_Four_DoT(uchar x,uchar y)
  209. {
  210. uchar i,m,n;
  211. if(x>=0&&x<24&&y>=0&&y<15)
  212. {
  213. m=((x)<<2)+31;
  214. n=((y)<<2)+2;
  215. for(i=0;i<4;i++)
  216. {
  217. Clear_Dot_Hs(m,n+i);
  218. Clear_Dot_Hs(m+1,n+i);
  219. Clear_Dot_Hs(m+2,n+i);
  220. Clear_Dot_Hs(m+3,n+i);
  221. }
  222. }
  223. }

    /****************************************************************************

  224. ** 函数名称: bit Read_Fk_Dot(char x,char y)
  225. ** 功能描述: 清除一个点
  226. ** 输 入: uchar x,uchar y 需要清点的地址
  227. **
  228. **
  229. ** 输 出:
  230. **
  231. ** 全局变量:
  232. ** 调用模块:
  233. **
  234. ** 作 者: 吴鉴鹰
  235. ** 作者所在单位:鉴鹰电子工作室
  236. ** 日 期: 14.05.10
  237. ****************************************************************************/
  238. bit Read_Fk_Dot(char x,char y)
  239. {
  240. bit flagfk=0;
  241. uchar m,n;
  242. if(y>=0)
  243. {
  244. m=(x<<2)+31;
  245. n=(y<<2)+2;
  246. Choice_12864_Screen(0);
  247. if(m>63)
  248. {
  249. m=m-64;
  250. Choice_12864_Screen(1);
  251. }
  252. m=Lcd_Data_Write(n>>3,m);
  253. if((n%8)==2)
  254. {
  255. if((m&0x3c)==0x3c)
  256. {
  257. flagfk=1;
  258. }
  259. else
  260. {
  261. flagfk=0;
  262. }
  263. }
  264. if((n%8)==6)
  265. {
  266. if((m&0xc0)==0xc0)
  267. {flagfk=1;

    }

  268. else
  269. {flagfk=0;}
  270. }
  271. }
  272. return(flagfk);

    }

复制代码
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

140

TA的帖子

1

TA的资源

一粒金砂(中级)

Rank: 2

发表于 2015-1-12 15:16 | 显示全部楼层
感谢分享~~~~~收藏了

点评

谢谢支持!  详情 回复 发表于 2015-1-13 17:20

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-13 17:20 | 显示全部楼层
hgy10086 发表于 2015-1-12 15:16
感谢分享~~~~~收藏了



谢谢支持!
为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

364

TA的帖子

0

TA的资源

纯净的硅(初级)

Rank: 4

 楼主| 发表于 2015-1-14 09:37 | 显示全部楼层
本帖最后由 吴鉴鹰. 于 2015-1-14 09:43 编辑

39、吴鉴鹰12864系列(连载)之基于12864的俄罗斯方块游戏的设计详精讲(五)——主程序讲解
  1. /*******************************************************************************************
  2. ** 函数名称:  main(void)
  3. ** 功能描述:  整个程序的框架
  4. ** 输 入:   
  5. **         
  6. **        
  7. ** 输 出:   
  8. **         
  9. ** 全局变量:
  10. ** 调用模块:
  11. **
  12. ** 作 者:    吴鉴鹰
  13. ** 日 期:     14.05.16
  14. ********************************************************************************************/
  15. //////////////////////////////
  16. void main(void)
  17. {
  18.     uchar i;
  19.     uchar count=0;
  20.     P2=0xff;
  21.     EA=1;                  //开CPU中断
  22.     //ET0=1;          //开定时器中断
  23.     EX0=1;          //开外部中断
  24.     EX1=1;
  25.     Choice_12864_Screen(2);
  26.     Init_12864_Screen();
  27.     Clear_12864_Screen();
  28.     ////////////////////
  29.     // play16(0,4,0,Tan);
  30.     //play16(0,6,0,Chi);
  31.     //play16(1,0,0,Snake);
  32.     ///////////////////
  33.     Display_16_point(0,2,0,RussiaBOX);
  34.     Display_16_point(0,4,0,RussiaBOX+32);
  35.         Display_16_point(0,6,0,RussiaBOX+64);
  36.     for(i=0;i<2;i++)
  37.     {
  38.         Display_16_point(1,i<<1,0,(RussiaBOX+96+(i<<5)));
  39.     }

  40.          Display_16_point(0,2,1,WJYZZ);
  41.         Display_16_point(0,4,1,WJYZZ+32);
  42.         Display_16_point(0,6,1,WJYZZ+64);
  43.         for(i=0;i<2;i++)
  44.         {
  45.            Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
  46.         }

  47.         Display_16_point(0,0,0,WWJJYYWXTP);
  48.         //Display_16_point(0,2,0,WWJJYYWXTP);
  49.         //Display_16_point(1,2,0,WWJJYYWXTP);
  50.         Display_16_point(1,4,0,WWJJYYWXTP);
  51.         Display_16_point(1,6,0,WWJJYYWXTP);
  52.         
  53.         Display_16_point(0,0,1,WWJJYYWXTP);
  54.         Display_16_point(1,4,1,WWJJYYWXTP);
  55.         Display_16_point(1,6,1,WWJJYYWXTP);

  56.          
  57.          //////////////////
  58.         for(i=0;i<4;i++)
  59.         {
  60.             Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
  61.         }
  62.         for(i=0;i<4;i++)
  63.         {
  64.             Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
  65.         }

  66.         for(i=0;i<4;i++)
  67.         {
  68.             Display_16_point(0,i<<1,3,(WWJJYYJ+(i<<5))) ;
  69.         }
  70.         for(i=0;i<4;i++)
  71.         {
  72.             Display_16_point(1,i<<1,3,(WWJJYYHH+(i<<5))) ;
  73.         }

  74.          //while(1);
  75.             Delay_S(); Delay_S();Delay_S();
  76.          GUI_CLEAR(Start_picture);
  77.          // while(1);
  78.           Delay_S(); Delay_S();Delay_S();
  79.      Delay_S(); Delay_S();Delay_S();
  80.         

  81. //////////////////

  82. //play16(0,4,2,Per_Cal_Li);
  83. //play16(0,6,2,Per_Cal_Li+32);
  84. //play16(1,0,2,Per_Cal_Li+64);

  85. //////////////////
  86. for(;;)
  87.   {
  88.     if((k==0x03)&&((P3&0x04)==0x04))
  89.    {
  90.         count++;
  91.         k=0;
  92.         if(count==4)
  93.         count=1;
  94.         switch(count)
  95.         {
  96.           case 1:
  97.                  {
  98.                             Display_16_point(0,4,2,Per_Cal_Li);
  99.                 Display_16_point(0,6,2,Per_Cal_Li+32);
  100.                 Display_16_point(1,0,2,Per_Cal_Li+64);
  101.                                 play16_fb(0,4,0);
  102.                 play16_fb(0,6,0);
  103.                 play16_fb(1,0,0);
  104.                          };break;
  105.           case 2: {
  106.                                       Display_16_point(0,4,0,Tan);
  107.                  Display_16_point(0,6,0,Chi);
  108.                  Display_16_point(1,0,0,Snake);
  109.                                  play16_fb(0,4,1);
  110.                  play16_fb(0,6,1);
  111.                  for(i=0;i<3;i++)
  112.                  {
  113.                    play16_fb(1,i<<1,1);
  114.                   }
  115.                     };break;
  116.           case 3:
  117.                   {
  118.                     
  119.                                  Display_16_point(0,4,1,RussiaBOX);
  120.                  Display_16_point(0,6,1,RussiaBOX+32);
  121.                  for(i=0;i<3;i++)
  122.                  {
  123.                    Display_16_point(1,i<<1,1,(RussiaBOX+64+(i<<5)));
  124.                  }
  125.                                  play16_fb(0,4,2);
  126.                  play16_fb(0,6,2);
  127.                  play16_fb(1,0,2);
  128.                   };break;
  129.               default:break;
  130.         }
  131.   }         
  132.   if(P3&0x04)
  133.   first=1;
  134.   if(flag5)
  135.   {
  136.     /*switch(count)
  137.         {
  138.         //          case 1:flag5=0;/*TanChiSnake();count=0;flag5=0;k=0;break;
  139.         //          case 2:flag5=0;Russia_Box_Fuction();count=0;flag5=0; k=0;break;
  140.         //          case 3:flag5=0;/*wannianli();count=0;flag5=0;k=0;break;
  141.         //          default:count=0;k=3;flag5=0;break;
  142.         //        }  */
  143.          flag5=0;
  144.          k=0;
  145.          Russia_Box_Fuction();
  146.          Choice_12864_Screen(2);
  147.      Init_12864_Screen();
  148.      Clear_12864_Screen();
  149.           Display_16_point(0,2,0,RussiaBOX);
  150.     Display_16_point(0,4,0,RussiaBOX+32);
  151.         Display_16_point(0,6,0,RussiaBOX+64);
  152.     for(i=0;i<2;i++)
  153.     {
  154.         Display_16_point(1,i<<1,0,(RussiaBOX+96+(i<<5)));
  155.     }

  156.          Display_16_point(0,2,1,WJYZZ);
  157.         Display_16_point(0,4,1,WJYZZ+32);
  158.         Display_16_point(0,6,1,WJYZZ+64);
  159.         for(i=0;i<2;i++)
  160.         {
  161.            Display_16_point(1,i<<1,1,(WJYZZ+96+(i<<5)));
  162.         }

  163.         Display_16_point(0,0,0,WWJJYYWXTP);
  164.         //Display_16_point(0,2,0,WWJJYYWXTP);
  165.         //Display_16_point(1,2,0,WWJJYYWXTP);
  166.         Display_16_point(1,4,0,WWJJYYWXTP);
  167.         Display_16_point(1,6,0,WWJJYYWXTP);
  168.         
  169.         Display_16_point(0,0,1,WWJJYYWXTP);
  170.         Display_16_point(1,4,1,WWJJYYWXTP);
  171.         Display_16_point(1,6,1,WWJJYYWXTP);

  172.          
  173.          //////////////////
  174.         for(i=0;i<4;i++)
  175.         {
  176.             Display_16_point(0,i<<1,2,(WWJJYYJ+(i<<5))) ;
  177.         }
  178.         for(i=0;i<4;i++)
  179.         {
  180.             Display_16_point(1,i<<1,2,(WWJJYYG+(i<<5))) ;
  181.         }

  182.         for(i=0;i<4;i++)
  183.         {
  184.             Display_16_point(0,i<<1,3,(WWJJYYJ+(i<<5))) ;
  185.         }
  186.         for(i=0;i<4;i++)
  187.         {
  188.             Display_16_point(1,i<<1,3,(WWJJYYHH+(i<<5))) ;
  189.         }
  190. //////////////////
  191.   }
  192. }

  193. }
复制代码



为了方便大家交流,建了两个QQ群:QQ群3号:198387118  【1000人群】QQ群5号: 239316959【2000人群】群内已有成员3000余人!
更多内容关注微信公众号:单片机精讲吴鉴鹰

回复

使用道具 举报

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

关闭

站长推荐上一条 1/5 下一条

  • 论坛活动 E手掌握

    扫码关注
    EEWORLD 官方微信

  • EE福利  唾手可得

    扫码关注
    EE福利 唾手可得

Archiver|手机版|小黑屋|电子工程世界 ( 京ICP证 060456 )

GMT+8, 2020-3-31 14:53 , Processed in 0.574097 second(s), 18 queries , Gzip On, MemCache On.

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