找回密码
 立即注册

QQ登录

只需一步,快速开始

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

基于stm32的12864俄罗斯方块程序

[复制链接]
跳转到指定楼层
楼主
ID:281024 发表于 2018-11-29 21:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
基础功能已经实现

单片机源程序如下:
  1. #include "Game.h"
  2. #include "LCD12864.h"
  3. #include "delay.h"

  4. u8 Key_value=0;   //按键值
  5. u32 random_value=1;   //随机数产生填充值

  6. u8 Score=0; //分数寄存变量  每消除一格 便分数加1
  7. u8 Level=1; //等级寄存器

  8. u8 SysFlag=0; //系统标志;
  9. u8 DelayCnt=5; //时间变量
  10. #define NEWSIGNFLAG 0  //产生新得积木标志
  11. #define DEADFLAG 1 //全局标志
  12. #define PAUSEFLAG 2 //暂停标志
  13. #define PASSSCORE 20 //完成当前局 就是20行  得分为20  等级加1

  14. //按键定义
  15. #define RESEVER 1  //复位
  16. #define CHANGE 2   //换方向
  17. #define DOWN 3    //向下
  18. #define LEFT 4    //向左
  19. #define RIGHT 5   //向右
  20. #define PAUSE 6    //暂停 开始


  21. //定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列
  22. u16  num[19+2]={
  23. 0xfff,//第1行,最下面
  24. 0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,
  25. 0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行
  26. 0xfff//第21行,最上面
  27. };



  28. //二维数组 用来存放积木块;
  29. u8 Block[28][2]={
  30. /*
  31. *   口     口口口   口口
  32. *   口     口         口      口
  33. *   口口              口  口口口      
  34. */
  35. {0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},
  36. /*
  37. *   口        口口 口口口
  38. *   口 口     口       口
  39. * 口口 口口口 口   
  40. */
  41. {0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},  
  42. /*
  43. *   口
  44. *   口口         口口
  45. *     口       口口
  46. */
  47. {0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},
  48. /*
  49. *   口        口口
  50. * 口口          口口
  51. * 口
  52. */
  53. {0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},  
  54. /*
  55. *          口                口
  56. *   口     口口   口口口   口口
  57. * 口口口   口       口       口
  58. */
  59. {0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},
  60. /*口
  61. * 口
  62. * 口       口口口口
  63. * 口
  64. */
  65. {0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},  
  66. /*
  67. * 口口
  68. * 口口
  69. */  
  70. {0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}
  71. };

  72. //积木结构体
  73. struct Jimu
  74. {
  75.         u16 dat;
  76.         char x;
  77.         u8 y;
  78.         u8 type;
  79.         u8 change;
  80. }Sign[3];




  81. //随机数生成  这里用来随机生成积木块;
  82. static u32 Seed = 1;
  83. #define A 48271L
  84. #define M 2147483647L
  85. #define Q (M / A)
  86. #define R (M % A)
  87. /************************************
  88. 伪随机数发生器
  89. *************************************/
  90. double Random(void)
  91. {
  92.         long TmpSeed;
  93.         TmpSeed=A*(Seed%Q)-R*(Seed/Q);
  94.         if(TmpSeed>=0)
  95.                 Seed=TmpSeed;
  96.         else
  97.                 Seed=TmpSeed+M;
  98.         return (double)Seed/M;
  99. }

  100. /**************************************
  101. 为伪随机数发生器播种
  102. ***************************************/
  103. void InitRandom(u32 InitVal)
  104. {
  105.         Seed=InitVal;
  106. }





  107. void DrawBoard(void)                   //画墙壁,就是指在屏幕上画一个框框和初始化界面显示文字
  108. {
  109.         unsigned char n;
  110.         for(n=0;n<12;n++)
  111.         {
  112.                 LCD12864_Rectangle(3*n,0,3*n+2,2,1);
  113.                 LCD12864_Rectangle(3*n,60,3*n+2,62,1);
  114.         }
  115.         for(n=0;n<20;n++)
  116.         {
  117.                 LCD12864_Rectangle(0,3*n,2,3*n+2,1);
  118.                 LCD12864_Rectangle(33,3*n,35,3*n+2,1);               
  119.         }
  120.         LCD12864_String(3,0,"   ");
  121.         LCD12864_String(3,1,"设计:吕钰");
  122.         LCD12864_String(3,2,"得分:0");
  123.         LCD12864_String(3,3,"等级:0");       
  124. }



  125. //根据积木图标左下坐标X,Y来画出积木图标
  126. u16 MaskTab[16]={
  127. 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
  128. 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
  129. };
  130. void DrawSign(struct Jimu Temp,unsigned char DrawMode)
  131. {
  132.         unsigned char m,n;
  133.         for(m=0;m<4;m++)
  134.                 for(n=0;n<4;n++)
  135.                 {
  136.                         if((Temp.dat&MaskTab[4*m+n])!=0)
  137.                         LCD12864_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode);
  138.                 }
  139. }

  140. //随机产生一个积木图标放到预产生区域并显示出来
  141. void CreatSign(void)                 
  142. {
  143.         u8 n;
  144.         u16 Temp;

  145.         DrawSign(Sign[2],0);//先清除

  146.         n=Random()*28;
  147.         Temp=(u16)Block[n][0]<<8;
  148.         Temp=Temp|Block[n][1];
  149.         Sign[2].dat=Temp;
  150.         Sign[2].x=45;
  151.         Sign[2].y=4*3+2;
  152.         Sign[2].type=n/4;
  153.         Sign[2].change=n%4;
  154.         DrawSign(Sign[2],1);//后画出
  155. }

  156. void FixSign(void)         //将积木图标值融入num数据中        也即把积木图标固定,无法再下降
  157. {
  158.         unsigned char m,n;
  159.         for(m=0;m<4;m++)//行循环
  160.                 for(n=0;n<4;n++)//列循环
  161.                 {
  162.                         if((Sign[0].dat&MaskTab[4*m+n])!=0)
  163.                         {
  164.                                 num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n];
  165.                         }
  166.                 }
  167. }

  168. u8 CheckIf(void)                  //判断积木图标中方块是否与障碍方块重合
  169. {
  170.         unsigned char m,n;
  171.         for(m=0;m<4;m++)//行循环
  172.                 for(n=0;n<4;n++)//列循环
  173.                 {
  174.                         if((Sign[1].dat&MaskTab[4*m+n])!=0)
  175.                         {
  176.                                 if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])!=0)
  177.                                         return 0;
  178.                         }
  179.                 }
  180.         return 1;
  181. }

  182. u8 CheckIfDown(void)                        //判断积木图标是否可以继续下降一格
  183. {
  184.         Sign[1]=Sign[0];//
  185.         Sign[1].y+=3;//假设下降一格       
  186.         return CheckIf();
  187.        
  188. }

  189. u8 CheckIfLeft(void)                        //判断积木图标是否可以向左移动
  190. {
  191.         Sign[1]=Sign[0];
  192.         Sign[1].x-=3;//假设左移一格       
  193.         return CheckIf(); //返回检测重合函数
  194. }

  195. u8 CheckIfRight(void)         //判断积木图标是否可以向右移动
  196. {
  197.         Sign[1]=Sign[0];
  198.         Sign[1].x+=3;//假设右移一格       
  199.         return CheckIf();
  200. }
  201. u8 CheckIfRoll(void)                //判断是否可以旋转
  202. {
  203.         unsigned char i;
  204.         unsigned int Temp;
  205.         Sign[1]=Sign[0];
  206.         if(++Sign[1].change>3)
  207.                 Sign[1].change=0;
  208.            i=Sign[1].type*4+Sign[1].change;
  209.         Temp=(unsigned int)Block[i][0]<<8;
  210.         Temp=Temp|Block[i][1];
  211.         Sign[1].dat=Temp;
  212.        
  213.         return CheckIf();
  214. }

  215. void DelFull(void)                                //寻找满格的行并做消除处理,最多寻找4个满行并做消除
  216. {
  217.         u8 m,n;
  218.         u8 Temp;
  219.         u8 Flag=0;
  220.         Temp=(Sign[0].y-2)/3;
  221.         if(Temp>=20)//防止越过了下边界
  222.                 Temp=1;
  223.         else
  224.                 Temp=20-Temp;
  225.         for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算
  226.         {
  227.                 if(num[n]==0xfff)
  228.                 {
  229.                         Flag=1;
  230.                         for(m=n+1;m<=19;m++)
  231.                         {
  232.                                 num[m-1]=num[m];
  233.                         }
  234.                         num[m]=0x801;
  235.                         Score++;//每找到一个满行,则分数加1
  236.                 }
  237.         }
  238.         if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面
  239.         {
  240.                 for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画
  241.                         for(n=1;n<=10;n++)
  242.                         {
  243.                                 if((num[m]&MaskTab[n])==0)
  244.                                 {       
  245.                                         if(LCD12864_Readpoint(30-(n-1)*3,57-(m-1)*3)!=0)//为加速而做的读象素操作
  246.                                         {
  247.                                                 LCD12864_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0);
  248.                                         }
  249.                                 }
  250.                                    else
  251.                                 {
  252.                                         if(LCD12864_Readpoint(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作
  253.                                         {
  254.                                                 LCD12864_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1);
  255.                                         }
  256.                                 }
  257.                         }
  258.         }
  259. }

  260. void PrintScore(void)                        //分数显示输出
  261. {
  262.         unsigned char Str[3]; //定义了一个局部数组
  263.         Str[0]=(Score/10)|0x30; //分数得十位
  264.         Str[1]=(Score%10)|0x30; //分数得个位
  265.         Str[2]=0;
  266.         LCD12864_String(6,2,Str); //在指定位置输出分数
  267. }

  268. void PrintLevel(void)                        //等级显示输出
  269. {
  270.         unsigned char Str[3]; //定义了一个局部数组
  271.         Str[0]=(Level/10)|0x30;
  272.         Str[1]=(Level%10)|0x30;
  273.         Str[2]=0;
  274.         LCD12864_String(6,3,Str);
  275. }

  276. void GamePlay(void)                                //玩游戏流程
  277. {
  278.         unsigned char m,n;
  279.         unsigned int Temp;
  280.         SysFlag|=1<<NEWSIGNFLAG;//刚开始初始化为需要产生新的积木图标
  281.         InitRandom(random_value);                //伪随机数发生器播种
  282.         LCD12864_String(3,1,"           ");
  283.         LCD12864_String(3,1,"开始");
  284.         PrintScore();
  285.         PrintLevel();
  286.         CreatSign();                        //随机显示一个方块到预览区
  287.         while(1)
  288.         {       
  289.                 if((SysFlag&(1<<NEWSIGNFLAG))==1)//判是否需要产生新的积木图标
  290.                 {
  291.                         SysFlag&=~(1<<NEWSIGNFLAG);
  292.                         Sign[0]=Sign[2];
  293.                         CreatSign();
  294.                         Sign[0].x=12;
  295.                         Sign[0].y=14;

  296.                         for(m=0;m<4;m++)//行循环
  297.                         {
  298.                                 for(n=0;n<4;n++)//列循环
  299.                                 {
  300.                                         if((Sign[0].dat&MaskTab[15-m*4-n])==0)
  301.                                                 break;
  302.                                 }
  303.                                 if(n==4)
  304.                                         Sign[0].y-=3;
  305.                         }//将积木图标出现置顶
  306.                        
  307.                         for(m=0;m<4;m++)//行循环
  308.                                 for(n=0;n<4;n++)//列循环
  309.                                 {
  310.                                         if((Sign[0].dat&MaskTab[4*m+n])!=0)
  311.                                         {
  312.                                                 if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])!=0)
  313.                                                         SysFlag|=1<<DEADFLAG;
  314.                                         }
  315.                                 }
  316.                         if((SysFlag&(1<<DEADFLAG))!=0)
  317.                                 break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。游戏结束
  318.                         DrawSign(Sign[0],1);       
  319.                 }
  320.                 switch(Key_value)
  321.                 {
  322.                         case LEFT:
  323.                                         Key_value=0;
  324.                                         if((SysFlag&(1<<PAUSEFLAG))==0)
  325.                                         {
  326.                                                 if(CheckIfLeft())
  327.                                                 {
  328.                                                         DrawSign(Sign[0],0);
  329.                                                         Sign[0].x-=3;
  330.                                                         DrawSign(Sign[0],1);
  331.                                                 }
  332.                                         }
  333.                                         else
  334.                                         {
  335.                                                 if(++Level>=4)
  336.                                                         Level=1;
  337.                                                 PrintLevel();
  338.                                         }
  339.                                         break;
  340.                         case RIGHT:
  341.                                         Key_value=0;
  342.                                         if((SysFlag&(1<<PAUSEFLAG))==0)
  343.                                         {
  344.                                                 if(CheckIfRight())
  345.                                                 {
  346.                                                         DrawSign(Sign[0],0);
  347.                                                         Sign[0].x+=3;
  348.                                                         DrawSign(Sign[0],1);       
  349.                                                 }
  350.                                         }
  351.                                         else
  352.                                         {
  353.                                                 if(++Level>=4)
  354.                                                         Level=1;
  355.                                                 PrintLevel();
  356.                                         }
  357.                                         break;
  358.                         case DOWN:
  359.                                         Key_value=0;
  360.                                         if((SysFlag&(1<<PAUSEFLAG))==0)
  361.                                         {
  362.                                                 if(CheckIfDown())//判断是否能继续下降一格
  363.                                                 {
  364.                                                         DrawSign(Sign[0],0);
  365.                                                         Sign[0].y+=3;
  366.                                                         DrawSign(Sign[0],1);       
  367.                                                 }
  368.                                         }
  369.                                         break;
  370.                         case CHANGE:
  371.                                         Key_value=0;
  372.                                         if((SysFlag&(1<<PAUSEFLAG))==0)
  373.                                         {
  374.                                                 if(CheckIfRoll())
  375.                                                 {
  376.                                                         DrawSign(Sign[0],0);
  377.                                                         if(++Sign[0].change>3)
  378.                                                                 Sign[0].change=0;
  379.                                                            m=Sign[0].type*4+Sign[0].change;
  380.                                                         Temp=(unsigned int)Block[m][0]<<8;
  381.                                                         Temp=Temp|Block[m][1];
  382.                                                         Sign[0].dat=Temp;
  383.                                                         DrawSign(Sign[0],1);
  384.                                                 }
  385.                                         }
  386.                                         break;
  387.                            case PAUSE:
  388.                                         Key_value=0;
  389.                                         SysFlag^=1<<PAUSEFLAG;
  390.                                         if((SysFlag&(1<<PAUSEFLAG))==0)
  391.                                         {
  392.                                                 LCD12864_String(3,1,"          "); //在显示“开始”之前将改区域得显示清除
  393.                                                 LCD12864_String(3,1,"开始");
  394.                                         }
  395.                                         else
  396.                                         {
  397.                                                 LCD12864_String(3,1,"          ");//在显示“暂停”之前将改区域得显示清除
  398.                                                 LCD12864_String(3,1,"暂停");       
  399.                                         }
  400.                                         break;
  401.                     default:
  402.                                         break;
  403.                 }
  404.                 if((SysFlag&(1<<PAUSEFLAG))!=0)
  405.                         continue;
  406.                 delay_ms(50);
  407.                 if(++DelayCnt>=2*(11-Level))
  408.                 {
  409.                         DelayCnt=0;
  410.                         if(CheckIfDown())//判断是否能继续下降一格
  411.                         {
  412.                                 DrawSign(Sign[0],0);
  413.                                 Sign[0].y+=3;
  414.                                 DrawSign(Sign[0],1);
  415.                         }
  416.                         else
  417.                         {
  418.                                 FixSign();
  419.                                 DelFull();
  420.                                 PrintScore();
  421.                                 if(Score>=PASSSCORE)
  422.                                 {
  423.                                         SysFlag&=~(1<<DEADFLAG);
  424.                                         break;//跳出玩游戏过程
  425.                                 }
  426.                                 SysFlag|=1<<NEWSIGNFLAG;//新的积木图标产生标志置1
  427.                         }
  428.                 }
  429.         }
  430. }

  431. void GameOver(void)                                        //游戏结束处理
  432. {
  433.         if((SysFlag&(1<<DEADFLAG))!=0)
  434.           {       
  435.                         LCD12864_Init(); //初始化LCD屏
  436.                   LCD12864_String(1,2,"失败");
  437.        
  438.           }
  439.         else
  440.                 {       
  441.                         LCD12864_Init(); //初始化LCD屏
  442.                         LCD12864_String(1,2,"恭喜");
  443.        
  444.                  }
  445. }
复制代码

所有资料51hei提供下载:
俄罗斯方块.rar (310.57 KB, 下载次数: 68)


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

使用道具 举报

沙发
ID:1 发表于 2018-12-1 02:04 | 只看该作者
补全原理图或者详细说明一下电路连接即可获得100+黑币
回复

使用道具 举报

板凳
ID:339366 发表于 2018-12-7 13:33 | 只看该作者
这个用kill怎么看 没学过stm32 不怎么会用
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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