久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 1519|回復: 0
打印 上一主題 下一主題
收起左側

基于51單片機的俄羅斯方塊程序與Proteus仿真圖

[復制鏈接]
跳轉到指定樓層
樓主
仿真在Proteus8.3運行正常,8.9不行
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)

部分代碼
  1. #include <REG52.H>
  2. #include"pic.c"
  3. #include <intrins.h>
  4. #define LCD_DATA P2
  5. #define button_delay 150  //按鍵延時
  6. #define button_acceleration 65  //按鍵加速度閾值
  7. #define GAME_LOCATION 30

  8. sbit change = P3^4;
  9. sbit OK = P3^5;
  10. sbit up = P3^2;
  11. sbit down = P3^0;
  12. sbit left = P3^1;
  13. sbit right = P3^3;
  14. sbit speaker=P3^6;

  15. sbit LCD_RS=P1^0;
  16. sbit LCD_RW=P1^1;
  17. sbit LCD_E=P1^2;
  18. sbit LCD_CS2=P1^4;        //右屏選擇(左右屏有時候相反)
  19. sbit LCD_CS1=P1^3;        //左屏選擇
  20. sbit LCD_RST=P3^7;

  21. unsigned int up_reg=button_delay;       //按鍵up累加器
  22. unsigned int down_reg=button_delay;     //按鍵down累加器
  23. unsigned int left_reg=button_delay;     //按鍵left累加器
  24. unsigned int right_reg=button_delay;    //按鍵right累加器
  25. unsigned int button_a_reg=button_delay; //按鍵button_a累加器
  26. unsigned int button_b_reg=button_delay; //按鍵button_b累加器
  27. unsigned int right_acceleration=0;        //按鍵right加速度寄存器
  28. unsigned int left_acceleration=0;        //按鍵left加速度寄存器

  29. unsigned int idata Box_Ram[19];//定義游戲點陣緩存10*16
  30. unsigned char box_down_reg;//定義方塊下落累加寄存器
  31. unsigned char time0_reg;//定義定時器0累加寄存器
  32. unsigned char next_mode;//定義下一個方塊的類型
  33. unsigned char next_shape;//定義下一個方塊的形狀
  34. unsigned int destroy_row_num=0;//定義所消的行數
  35. unsigned char speed_num=0;//定義游戲速度等級
  36. unsigned char level_num;//定義游戲難度等級
  37. bit game_over_flag;//游戲結束標志位置0表示游戲未結束
  38. bit pause_game_flag;//游戲暫停標志位置0表示游戲未暫停

  39. struct
  40. {
  41.     unsigned char mode;//類型
  42.     unsigned char shape;//形狀
  43.     unsigned char x;//x坐標
  44.     unsigned char y;//y坐標
  45.     unsigned int box;//定義方塊緩存
  46. }s_box;    //定義方塊結構體
  47. //LCD檢測忙狀態函數
  48. void LCD_check_busy()
  49. {
  50.     unsigned char temp;
  51.     LCD_RS=0;
  52.     LCD_RW=1;
  53.     do
  54.     {
  55.         LCD_DATA=0xff;
  56.         LCD_E=1;
  57.         temp=LCD_DATA;
  58.         LCD_E=0;
  59.     }while((temp&0x80)==0x80);        
  60. }
  61. //寫指令代碼(cs為0選左屏,cs為1選右屏)
  62. void LCD_W_code(unsigned char tpcode,bit cs)
  63. {
  64.     LCD_RS=0;
  65.     LCD_RW=0;
  66.     LCD_CS2=~cs;
  67.     LCD_CS1=cs;
  68.     LCD_DATA=tpcode;
  69.     LCD_E=1;
  70.     _nop_();
  71.     LCD_E=0;
  72. }
  73. //寫顯示數據(cs為0選左屏,cs為1選右屏)
  74. void LCD_W_data(unsigned char tpdata,bit cs)
  75. {
  76.     LCD_check_busy();
  77.     LCD_RS=1;
  78.     LCD_RW=0;
  79.     LCD_CS2=~cs;
  80.     LCD_CS1=cs;   
  81.     LCD_DATA=tpdata;
  82.     LCD_E=1;   
  83.     _nop_();
  84.     LCD_E=0;
  85. }

  86. //LCD初始化函數
  87. void LCD_initialize()
  88. {
  89.     LCD_RST=0;
  90.     _nop_();
  91.     _nop_();
  92.     LCD_RST=1;
  93.     LCD_W_code(0x3f,0);        //開顯示設置   
  94.     LCD_W_code(0xc0,0);        //設置顯示起始行為第一行   
  95.     LCD_W_code(0xb8,0);        //頁面地址設置   
  96.     LCD_W_code(0x40,0);        //列地址設為0
  97.     LCD_W_code(0x3f,1);
  98.     LCD_W_code(0xc0,1);   
  99.     LCD_W_code(0xb8,1);
  100.     LCD_W_code(0x40,1);
  101. }
  102. //LCD清屏函數
  103. void LCD_clear()
  104. {
  105.     unsigned char i,j;
  106.     for(j=0;j<8;j++)
  107.     {
  108.         LCD_W_code(0xb8+j,0);
  109.         LCD_W_code(0x40,0);
  110.         LCD_W_code(0xb8+j,1);
  111.         LCD_W_code(0x40,1);
  112.         for(i=0;i<64;i++)
  113.             {   
  114.                 LCD_W_data(0x00,0);   
  115.                 LCD_W_data(0x00,1);
  116.             }
  117.     }
  118. }
  119. //LCD顯示字符串函數(word表示要顯示的字符串,
  120. //length表示要顯示的字符串寬度,
  121. //x表示首字符所在行數,
  122. //y表示首字符所在列數)
  123. void LCD_display_word(unsigned char word[],
  124.                       unsigned int length,
  125.                       unsigned char x,
  126.                       unsigned char y)
  127. {
  128.     unsigned char i;
  129.     for(i=0;i<length;i++)
  130.     {
  131.         
  132.         LCD_W_code(0xb8+x,0);
  133.         LCD_W_code(0xb8+x,1);
  134.         if(y+i<64)
  135.         {
  136.             LCD_W_code(0x40+y+i,0);   
  137.             LCD_W_data(word[i],0);
  138.         }
  139.         else
  140.         {
  141.             LCD_W_code(y+i,1);   
  142.             LCD_W_data(word[i],1);
  143.         }
  144.     }
  145. }
  146. //LCD畫全屏函數
  147. void LCD_full_draw(unsigned char word[])
  148. {
  149.     unsigned char i,j;
  150.     for(i=0;i<8;i++)
  151.     {
  152.         LCD_W_code(0xb8+i,0);
  153.         LCD_W_code(0x40,0);   
  154.         for(j=0;j<64;j++)
  155.         {
  156.             LCD_W_data(word[i*128+j],0);
  157.         }
  158.         LCD_W_code(0xb8+i,1);
  159.         LCD_W_code(0x40,1);   
  160.         for(j=0;j<64;j++)
  161.         {
  162.             LCD_W_data(word[i*128+64+j],1);
  163.         }            
  164.     }
  165. }
  166. //LCD顯示一個字節函數(
  167.   //x表示x坐標,
  168.   //y表示y坐標,
  169.   //tpdata表示要顯示的數據)
  170. void LCD_display_byte(unsigned char x,
  171.                       unsigned char y,
  172.                       unsigned char tpdata)
  173. {
  174.     if(x<64)
  175.     {
  176.         LCD_W_code(0xb8+y,0);
  177.         LCD_W_code(0x40+x,0);
  178.         LCD_W_data(tpdata,0);   
  179.     }
  180.     else
  181.     {
  182.         LCD_W_code(0xb8+y,1);
  183.         LCD_W_code(x,1);
  184.         LCD_W_data(tpdata,1);   
  185.     }
  186. }

  187. void LCD_draw(unsigned char word[])
  188. {
  189.   unsigned char i,j;
  190.   for(i=0;i<8;i++)
  191.   {
  192.     LCD_W_code(0xb8+i,1);
  193.     LCD_W_code(0x40+20,1);
  194.     for(j=0;j<44;j++)
  195.     {
  196.       LCD_W_data(word[i*44+j],1);
  197.     }
  198.   }
  199. }
  200. //基本界面顯示函數
  201. void display_basic()
  202. {
  203.     unsigned char i;
  204.     for(i=0;i<8;i++)
  205.     {
  206.         LCD_display_byte(GAME_LOCATION,i,0xff);
  207.         LCD_display_byte(GAME_LOCATION+41,i,0xff);
  208.     }
  209. }
  210. //刷新游戲區域函數
  211. void refurbish_display()
  212. {
  213.     unsigned char i,j,tpdata;
  214.     for(i=0;i<8;i++)
  215.     {
  216.         for(j=0;j<10;j++)
  217.         {
  218.             tpdata=0x00;
  219.             if(  (Box_Ram[2*i]>>(12-j))&0x0001==1  )
  220.             {
  221.                 tpdata=0x0f;
  222.             }
  223.             if(  (Box_Ram[2*i+1]>>(12-j))&0x0001==1  )
  224.             {
  225.                 tpdata|=0xf0;
  226.             }
  227.             LCD_display_byte(GAME_LOCATION+1+j*4,i,tpdata);
  228.             LCD_display_byte(GAME_LOCATION+2+j*4,i,0xbb&tpdata);
  229.             LCD_display_byte(GAME_LOCATION+3+j*4,i,0xdd&tpdata);
  230.             LCD_display_byte(GAME_LOCATION+4+j*4,i,tpdata);
  231.         }
  232.     }
  233. }
  234. //基本按鍵程序(返回0表示沒按鍵被按下,返回1表示down被按下,返回2表示up被按下,返回3表示button_a被按下,返回4表示left被按下,返回5表示right被按下)
  235. //游戲中按鍵識別程序(有優先級,從高到低依次是button_a_reg>down>left>right>up)
  236. unsigned char basic_button()
  237. {
  238.     unsigned char tpflag=0;
  239.     if(OK==0)
  240.     {
  241.         if(button_b_reg<button_delay*8)
  242.         {
  243.           button_b_reg++;
  244.         }
  245.         else
  246.         {
  247.           button_b_reg=0;
  248.           tpflag=6;
  249.         }
  250.     }
  251.     else
  252.     {
  253.             button_b_reg=button_delay*8;
  254.     }
  255.     if(down==0)
  256.     {
  257.         if(down_reg<button_delay)//按鍵一直被按下時設置時間間隔觸發
  258.         {
  259.             down_reg++;
  260.         }
  261.         else
  262.         {
  263.             down_reg=0;
  264.             tpflag=1;//返回1表示down被按下
  265.         }        
  266.     }
  267.     else
  268.     {
  269.         down_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  270.     }
  271.     if(up==0)
  272.     {
  273.         if(up_reg<button_delay)//按鍵一直被按下時設置時間間隔觸發
  274.         {
  275.             up_reg++;
  276.         }
  277.         else
  278.         {
  279.             up_reg=0;
  280.             tpflag=2;//返回2表示up被按下
  281.         }        
  282.     }
  283.     else
  284.     {
  285.         up_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  286.     }
  287.     if(change==0)
  288.     {
  289.         if(button_a_reg<button_delay*8)//按鍵一直被按下時設置時間間隔觸發
  290.         {
  291.             button_a_reg++;
  292.         }
  293.         else
  294.         {
  295.             button_a_reg=0;
  296.             tpflag=3;//返回3表示button_a被按下
  297.         }        
  298.     }
  299.     else
  300.     {
  301.         button_a_reg=button_delay*8;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  302.     }
  303.     if(left==0)
  304.     {
  305.         if(left_reg<(button_delay))//按鍵一直被按下時設置時間間隔觸發
  306.         {
  307.             left_reg++;
  308.         }
  309.         else
  310.         {
  311.             left_reg=left_acceleration*button_acceleration;
  312.             if(left_acceleration<2)left_acceleration++;
  313.             tpflag=4;//返回4表示left被按下
  314.         }        
  315.     }
  316.     else
  317.     {
  318.         left_acceleration=0;
  319.         left_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  320.     }
  321.     if(right==0)
  322.     {
  323.         if(right_reg<(button_delay))//按鍵一直被按下時設置時間間隔觸發
  324.         {
  325.             right_reg++;
  326.         }
  327.         else
  328.         {
  329.             right_reg=right_acceleration*button_acceleration;
  330.             if(right_acceleration<2)right_acceleration++;
  331.             tpflag=5;//返回5表示right被按下
  332.         }        
  333.     }
  334.     else
  335.     {
  336.         right_acceleration=0;
  337.         right_reg=button_delay;//釋放按鍵時置按鍵緩存為button_delay,以便在下次按鍵時及時響應
  338.     }
  339.     return(tpflag);
  340. }
  341. //檢查覆蓋函數(檢查此時帶入的參數所確定的方塊是否會覆蓋原有圖形,不會覆蓋返回1,覆蓋返回0)
  342. bit check_cover(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
  343. {
  344.     unsigned char i;
  345.     bit tpflag=1;
  346.     unsigned int temp;
  347.     temp=s_box.box;
  348.     for(i=0;i<4;i++)
  349.     {
  350.         Box_Ram[3-i+s_box.y]&=(~((temp&0x000f)<<(9-s_box.x)));
  351.         temp=temp>>4;
  352.     }//先將現有的方塊從游戲點陣緩存中刪除
  353.     temp=tpbox;
  354.     for(i=0;i<4;i++)
  355.     {
  356.         if((((temp&0x000f)<<(9-tpx))&Box_Ram[3-i+tpy])!=0x0000)
  357.         {
  358.             tpflag=0;
  359.         }
  360.         temp=temp>>4;
  361.     }//檢查方塊是否和原有圖形重疊,重疊置標志位tpflag為0,不重疊不置標志位,即tpflag為1
  362.     temp=s_box.box;
  363.     for(i=0;i<4;i++)
  364.     {
  365.         Box_Ram[3-i+s_box.y]|=((temp&0x000f)<<(9-s_box.x));
  366.         temp=temp>>4;
  367.     }//在游戲點陣緩存中恢復原有方塊
  368.     return(tpflag);
  369. }
  370. //方塊緩存數據函數(輸入方塊類型和形狀即可獲得方塊緩存數據)
  371. unsigned int box_read_data(unsigned char tpmode,unsigned char tpshape)
  372. {
  373.     unsigned int tpbox;
  374.     switch(tpmode)
  375.     {
  376.         case 0: switch(tpshape)
  377.                 {
  378.                     case 0: tpbox=0xf000;break;
  379.                     case 1: tpbox=0x4444;break;
  380.                     case 2: tpbox=0xf000;break;
  381.                     case 3: tpbox=0x4444;break;
  382.                     default:;
  383.                 }break;   
  384.         case 1: switch(tpshape)
  385.                 {
  386.                     case 0: tpbox=0xe800;break;
  387.                     case 1: tpbox=0xc440;break;
  388.                     case 2: tpbox=0x2e00;break;
  389.                     case 3: tpbox=0x88c0;break;
  390.                     default:;
  391.                 }break;   
  392.         case 2: switch(tpshape)
  393.                 {
  394.                     case 0: tpbox=0xe200;break;
  395.                     case 1: tpbox=0x44c0;break;
  396.                     case 2: tpbox=0x8e00;break;
  397.                     case 3: tpbox=0xc880;break;
  398.                     default:;
  399.                 }break;   
  400.         case 3: switch(tpshape)
  401.                 {
  402.                     case 0: tpbox=0xcc00;break;
  403.                     case 1: tpbox=0xcc00;break;
  404.                     case 2: tpbox=0xcc00;break;
  405.                     case 3: tpbox=0xcc00;break;
  406.                     default:;
  407.                 }break;   
  408.         case 4: switch(tpshape)
  409.                 {
  410.                     case 0: tpbox=0xc600;break;
  411.                     case 1: tpbox=0x4c80;break;
  412.                     case 2: tpbox=0xc600;break;
  413.                     case 3: tpbox=0x4c80;break;
  414.                     default:;
  415.                 }break;   
  416.         case 5: switch(tpshape)
  417.                 {
  418.                     case 0: tpbox=0x6c00;break;
  419.                     case 1: tpbox=0x8c40;break;
  420.                     case 2: tpbox=0x6c00;break;
  421.                     case 3: tpbox=0x8c40;break;
  422.                     default:;
  423.                 }break;
  424.         case 6: switch(tpshape)
  425.                 {
  426.                     case 0: tpbox=0x4e00;break;
  427.                     case 1: tpbox=0x8c80;break;
  428.                     case 2: tpbox=0xe400;break;
  429.                     case 3: tpbox=0x4c40;break;
  430.                     default:;
  431.                 }break;
  432.         default:;
  433.     }
  434.     return(tpbox);
  435. }
  436. //方塊載入函數
  437. void box_load()
  438. {
  439.     s_box.box=box_read_data(s_box.mode,s_box.shape);
  440. }
  441. //方塊映射游戲點陣緩存函數(參數是原來方塊的位置、緩存,先消去原有位置的方塊)
  442. void box_to_Box_Ram(unsigned char tpx,unsigned char tpy,unsigned int tpbox)
  443. {
  444.     unsigned char i;
  445.     unsigned int temp;
  446.     temp=tpbox;
  447.     for(i=0;i<4;i++)
  448.     {
  449.         Box_Ram[3-i+tpy]=Box_Ram[3-i+tpy]&(~((temp&0x000f)<<(9-tpx)));
  450.         temp=temp>>4;
  451.     }//從游戲點陣緩存中刪除以前的方塊
  452.     temp=s_box.box;
  453.     for(i=0;i<4;i++)
  454.     {
  455.         Box_Ram[3-i+s_box.y]=((temp&0x000f)<<(9-s_box.x))|Box_Ram[3-i+s_box.y];
  456.         temp=temp>>4;
  457.     }//在游戲點陣緩存中加入新的方塊
  458. }
  459. //顯示數字函數(
  460.   //x表示x坐標,
  461.   //y表示y坐標,
  462.   //tpdata表示要顯示的數字)
  463. //顯示速度函數
  464. void show_num(unsigned char x,
  465.                       unsigned char y,
  466.                       unsigned char tpdata)
  467. {
  468.     unsigned char i;
  469.     for(i=0;i<4;i++)
  470.     {
  471.         LCD_display_byte(x+i,y,num_data[tpdata*4+i]);   
  472.     }
  473. }
  474. void show_speed_num(unsigned char x,unsigned char y)
  475. {
  476.     show_num(x,y,speed_num);
  477. }
  478. //顯示得分函數
  479. void show_score_num(unsigned char x,unsigned char y)
  480. {
  481.     show_num(x,y,destroy_row_num/10000);
  482.     show_num(x+=5,y,(destroy_row_num%10000)/1000);
  483.     show_num(x+=5,y,(destroy_row_num%1000)/100);
  484.     show_num(x+=5,y,(destroy_row_num%100)/10);
  485.     show_num(x+=5,y,destroy_row_num%10);
  486. }
  487. //消行函數
  488. void destroy_row()
  489. {
  490.     unsigned char i,j=0;
  491.     unsigned char tpflag[4]={0,0,0,0};//最多一次只能消四行,所以設置四個標志位即可,初值為0
  492.     for(i=0;i<16;i++)
  493.     {
  494.         if((Box_Ram[i]&0x3ffc)==0x3ffc)
  495.         {
  496.             tpflag[j]=i+1;//tpflag為0表示不標志,1表示第0行緩存為0xffff,n表示第n+1行緩存為0xffff
  497.             destroy_row_num++;//消除的行數加一
  498.             /*如不把Box_Ram[19]定義成idata類型的話加入這段代碼顯示數據區就溢出了*/
  499.             if(destroy_row_num%30==0&&speed_num!=9)
  500.             {
  501.                 speed_num++;//消夠三十行游戲速度加一
  502.                 show_speed_num(13,4);//調用顯示游戲速度函數
  503.             }
  504.             /*如不把Box_Ram[19]定義成idata類型的話加入這段代碼顯示數據區就溢出了*/
  505.             j++;
  506.             if(j==4)
  507.             {
  508.                 break;
  509.             }//檢查完有四行要消除則退出檢查循環
  510.         }
  511.     }//依次檢測是否有行緩存為0xffff,如果是則標志tpflag為此行的行號
  512.     for(j=0;j<4;j++)
  513.     {
  514.         if(tpflag[j]!=0)
  515.         {
  516.             for(i=tpflag[j]-1;i>0;i--)
  517.             {
  518.             Box_Ram[i]=Box_Ram[i-1];
  519.             Box_Ram[0]=0x2004;
  520.             }
  521.         }
  522.     }//被標志的行依次被上一行所取代,即被消去
  523.     show_score_num(3,1);
  524. }
  525. //顯示下一個方塊函數
  526. void show_next_box()
  527. {
  528.     unsigned char i,tpdata;
  529.     unsigned int temp;
  530.     temp=box_read_data(next_mode,next_shape);
  531.     for(i=0;i<4;i++)
  532.     {
  533.         tpdata=0x00;
  534.         if(  ((temp>>(15-i))&0x0001)==1  )
  535.         {
  536.             tpdata=0x0f;
  537.         }
  538.         if(  ((temp>>(11-i))&0x0001)==1  )
  539.         {
  540.             tpdata|=0xf0;
  541.         }
  542.         LCD_display_byte(7+i*4,6,tpdata);
  543.         LCD_display_byte(8+i*4,6,0xbb&tpdata);
  544.         LCD_display_byte(9+i*4,6,0xdd&tpdata);
  545.         LCD_display_byte(10+i*4,6,tpdata);   
  546.         tpdata=0x00;
  547.         if(  ((temp>>(7-i))&0x0001)==1  )
  548.         {
  549.             tpdata=0x0f;
  550.         }
  551.         if(  ((temp>>(3-i))&0x0001)==1  )
  552.         {
  553.             tpdata|=0xf0;
  554.         }
  555.         LCD_display_byte(7+i*4,7,tpdata);
  556.         LCD_display_byte(8+i*4,7,0xbb&tpdata);
  557.         LCD_display_byte(9+i*4,7,0xdd&tpdata);
  558.         LCD_display_byte(10+i*4,7,tpdata);        
  559.     }
  560. }
  561. //方塊生成函數
  562. void box_build()
  563. {
  564.     s_box.mode=next_mode;
  565.     s_box.shape=next_shape;
  566.     s_box.x=3;
  567.     s_box.y=0;
  568.     next_mode=TL0%7;//產生隨機數,但是是偽隨機的
  569.     next_shape=TL0%4;//產生隨機數,但是是偽隨機的
  570.     show_next_box();//放到game_execute()函數中不知道為什么就是不正常顯示(2015注釋:程序可能重入了)
  571. }
  572. void game_button()
  573. {
  574.    
  575.     switch(basic_button())
  576.     {
  577.         case 3: if(s_box.y!=0)//3表示button_a被按下
  578.                 {
  579.                     EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  580.                     speaker=0;
  581.                     if(s_box.shape==3&&check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,0)))
  582.                     {
  583.                            
  584.                         s_box.shape=0;
  585.                         box_load();
  586.                         box_to_Box_Ram(s_box.x,s_box.y,box_read_data(s_box.mode,3));
  587.                     }
  588.                     else if(check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,0)))
  589.                     {    if(check_cover(s_box.x,s_box.y,box_read_data(s_box.mode,s_box.shape+1)))
  590.                             {   
  591.                                 s_box.shape++;
  592.                                 box_load();
  593.                                 box_to_Box_Ram(s_box.x,s_box.y,box_read_data(s_box.mode,s_box.shape-1));
  594.                             }
  595.                      }
  596.                     EA=1;//開中斷
  597.                     speaker=1;
  598.                     }break;
  599.         case 1: if(s_box.y!=0)//1表示down被按下
  600.         {
  601.             EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  602.             speaker=0;
  603.             while(check_cover(s_box.x,s_box.y+1,s_box.box))//檢測是否能下降,指導不能再下降為止
  604.             {
  605.                 s_box.y++;
  606.                 box_to_Box_Ram(s_box.x,s_box.y-1,s_box.box);
  607.             }
  608.             destroy_row();
  609.             box_build();
  610.             box_load();
  611.                     //    game_over_flag=check_game_over();//游戲結束標志位置1表示游戲結束
  612.                     //    next_box();
  613.             box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  614.             EA=1;//開中斷
  615.             speaker=1;
  616.             }break;
  617.         case 4: if(s_box.y!=0)//4表示left被按下
  618.         {
  619.             EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  620.             speaker=0;
  621.             if(check_cover(s_box.x-1,s_box.y,s_box.box))
  622.             {
  623.                 s_box.x--;
  624.                 box_to_Box_Ram(s_box.x+1,s_box.y,s_box.box);
  625.             }
  626.             EA=1;//開中斷
  627.             speaker=1;
  628.         }break;
  629.         case 5: if(s_box.y!=0)//5表示right被按下
  630.                 {
  631.                     EA=0;//關中斷,如果不關的話可能引起游戲顯示混亂
  632.                     speaker=0;
  633.                     if(check_cover(s_box.x+1,s_box.y,s_box.box))
  634.                     {
  635.                         s_box.x++;
  636.                         box_to_Box_Ram(s_box.x-1,s_box.y,s_box.box);
  637.                     }
  638.                         EA=1;//開中斷
  639.                         speaker=1;
  640.                     }break;
  641.         case 2: //2表示up被按下
  642.             speaker=0;
  643.             pause_game_flag=~pause_game_flag;//游戲暫停標志取反
  644.             while(up==0);
  645.             speaker=1;
  646.             break;
  647.         default:;
  648.     }   
  649. }
  650. //檢查游戲結束函數(游戲結束返回1,游戲沒有結束返回0)
  651. bit check_game_over()
  652. {
  653.     unsigned char i;
  654.     bit tpflag=0;
  655.     unsigned int temp;
  656.     temp=s_box.box;
  657.     for(i=0;i<4;i++)
  658.     {
  659.         if((((temp&0x000f)<<(9-s_box.x))&Box_Ram[3-i+s_box.y])!=0x0000)
  660.         {
  661.             tpflag=1;
  662.         }
  663.         temp=temp>>4;
  664.     }//檢查新建方塊是否和原有圖形重疊,重疊置標志位tpflag為1,不重疊不置標志位,即tpflag為0
  665.     return(tpflag);
  666. }
  667. //游戲執行函數(控制方塊下落,檢測是否到底,如果到底調用消行函數)
  668. void game_execute()
  669. {
  670.     if(box_down_reg<20-(speed_num<<1))
  671.     {                  
  672.         box_down_reg++;
  673.     }
  674.     else
  675.     {
  676.         box_down_reg=0;
  677.         if(check_cover(s_box.x,s_box.y+1,s_box.box))
  678.         {
  679.             s_box.y++;
  680.             box_to_Box_Ram(s_box.x,s_box.y-1,s_box.box);
  681.         }//檢測是否還可以下降,如果還能下降則繼續下降
  682.         else
  683.         {
  684.             destroy_row();
  685.             box_build();
  686.             box_load();
  687.             game_over_flag=check_game_over();//游戲結束標志位置1表示游戲結束
  688.             box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  689.             box_down_reg=(20-(speed_num<<1)-1);//為了使方塊一出現就能變換形狀,所以需要盡快使得方塊下降一行,不知道為什么最高行不能變換形狀
  690.         }//如果不能下降則調用消行函數檢查是否可以消行,之后重新建立方塊
  691.     }   
  692. }
  693. //選擇游戲速度函數
  694. void select_speed()
  695. {
  696.     unsigned char i;
  697.     bit tpflag=1;//置循環標志位為1
  698.     LCD_clear();
  699.     for(i=0;i<128;i++)
  700.     {
  701.         LCD_display_byte(i,0,0xff);
  702.         LCD_display_byte(i,7,0xff);
  703.     }
  704.     LCD_display_byte(60,4,0x7f);
  705.     LCD_display_byte(59,4,0x3e);
  706.     LCD_display_byte(58,4,0x1c);
  707.     LCD_display_byte(57,4,0x08);
  708.     LCD_display_byte(67,4,0x7f);
  709.     LCD_display_byte(68,4,0x3e);
  710.     LCD_display_byte(69,4,0x1c);
  711.     LCD_display_byte(70,4,0x08);
  712.     LCD_display_word(speed_data,24,3,52);
  713.     show_speed_num(62,4);
  714.     while(tpflag)
  715.     {
  716.         switch(basic_button())
  717.         {
  718.             case 4: if(speed_num!=0)
  719.                     {
  720.                         speaker=0;
  721.                         speed_num--;
  722.                         show_speed_num(62,4);
  723.                         speaker=1;
  724.                     }
  725.                     while(left==0);
  726.                     break;
  727.             case 5: if(speed_num!=9)
  728.                     {
  729.                         speaker=0;
  730.                         speed_num++;
  731.                         show_speed_num(62,4);
  732.                         speaker=1;
  733.                     }
  734.                     while(right==0);
  735.                     break;
  736.             case 6: tpflag=0;
  737.                      speaker=0;
  738.                     while(OK==0);
  739.                     speaker=1;
  740.                     break;
  741.             default:;
  742.         }
  743.     }//選擇游戲速度循環
  744. }
  745. //游戲開始顯示畫面
  746. void game_start_show()
  747. {
  748.     bit tpflag=1;//置循環標志位為1
  749.     LCD_full_draw(start_pic);
  750.     while(tpflag)
  751.     {
  752.         switch(basic_button())
  753.         {
  754.             case 6: tpflag=0;
  755.                     speaker=0;
  756.                     while(OK==0);
  757.                     speaker=1;
  758.                     break;
  759.             default:;
  760.         }
  761.     }//game_start_show循環
  762. }
  763. //游戲初始化函數
  764. void game_initialize()
  765. {
  766.     box_down_reg=0;
  767.     next_mode=6;
  768.     next_shape=2;
  769.     destroy_row_num=0;
  770.     game_over_flag=0;
  771.     pause_game_flag=0;
  772.     LCD_clear();
  773.     time0_reg=0;
  774.     display_basic();   
  775.     LCD_display_word(score_data,24,0,3);
  776.     LCD_display_word(speed_data,24,3,3);
  777.     show_score_num(3,1);
  778.     show_speed_num(13,4);
  779. }
  780. //定時器0初始化函數
  781. void time0_initialize()
  782. {
  783.     TMOD=0x03;//定時器0,16位工作方式
  784.     TR0=1; //啟動定時器
  785.     ET0=1; //打開定時器0中斷
  786.             //默認中斷優先級為低
  787.     EA=1; //打開總中斷
  788. }
  789. //俄羅斯方塊游戲主函數
  790. void Tetris_main()
  791. {
  792.     unsigned char i;
  793.     for(i=0;i<19;i++)
  794.     {
  795.         Box_Ram[i]=Box_Ram_data[i];
  796.     };//載入游戲初始顯示畫面
  797.     LCD_draw(mpic);
  798.     game_over_flag=0;//游戲結束標志位置0表示游戲未結束
  799.     box_build();
  800.     box_load();
  801. //    next_box();
  802.     box_to_Box_Ram(s_box.x,s_box.y,s_box.box);
  803.     box_down_reg=(20-(speed_num<<1)-1);//為了使方塊一出現就能變換形狀,所以需要盡快使得方塊下降一行,不知道為什么最高行不能變換形狀
  804.     time0_initialize();
  805.     while(!game_over_flag)//如果游戲結束標志位置1,表示游戲結束,打破循環,調用游戲結束畫面顯示函數
  806.     {
  807.         game_button();
  808.     }
  809.     EA=0;//游戲結束后關中斷
  810. }
  811. //游戲結束畫面顯示函數
  812. void game_over_show()
  813. {
  814.     unsigned char i;
  815.     bit tpflag=1;//置循環標志位為1
  816.     LCD_full_draw(over_pic);
  817.     while(change==0);
  818.     while(tpflag)
  819.     {
  820.         switch(basic_button())
  821.         {
  822.             case 6: tpflag=0;
  823.                     speaker=0;
  824.                     while(OK==0);
  825.                     speaker=1;
  826.                     break;
  827.             default:;
  828.         }
  829.     }//game over畫面循環
  830.     LCD_clear();
  831.     for(i=0;i<128;i++)
  832.     {
  833.         LCD_display_byte(i,0,0xff);
  834.         LCD_display_byte(i,7,0xff);
  835.     }
  836.     LCD_display_word(score_data,24,3,52);
  837.     show_score_num(52,4);
  838.     tpflag=1;
  839.     while(tpflag)
  840.     {
  841.         switch(basic_button())
  842.         {
  843.             case 6: tpflag=0;
  844.                     speaker=0;
  845.                     while(OK==0);
  846.                     speaker=1;
  847.                     break;
  848.             default:;
  849.         }
  850.     }//游戲得分顯示循環
  851. }

  852. void main()
  853. {
  854.     LCD_initialize();
  855.     LCD_clear();
  856.     while(1)
  857.     {
  858.         game_start_show();
  859.         select_speed();
  860.         game_initialize();//調用游戲初始化函數,初始化游戲所有變量以及在液晶屏上顯示基本的信息
  861.         Tetris_main();
  862.         game_over_show();   
  863.     }   
  864. }
  865. //定時器0中斷服務
  866. void timer0() interrupt 1
  867. {
  868.     TH0=0x00;
  869.     TL0=0x00;
  870.     if(time0_reg<10)
  871.     {                  
  872.         time0_reg++;
  873.     }
  874.     else
  875.     {
  876.         time0_reg=0;
  877.         if(pause_game_flag==0)
  878.         {
  879.             game_execute();
  880.             refurbish_display();
  881.         }
  882.     }
  883. }
