找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1774|回复: 2
收起左侧

俄罗斯方块单片机程序-已验证

[复制链接]
ID:33449 发表于 2018-11-3 10:39 | 显示全部楼层 |阅读模式
俄罗斯方块程序

单片机源程序如下:
  1. #include "reg51.h"
  2. #include "eluosi.h"
  3. #define uchar unsigned char
  4. #define uint unsigned int  
  5. static unsigned long Seed = 1;
  6. #define A 48271L
  7. #define M 2147483647L
  8. #define Q (M / A)
  9. #define R (M % A)
  10. sbit K1=P3^4;
  11. sbit K2=P3^5;
  12. sbit K3=P3^6;
  13. sbit K4=P3^7;
  14. unsigned int idata num[19+2]={ 0xfff,//第1行,最下面
  15. 0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,
  16. 0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行 0xfff//第21行,最上面  
  17. };//定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列
  18. unsigned char code Block[28][2]={ /*
  19. *   口     口口口   口口
  20. *   口     口         口      口
  21. *   口口              口  口口口       */
  22. {0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},
  23. /*
  24. *   口        口口 口口口
  25. *   口 口     口       口
  26. * 口口 口口口 口   
  27. */
  28. {0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},   /*
  29. *   口
  30. *   口口         口口
  31. *     口       口口
  32. */
  33. {0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},
  34. /*
  35. *   口        口口 * 口口          口口 * 口 */
  36. {0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},  
  37. /*
  38. *          口                口
  39. *   口     口口   口口口   口口
  40. * 口口口   口       口       口
  41. */
  42. {0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},
  43. /*口
  44. * 口
  45. * 口       口口口口
  46. * 口
  47. */
  48. {0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},  
  49. /*
  50. * 口口
  51. * 口口
  52. */   
  53. {0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}
  54. };  
  55. #define PASSSCORE 20
  56. struct Jimu
  57. {  
  58. unsigned int dat;   
  59. char x;  
  60. unsigned char y;  
  61. unsigned char type;  
  62. unsigned char change;
  63. }Sign[3];//积木结构体  

  64. unsigned char SysFlag=0;
  65. #define NEWSIGNFLAG 0
  66. #define DEADFLAG 1
  67. #define PAUSEFLAG 2

  68. unsigned char Score=0;
  69. unsigned char Level=1;
  70. unsigned char DelayCnt=5;
  71. /*********************************************************/
  72. #define N 25
  73. /************************************
  74. 伪随机数发生器
  75. *************************************/
  76. double Random(void)
  77. {  
  78. long TmpSeed;  
  79. TmpSeed=A*(Seed%Q)-R*(Seed/Q);
  80. if(TmpSeed>=0)   
  81.      Seed=TmpSeed;
  82. else   
  83.     Seed=TmpSeed+M;  
  84. return (double)Seed/M;
  85. }  

  86. /**************************************
  87. 为伪随机数发生器播种
  88. ***************************************/
  89. void InitRandom(unsigned long InitVal)
  90. {  
  91. Seed=InitVal;
  92. }  
  93. //延时子程序
  94. void Delay(unsigned int t)
  95. {   
  96. unsigned int i,j;  
  97. for(i=0;i<t;i++)   
  98. for(j=0;j<10;j++);   
  99. }
  100. /*********************************
  101. 初始化MPU
  102. **********************************/
  103. void InitCpu(void)
  104. {
  105.           TMOD=0x0;
  106. TH0=0;  
  107. TL0=0;  
  108. TR0=1;  
  109. ET0=1;   
  110. EX1=1;
  111. EA=1;
  112.      TCON|=0x04;
  113. }
  114. /****************************
  115. welcome   游戏选择界面
  116. /**********************/
  117. void welcome()
  118. {
  119. Lcd_WriteStr(0,0,"欢迎来玩");  
  120. Lcd_WriteStr(0,1,"俄罗斯方块 ");
  121. Lcd_WriteStr(0,2,"设置按K1");
  122. Lcd_WriteStr(0,2,"开玩按K2");   
  123. }
  124. /*************
  125. 俄罗斯方块部分
  126. /******************************
  127. 画墙壁,初始化界面
  128. *******************************/
  129. void DrawBoard(void)
  130. {  
  131. unsigned char n;  
  132. for(n=0;n<12;n++)
  133. {   
  134. Lcd_Rectangle(3*n,0,3*n+2,2,1);   
  135. Lcd_Rectangle(3*n,60,3*n+2,62,1);
  136. }  
  137. for(n=0;n<20;n++)
  138. {   
  139. Lcd_Rectangle(0,3*n,2,3*n+2,1);   
  140. Lcd_Rectangle(33,3*n,35,3*n+2,1);   
  141.            }  
  142.        Lcd_WriteStr(4,0,"经典游戏");  
  143.        Lcd_WriteStr(3,2,"Score:");  
  144.        Lcd_WriteStr(3,3,"Level:"); }  

  145. /***********************************
  146. 游戏结束处理
  147. ************************************/
  148. void GameOver(void)
  149. {  
  150. if((SysFlag&(1<<DEADFLAG))!=0)  
  151.    Lcd_WriteStr(3,1,"You Fail");  
  152. else  
  153.   Lcd_WriteStr(3,1,"You Pass");
  154. }
  155. unsigned int code MaskTab[16]={
  156. 0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080, 0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000
  157. };  

  158. /**********************************
  159. 根据积木图标左下坐标X,Y来画出积木图标
  160. ***********************************/
  161. void DrawSign(struct Jimu Temp,unsigned char DrawMode)
  162. {  
  163. unsigned char m,n;  
  164. for(m=0;m<4;m++)   
  165. for(n=0;n<4;n++)   
  166. {   
  167. if((Temp.dat&MaskTab[4*m+n])!=0)
  168.     Lcd_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode);
  169. }   
  170.   }
  171.   
  172. /********************************
  173. 将积木图标值融入num数据中 也即把积木图标固定,无法再下降
  174. *********************************/
  175. FixSign(void)
  176. {  
  177. unsigned char m,n;
  178. for(m=0;m<4;m++)//行循环   
  179. for(n=0;n<4;n++)//列循环   
  180. {   
  181. if((Sign[0].dat&MaskTab[4*m+n])!=0)  
  182.   {     
  183. num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n];  
  184.   }  
  185. }
  186. }
  187.   
  188. /********************************
  189. 判断积木图标中方块是否与障碍方块重合
  190. *********************************/
  191. unsigned char CheckIf(void)
  192. {  
  193. unsigned char m,n;  
  194. for(m=0;m<4;m++)//行循环
  195. for(n=0;n<4;n++)//列循环  
  196. {   
  197. if((Sign[1].dat&MaskTab[4*m+n])!=0)  
  198.   {     
  199. if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])!=0)                      return 0;  
  200.   }   
  201. }  
  202. return 1;
  203.    }  

  204. /********************************
  205. 判断积木图标是否可以继续下降一格
  206. ********************************/
  207. unsigned char CheckIfDown(void)
  208. {  
  209. Sign[1]=Sign[0];//  
  210. Sign[1].y+=3;//假设下降一格   
  211. return CheckIf();  
  212. }  
  213. /********************************
  214. 判断积木图标是否可以向左移动
  215. *********************************/
  216. unsigned char CheckIfLeft(void)
  217. {  
  218. Sign[1]=Sign[0];
  219. Sign[1].x-=3;  
  220. return CheckIf();
  221. }  
  222. /********************************
  223. 判断积木图标是否可以向右移动
  224. *********************************/
  225. unsigned char CheckIfRight(void)
  226. {  
  227. Sign[1]=Sign[0];  
  228. Sign[1].x+=3;  
  229. return CheckIf();
  230. }  
  231. /********************************
  232. 判断是否可以旋转
  233. *********************************/
  234. unsigned char CheckIfRoll(void)
  235. {  
  236. unsigned char i;  
  237. unsigned int Temp;
  238.         Sign[1]=Sign[0];  
  239. if(++Sign[1].change>3)  
  240. Sign[1].change=0;
  241. i=Sign[1].type*4+Sign[1].change;
  242. Temp=(unsigned int)Block[i][0]<<8;
  243. Temp=Temp|Block[i][1];
  244. Sign[1].dat=Temp;

  245. return CheckIf();
  246. }  

  247. /********************************
  248. 寻找满格的行并做消除处理
  249. 最多寻找4个满行并做消除
  250. *********************************/
  251. void DelFull(void)
  252. {
  253. unsigned char m,n;  
  254. unsigned char Temp;  
  255. unsigned char Flag=0;  
  256. Temp=(Sign[0].y-2)/3;  
  257. if(Temp>=20)//防止越过了下边界
  258.     Temp=1;  
  259. else  
  260.     Temp=20-Temp;  
  261. for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算
  262. {   
  263. if(num[n]==0xfff)   
  264. {   
  265. Flag=1;   
  266. for(m=n+1;m<=19;m++)   
  267. {     
  268. num[m-1]=num[m];
  269. }   
  270. num[m]=0x801;
  271. Score++;//每找到一个满行,则分数加1
  272. }
  273. }  
  274. if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面
  275.     {  
  276.                  for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画   
  277.      for(n=1;n<=10;n++)   
  278.     {     
  279. if((num[m]&MaskTab[n])==0)   
  280. {      
  281.          if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)!=0)//为加速而做的读象素操作      
  282.     {      
  283. Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0);   
  284.                }   
  285.            }      
  286. else   
  287.   {     
  288. if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作               
  289. {      
  290. Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1);      }   
  291.   }   
  292. }  
  293. }
  294. }
  295.   
  296. /*******************************
  297. 随机产生一个积木图标放到预产生区域并显示出来
  298. ********************************/
  299. void CreatSign(void)
  300. {  
  301. unsigned char n;  
  302. unsigned int Temp;  
  303. DrawSign(Sign[2],0);//先清除   
  304. n=Random()*28;  
  305. Temp=(unsigned int)Block[n][0]<<8;
  306. Temp=Temp|Block[n][1];  
  307. Sign[2].dat=Temp;
  308. Sign[2].x=45;  
  309. Sign[2].y=4*3+2;
  310. Sign[2].type=n/4;  
  311. Sign[2].change=n%4;
  312. DrawSign(Sign[2],1);//后画出
  313. }  

  314. void PrintScore(void)
  315. {  
  316. unsigned char Str[3];  
  317. Str[0]=(Score/10)|0x30;
  318. Str[1]=(Score%10)|0x30;
  319. Str[2]=0;
  320. Lcd_WriteStr(6,2,Str);
  321. }  

  322. void PrintLevel(void)
  323. {  
  324. unsigned char Str[3];
  325. Str[0]=(Level/10)|0x30;
  326. Str[1]=(Level%10)|0x30;
  327. Str[2]=0;
  328. Lcd_WriteStr(6,3,Str);
  329. }  

  330. /********************************
  331. 游戏的具体过程,也是俄罗斯方块算法的关键部分
  332. *********************************/
  333. void GamePlay(void)
  334. {  
  335. unsigned char m,n;   
  336. unsigned int Temp;  
  337. SysFlag|=1<<NEWSIGNFLAG;//刚开始初始化为需要产生新的积木图标      
  338. InitRandom(TL0);  
  339. Lcd_WriteStr(3,1,"Playing");
  340. PrintScore();  
  341. PrintLevel();  
  342. CreatSign();  
  343. while(1)
  344. {   
  345. if((SysFlag&(1<<NEWSIGNFLAG))==1)//判是否需要产生新的积木图标   
  346. {   
  347. SysFlag&=~(1<<NEWSIGNFLAG);   
  348. Sign[0]=Sign[2];   
  349. CreatSign();   
  350. Sign[0].x=12;
  351. Sign[0].y=14;
  352. for(m=0;m<4;m++)//行循环
  353.    {   
  354. for(n=0;n<4;n++)//列循环   
  355.   {      
  356. if((Sign[0].dat&MaskTab[15-m*4-n])==0)         
  357.       break;   
  358. }   
  359. if(n==4)     
  360.      Sign[0].y-=3;   
  361. }//将积木图标出现置顶  
  362.    
  363. for(m=0;m<4;m++)//行循环
  364.     for(n=0;n<4;n++)//列循环     
  365.      {  
  366.     if((Sign[0].dat&MaskTab[4*m+n])!=0)  
  367.     {      
  368. if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])!=0)               
  369.          SysFlag|=1<<DEADFLAG;     
  370. }   
  371. }
  372.    if((SysFlag&(1<<DEADFLAG))!=0)  
  373.    break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。游戏结束   
  374. DrawSign(Sign[0],1);   
  375. }      
  376. if((CheckIfLeft())&&(K3==0))  //左   
  377.     {   
  378.             DrawSign(Sign[0],0);
  379.         Sign[0].x-=3;      
  380.     DrawSign(Sign[0],1);      
  381. }      
  382.       if((CheckIfRight())&&(K4==0))   //右   
  383.    {
  384.           DrawSign(Sign[0],0);      
  385.               Sign[0].x+=3;      
  386.    DrawSign(Sign[0],1);   
  387.     }
  388.       if((CheckIfDown())&&(K2==0))//下  
  389.        {         
  390.                          DrawSign(Sign[0],0);   
  391.                       Sign[0].y+=3;   
  392.    DrawSign(Sign[0],1);
  393. }      
  394. if((CheckIfRoll())&&(K1==0)) //翻转      
  395. {      
  396.   DrawSign(Sign[0],0);      
  397.   if(++Sign[0].change>3)   
  398.       Sign[0].change=0;  
  399. m=Sign[0].type*4+Sign[0].change;
  400. Temp=(unsigned int)Block[m][0]<<8;      
  401. Temp=Temp|Block[m][1];        
  402. Sign[0].dat=Temp;      
  403. DrawSign(Sign[0],1);
  404. }  
  405.                  if((SysFlag&(1<<PAUSEFLAG))!=0)   
  406.                          continue;  
  407. Delay(500);  
  408. if(++DelayCnt>=2*(11-Level))  
  409. {   
  410. DelayCnt=0;   
  411. if(CheckIfDown())//判断是否能继续下降一格
  412.    {   
  413.                          DrawSign(Sign[0],0);
  414.             Sign[0].y+=3;  
  415.                    DrawSign(Sign[0],1);
  416.    }   
  417. else   
  418. {   
  419.                  FixSign();   
  420. DelFull();   
  421. PrintScore();  
  422.                    if(Score>=PASSSCORE)   
  423.               {      
  424. SysFlag&=~(1<<DEADFLAG);
  425.      break;//跳出玩游戏过程
  426.     }   
  427. SysFlag|=1<<NEWSIGNFLAG;//新的积木图标产生标志置1   
  428. }   
  429. }
  430. }  
  431.                  }  

  432. void Main()
  433. {  
  434.   InitCpu();//初始化CPU
  435. Lcd_Reset(); //初始化LCD屏
  436. Lcd_Clear(0);//清屏      
  437. Lcd_Reset(); //初始化LCD屏  
  438. Lcd_Clear(0);//清屏  
  439. DrawBoard();//画界面  
  440. GamePlay();//玩游戏   
  441. GameOver();//游戏结束  
  442. Lcd_Reset(); //初始化LCD屏  
  443. Lcd_Clear(0);//清屏   
  444.   }
复制代码

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

使用道具 举报

ID:1 发表于 2018-11-3 13:25 | 显示全部楼层
补全原理图或者详细说明一下电路连接即可获得100+黑币 什么屏?
回复

使用道具 举报

ID:418731 发表于 2018-11-4 20:23 | 显示全部楼层
阿波罗可以用这个程序吗???
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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