找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 4294|回复: 6
收起左侧

单片机俄罗斯方块源程序和proteus仿真工程文件 带视频

[复制链接]
ID:137190 发表于 2016-9-25 16:07 | 显示全部楼层 |阅读模式
视频教程:


这个51单片机俄罗斯方块的资料很全,原理图 仿真 教程 视频都有.
0.png 0.png 0.png 0.png

单片机做的俄罗斯方块所有资料下载:
俄罗斯方块.rar (5.38 MB, 下载次数: 53)


  1. /*****************************************************************************************
  2. 名称:《基于8052单片机和8X16点阵屏俄罗斯方块游戏板》
  3. 时间:05月23日17时
  4. 单位:武汉理工大学信息学院电子1003班
  5. 作者:颜
  6. *****************************************************************************************/
  7. #include<reg52.h>
  8. #include<stdlib.h>
  9. #include<math.h>
  10. #define uchar unsigned char
  11. sbit slock=P2^7;                                        //译码器输出使能端
  12. sbit upkey=P2^3;                                        //“旋转图形/向上”按键
  13. sbit leftkey=P2^1;                                        //“左移/向左”按键
  14. sbit rightkey=P2^2;                                        //“右移/向右”按键
  15. sbit downkey=P2^0;                                        //“快速下移/向下”按键
  16. sbit duan=P2^5;                                                //数码管段选信号所用锁存器的锁存允许端
  17. sbit wei=P2^6;                                                //数码管位选信号所用锁存器的锁存允许端
  18. sbit startsuspendkey=P2^4;                        //“开始/暂停/继续”多功能切换按键
  19. /***********************************图形编码机制介绍**************************************
  20. 1.由于俄罗斯方块图形的宽度和高度最多只有四位,所以要以4X4为基本单元。
  21. 2.硬件采用16行扫描、8位送显示信号
  22. 3.各个图形的宽度不一致,所以要人为给图形设定居中位置。
  23.   若图形宽度为偶数可直接将其居中,若为奇数则靠左居中。
  24. 4.由于图形需要旋转,所以由基本的图形会衍生出另外3种图形。
  25. 5.因此每个图形应该给定4个8位的二进制码,并放入一个二维数组里。
  26. 6.经典俄罗斯方块游戏里有19种不同形状的方块,包括旋转得到的。
  27. 7.数组的第一个下标为该图形的编号
  28. *****************************************************************************************/
  29. uchar code allshape[19][4]={0x00,0x00,0x18,0x18,0x10,0x10,0x10,0x10,0x00,0x00,0x00,0x3c,
  30.                                                         0x00,0x08,0x18,0x10,0x00,0x00,0x30,0x18,0x00,0x10,0x18,0x08,
  31.                                                         0x00,0x00,0x18,0x30,0x00,0x08,0x08,0x18,0x00,0x00,0x38,0x08,
  32.                                                         0x00,0x18,0x10,0x10,0x00,0x00,0x20,0x38,0x00,0x10,0x10,0x18,
  33.                                                         0x00,0x00,0x08,0x38,0x00,0x18,0x08,0x08,0x00,0x00,0x38,0x20,
  34.                                                         0x00,0x00,0x10,0x38,0x00,0x08,0x18,0x08,0x00,0x00,0x38,0x10,
  35.                                                         0x00,0x10,0x18,0x10};
  36. /****************************************************************************************/
  37. uchar code number[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};        //数码管数形显示编码
  38. uchar code weima[4]={0x01,0x02,0x04,0x08};                                                                        //位选信号编码,方便写循环使用
  39. char shapewidth[19]={2,1,4,2,3,2,3,2,3,2,3,2,3,2,3,3,2,3,2};                                //各个图形的宽度属性,用于判断左移和右移的步格数上限
  40. char shaperotate[19]={0,2,1,4,3,6,5,8,9,10,7,12,13,14,11,16,17,18,15};                //旋转图形时,用于改变图形的编号以实现图形的切换
  41. uchar staticdata[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xff};                        //用于存储方块降落后固定显示的图形信息
  42. uchar rate[5]={0,1,3,6,10};                                                                                                        //规定一次性消掉的行数的分数奖励机制


  43. /****************************************全局变量声明************************************/
  44. char y;                                        //方块位置属性:底部下落的高度,y=0时:刚刚出现,y=15时:下落到屏幕最底部
  45. char shapenum;                        //方块形状属性:从0到18
  46. int left;                                 //方块位置属性:方块偏离居中位置的格数,不同的方块left值的上限不同
  47. int mark;                                //玩家分数变量
  48. int speed;                                //方块下落速度变量
  49. int initialspeed;                //方块下落的初始速度
  50. int systemspeed;                //系统下落速度,此值会随着玩家分数的增加而减小,相应的下落速度会增大
  51. int fastspeed;                        //当用户按下down键时,方块下落速度为此值
  52. int k;                                        //一个全局循环变量,“帧数”变量
  53. int startcontrol=1;                //开始画面状态指示变量,为1时说明程序进入开机欢迎界面
  54. int suspendcontrol=0;        //游戏暂停与游戏继续画面状态指示变量,为1说明处在暂停界面,为0说明处在继续画面
  55. int randnum;                        //随机数变量,用于产生随机方块
  56. /****************************************************************************************/


  57. /****************************************函数声明****************************************/
  58. void delayms(int);                                //粗略延时函数
  59. uchar move(uchar,int);                        //对二进制码实行移位,可为负值
  60. void shapedisplay();                        //对点阵扫描一场,对数码管扫描一场,用于显示图形和数字
  61. void keyscan();                                        //对所有键盘扫描一次,并执行相应运算和操作
  62. uchar check(char,int);                        //用于检查方块将要下落的位置或是将要旋转的位置是否有障碍
  63. uchar shapedisappear();                        //用于消行,返回一次性消掉的行数
  64. numberdisplay(int amark);                //用于四位数字显示
  65. void startimage();                                //游戏等待开始画面函数
  66. void overimage();                                //游戏结束后的画面
  67. void dataset();                                        //对数据初始化,为游戏重新开始做准备
  68. /****************************************************************************************/


  69. /*****************************************主函数*****************************************/
  70. void main()
  71. {
  72.         char j;
  73.         startimage();                                        //进入开机,函数内有键盘扫描,只有按下“开始”键会退出函数,否则不退出
  74.         dataset();                                                //对数据进行初始化
  75.         while(1){                                                //进入大循环
  76.                 k=speed;                                        //确定显示的帧数
  77.                 while(k--){
  78.                         keyscan();                                //扫描键盘,放入高速循环语句中提高键盘的响应速度,并检测此时用户是否有相应请求
  79.                         shapedisplay();                        //显示图形和数字
  80.                 }
  81.                 y++;                                                //图形下落一格
  82.                 if(check(shapenum,left)){        //在没有显示之前判断将要下落的位置是否有障碍物,如果有障碍就进入到if语句中
  83.                         if(y==1){                                //如果y=1;说明方块刚出现就遇到障碍物了,这时游戏需结束
  84.                                 overimage();                //进入游戏结束画面,此函数内没有键盘扫描,运行一段时间会自动退出
  85.                                 startimage();                //又进入开机画面
  86.                                 dataset();                        //对数据进行初始化,将前一用户数据清零        
  87.                         }
  88.                         else{                                                                                                        //遇到障碍物,但还不至于图形不能出现
  89.                                 y--;                                                                                                //y回到原值
  90.                                 for(j=0;j<4;j++){                                                                        //将下落形状的值赋给固定图形,形成停留显示的效果
  91.                                         staticdata[y+j]+=move(allshape[shapenum][j],left);
  92.                                 }
  93.                                 mark+=rate[shapedisappear()];                                                //消掉已拼满的函数,并记录所得分数
  94.                                 y=0;                                                                                                //为下一个方块赋属性值:从第一行出现
  95.                                 left=0;                                                                                                //为下一个方块赋属性值:居中显示
  96.                                 randnum=rand()%19;shapenum=randnum;                                        //为下一个方块赋属性值:给定形状
  97.                                 systemspeed=initialspeed-10*(mark/40);                                //计算相应分数下的系统速度值,分数越高,速度越快
  98.                                 speed=systemspeed;                                                                        //将此值赋给速度控制量
  99.                         }
  100.                 }
  101.         }
  102. }
  103. /****************************************************************************************/


  104. /***************************************自定义函数***************************************/
  105. void delayms(int xms)                          //粗略的延时函数
  106. {        
  107.         int i,j;
  108.         for(i=xms;i>0;i--)
  109.                 for(j=110;j>0;j--);
  110. }
  111. /****************************************************************************************/
  112. uchar move(uchar aa,int anum)        //移位函数        
  113. {                                                                 
  114.         if(anum>=0)
  115.                 aa<<=anum;
  116.         else
  117.                 aa>>=(-anum);
  118.         return aa;
  119. }
  120. /****************************************************************************************/
  121. void shapedisplay()                                //显示函数
  122. {
  123.         uchar j;
  124.         for(j=y<3?3-y:0;j<4;j++){        //显示动态方块               
  125.                 slock=1;P1=j+y-3;P3=move(allshape[shapenum][j],left);
  126.                 slock=0;delayms(1);P3=0x00;
  127.         }
  128.         for(j=0;j<16;j++){                        //显示静态方块
  129.                 slock=1;P1=j;P3=staticdata[j+3];
  130.                 slock=0;delayms(1);P3=0x00;
  131.         }
  132.         numberdisplay(mark);                //分数显示        
  133. }
  134. /****************************************************************************************/
  135. numberdisplay(int amark)                //大数拆分并显示,带去无效零功能
  136. {
  137.         char i;
  138.         uchar num[4];
  139.         num[0]=amark/1000%10;num[1]=amark/100%10;num[2]=amark/10%10;num[3]=amark%10;
  140.         if(amark<10){                                   //显示一位数
  141.                 for(i=3;i<4;i++){
  142.                         P0=0xff;
  143.                         duan=1;
  144.                         P0=number[num[i]];
  145.                         duan=0;
  146.                         P0=0x00;
  147.                         wei=1;
  148.                         P0=weima[i];
  149.                         wei=0;
  150.                         delayms(1);
  151.                         wei=1;
  152.                         P0=0x00;
  153.                         wei=0;
  154.                 }
  155.         }
  156.         else if(amark<100){                          //显示两位数
  157.                 for(i=2;i<4;i++){
  158.                         P0=0xff;
  159.                         duan=1;
  160.                         P0=number[num[i]];
  161.                         duan=0;
  162.                         P0=0x00;
  163.                         wei=1;
  164.                         P0=weima[i];
  165.                         wei=0;
  166.                         delayms(1);
  167.                         wei=1;
  168.                         P0=0x00;
  169.                         wei=0;
  170.                 }
  171.         }
  172.         else if(amark<1000){                  //显示三位数
  173.                 for(i=1;i<4;i++){
  174.                         P0=0xff;
  175.                         duan=1;
  176.                         P0=number[num[i]];
  177.                         duan=0;
  178.                         P0=0x00;
  179.                         wei=1;
  180.                         P0=weima[i];
  181.                         wei=0;
  182.                         delayms(1);
  183.                         wei=1;
  184.                         P0=0x00;
  185.                         wei=0;
  186.                 }
  187.         }
  188.         else{                                                //显示四位数
  189.                 for(i=0;i<4;i++){
  190.                         P0=0xff;
  191.                         duan=1;
  192.                         P0=number[num[i]];
  193.                         duan=0;
  194.                         P0=0x00;
  195.                         wei=1;
  196.                         P0=weima[i];
  197.                         wei=0;
  198.                         delayms(1);
  199.                         wei=1;
  200.                         P0=0x00;
  201.                         wei=0;
  202.                 }  
  203.         }         
  204.         return 0;
  205. }
  206. /****************************************************************************************/
  207. void keyscan()                                         //键盘扫锚并执行用户输入的指令
  208. {
  209.         if(leftkey==0&&(left<(shapewidth[shapenum]<3?3:2))&&!check(shapenum,left+1)&&startcontrol==0&&suspendcontrol==0){
  210.                 delayms(10);                        //按键无效条件:1.左移超边缘;2.左移遇障碍;3.处在欢迎界面;4.处在暂停界面
  211.                 if(leftkey==0){        
  212.                         left++;                                //按键命令:方块左移一位
  213.                         speed=systemspeed;
  214.                         while(!leftkey){                                                        
  215.                                 shapedisplay();                                
  216.                         }
  217.                 }
  218.         }
  219.         if(rightkey==0&&(left>(shapewidth[shapenum]<3?shapewidth[shapenum]-5:shapewidth[shapenum]-6))&&!check(shapenum,left-1)&&startcontrol==0&&suspendcontrol==0){
  220.                 delayms(10);                           //按键无效条件:1.右移超边缘;2.右移遇障碍;3.处在欢迎界面;4.处在暂停界面
  221.                 if(rightkey==0){        
  222.                         left--;                                //按键命令:方块右移一位
  223.                         speed=systemspeed;
  224.                         while(!rightkey){                        
  225.                                 shapedisplay();        
  226.                         }
  227.                 }
  228.         }
  229.         if(upkey==0&&!check(shaperotate[shapenum],left)&&(left<(shapewidth[shaperotate[shapenum]]<3?4:3))&&(left>(shapewidth[shaperotate[shapenum]]<3?shapewidth[shaperotate[shapenum]]-6:shapewidth[shapenum]-7))&&startcontrol==0&&suspendcontrol==0){
  230.                 delayms(10);                        //按键无效条件:1.翻转超左右边缘;2.翻转遇障碍;3.处在欢迎界面;4.进入暂停界面
  231.                 if(upkey==0){        
  232.                         shapenum=shaperotate[shapenum];        //按键命令:将翻转后的图形编号赋给要显示的图形编号
  233.                         speed=systemspeed;
  234.                         while(!upkey){                        
  235.                                 shapedisplay();
  236.                         }
  237.                 }
  238.         }
  239.         if(downkey==0&&speed!=fastspeed&&startcontrol==0&&suspendcontrol==0){
  240.                 delayms(10);                        //按键无效条件:1.已经进入快速下降状态;2.处在欢迎界面;3.进入暂停界面
  241.                 if(downkey==0){        
  242.                         speed=fastspeed;        //按键命令:将方块下落速度加快
  243.                         k=speed;
  244.                         while(!downkey){
  245.                                 shapedisplay();
  246.                         }
  247.                 }
  248.         }
  249.         if(startsuspendkey==0&&startcontrol==1&&suspendcontrol==0){
  250.                 delayms(10);                           //按键有效条件:1.处在开始欢迎界面;2.处在暂停界面
  251.                 if(startsuspendkey==0){
  252.                         startcontrol=0;                           
  253.                         suspendcontrol=0;        //按键命令:使进入继续游戏状态
  254.                         while(!startsuspendkey){
  255.                         }
  256.                 }        
  257.         }
  258.          if(startsuspendkey==0&&startcontrol==0&&suspendcontrol==0){
  259.                 delayms(10);                         //按键无效条件:1.处在开始欢迎界面;2.处在暂停状态
  260.                 if(startsuspendkey==0){
  261.                         suspendcontrol=1;        
  262.                         startcontrol=0;                //按键命令:状态切换,使进入暂停状态
  263.                         while(!startsuspendkey){
  264.                                 shapedisplay();        
  265.                         }
  266.                         while(suspendcontrol){
  267.                                 shapedisplay();
  268.                                 keyscan();                //等待结束暂停状态的命令
  269.                         }                                                        
  270.                 }
  271.         }
  272.          if(startsuspendkey==0&&startcontrol==0&&suspendcontrol==1){
  273.                 delayms(10);                        //按键有效条件:处在暂停界面
  274.                 if(startsuspendkey==0){        
  275.                         suspendcontrol=0;
  276.                         startcontrol=0;                //按键命令:状态切换,使进入继续游戏状态
  277.                         while(!startsuspendkey){
  278.                                 shapedisplay();
  279.                         }                                
  280.                 }
  281.         }
  282. }
  283. /****************************************************************************************/
  284. uchar check(char ashapenum,int aleft)        //判断方块是否会遇到障碍物
  285. {
  286.         char i=3,j=0;
  287.         while(!j&&i>=0){
  288.                 if((move(allshape[ashapenum][i],aleft)+staticdata[y+i])!=(move(allshape[ashapenum][i],aleft)|staticdata[y+i])){
  289.                         j++;
  290.                 }
  291.                 i--;
  292.         }
  293.         return j;                                                           //返回0,说明没有障碍
  294. }
  295. /****************************************************************************************/
  296. uchar shapedisappear()                                           //方块落定后消掉拼满的行,并使没有拼满的行整体下移填补空缺行
  297. {
  298.         char i,j,r=4;
  299.         for(i=0;i<r;i++){
  300.                 if(staticdata[y+3-i]==0xff){
  301.                         for(j=y+3-i;j>0;j--){
  302.                                 staticdata[j]=staticdata[j-1];
  303.                         }
  304.                         i--,r--;
  305.                 }
  306.         }
  307.         return 4-r;                                                        //函数返回一次性消掉的行的数目
  308. }
  309. /****************************************************************************************/
  310. void startimage()                                                  //开机欢迎画面,在没有按键作用的时候会不断执行
  311. {
  312.         uchar i,j;
  313.         startcontrol=1;
  314.         while(startcontrol){
  315.                 for(i=10;i>0;i--){
  316.                         for(j=0;j<16;j+=2){
  317.                                 slock=1;P1=j;P3=0xaa;
  318.                                 slock=0;delayms(1);P3=0x00;
  319.                         }
  320.                         for(j=1;j<16;j+=2){
  321.                                 slock=1;P1=j;P3=0x55;
  322.                                 slock=0;delayms(1);P3=0x00;
  323.                         }
  324.                         keyscan();                                           //随时响应用户输入
  325.                 }               
  326.                 for(i=10;i>0;i--){
  327.                         for(j=1;j<16;j+=2){
  328.                                 slock=1;P1=j;P3=0xaa;
  329.                                 slock=0;delayms(1);P3=0x00;
  330.                         }
  331.                         for(j=0;j<16;j+=2){
  332.                                 slock=1;P1=j;P3=0x55;
  333.                                 slock=0;delayms(1);P3=0x00;
  334.                         }
  335.                         keyscan();                                        //随时响应用户输入        
  336.                 }
  337.         }
  338. }
  339. /****************************************************************************************/
  340. void overimage()                                                  //游戏结束画面,分数会强制闪烁8次,并自动结束
  341. {
  342.         int i,j;
  343.         for(j=0;j<8;j++){
  344.                 for(i=0;i<200;i++){
  345.                         numberdisplay(mark);        
  346.                 }
  347.                 delayms(500);
  348.         }
  349. }        
  350. /****************************************************************************************/
  351. void dataset()                                                           //数据全部清零,重新开始游戏
  352. {
  353.         char j;
  354.         y=0;
  355.         left=0;
  356.         shapenum=0;
  357.         initialspeed=100;
  358.         speed=initialspeed;
  359.         systemspeed=initialspeed;
  360.         fastspeed=5;
  361.         randnum=rand()%19;
  362.         shapenum=randnum;
  363.         mark=0;
  364.         for(j=0;j<19;j++){                                          //清除点阵上的显示数据
  365.                 staticdata[j]=0;
  366.         }
  367. }
  368. /****************************************************************************************/
复制代码

回复

使用道具 举报

ID:304879 发表于 2018-4-10 18:09 | 显示全部楼层
为什么我画好图,装上编译文件 .hex后,点开始仿真,却不行。怎么办
无标题2.png
回复

使用道具 举报

ID:304879 发表于 2018-4-12 10:00 | 显示全部楼层
好奇怪。仿真不了。不亮
回复

使用道具 举报

ID:168911 发表于 2018-4-14 09:49 | 显示全部楼层
是点阵不亮还是数码管不亮?
回复

使用道具 举报

ID:304879 发表于 2018-4-17 19:50 | 显示全部楼层
老当益壮 发表于 2018-4-14 09:49
是点阵不亮还是数码管不亮?

都不亮,如图那样
回复

使用道具 举报

ID:365277 发表于 2018-7-6 13:49 | 显示全部楼层
想问问电路图上的s0~s7分别对应的什么脚位
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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