復制代碼

仿真在Proteus8.13 8.3運行正常,8.9不行
Keil代碼與Proteus仿真下載: Proteus8.13仿真程序.7z (80.34 KB, 下載次數: 29)

評分

參與人數 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 91丨九色丨国产在线 | 在线视频a| 久草网址| 在线只有精品 | 日本高清不卡视频 | 久久999 | 欧美视频免费在线观看 | 国产一区二区三区四区在线观看 | 7777久久| 一区二区三区高清 | 麻豆精品国产91久久久久久 | 亚洲成人av | 欧美精品一区二区在线观看 | 华丽的挑战在线观看 | 亚洲人成人一区二区在线观看 | 亚洲精品第一国产综合野 | 一区中文字幕 | 亚洲欧美日韩网站 | 男女羞羞视频在线看 | 亚洲视频在线看 | 精品国产免费人成在线观看 | 欧美性猛交一区二区三区精品 | 婷婷久| 人人天天操 | www国产成人免费观看视频,深夜成人网 | 久久国产高清视频 | 国产精品1区2区 | 精品国产一区二区三区观看不卡 | 视频1区2区 | 亚洲综合无码一区二区 | 黄色国产视频 | 亚洲国产二区 | 久久99国产精一区二区三区 | www亚洲精品 | 国产剧情一区 | 亚洲综合久久网 | 性色av香蕉一区二区 | 久久lu| 天天干天天色 | 成人欧美一区二区三区黑人孕妇 | 欧美一级黄色免费看 |