基於51單片機的貪吃蛇游戲設計


本科時候做的一個課程作業,自己搭一個很簡易的電路,比較有意思且易上手,故將之記錄下來。(全套的仿真及代碼,演示視頻,課程報告以及PPT展示上傳在CSDN。)

一. 實驗目的

(1) 通過對C51語言的理解,編寫程序實現對貪吃蛇的有效控制;
(2) 通過對51單片機硬件的學習,學會運用面包板,獨立按鍵、點陣屏等,完成對完整電路的搭建過程;
(3) 通過對Proteus仿真軟件的學習,實現基於STC89C52單片機的8*8點陣貪吃蛇的硬件電路仿真。

二. 實驗介紹

貪吃蛇是一款經典小游戲,其游戲的規則是:玩家通過四個方向鍵來控制蛇的移動,控制其在地圖上吃豆子。吃掉豆子后蛇身相應加長,蛇身速度加快。蛇運動過程中撞到牆壁或蛇身,則立即結束本輪游戲。

三. 實現功能

(1)制作一個8*8點陣的貪吃蛇游戲;
(2)通過LED點陣屏為載體顯示數據;
(3)外接4個獨立按鍵作為輸入端,分別控制蛇的移動方向(上、下、左、右);
(4)蛇頭與牆壁或蛇身相撞,隨即結束游戲並復位。

四. 方案設計

在該系統中,硬件部分包括STC89C52單片機,8*8點陣屏,4個按鍵;軟件部分是在keil環境下用C51語言編寫,設置蛇的初始段數為2點,並設置有障礙牆壁,游戲結束后自動復位。
(1)貪吃蛇的移動
在貪吃蛇的移動過程中,每次需要將蛇頭要到的下一個LED燈點亮,對應蛇尾的LED燈熄滅。在程序中即是先把蛇尾位置的值傳給蛇頭的下一個位置,然后改變蛇尾的值即可。蛇頭下一個位置的確定由蛇頭和偏移量來確定,每次通過操作四個獨立按鍵來控制蛇步進的偏移量。因而只要將蛇頭的位置加上其偏移量的值,即可得到新的蛇頭位置。
(2)食物的出現
在市場上所流行的貪吃蛇游戲中,食物的出現是一種隨機行為,這在程序中需要做一個隨機數來支撐該過程。我們組在實驗過程中也嘗試了該過程,最終選擇讓食物出現在蛇尾的后一步,來執行整個程序。與此同時,食物出現的位置不能與蛇的位置重合,也不能超出牆外,否則需要重置食物。

五. 模塊應用

(1)AT89C52單片機最小系統模塊

本系統是以STC89C52RC為核心,加上復位電路和晶振電路來構成最小系統。該系統中選用11.0592M晶振,使得單片機有較為合理的運行速度;其起振電容對振盪器的頻率高低、穩定性以及快速性影響較合適,復位電路為按鍵高電平復位。
在這里插入圖片描述

(2)1588BS 8*8共陽點陣屏模塊

本實驗中是采用8*8共陽紅色點陣顯示屏,它共16個引腳,分別與單片機P1口的八位管腳、P2口的八位管腳,按照一定要求(連接規則來源於百度查詢)通過杜邦線一一對應連接,繼而用來顯示貪吃蛇的游戲畫面。
在這里插入圖片描述
點陣屏各點的點亮原理:
該點陣屏各引腳分別對應各led點(其原理圖詳見下圖),其基本原理是:當第一行接入高電平,第一列接入低電平,且其它列為高電平時,則第一個led燈點亮。同理,其他所有的led燈點亮原理均是如此。
在這里插入圖片描述

(3)獨立按鍵模塊

本實驗中外接4個獨立按鍵,分別通過控制單片機P3口的P3.1~P3.4,從而控制蛇的游走方向(上、下、左、右)。當按鍵未按下時,控制P3口為低電平;當其中某一按鍵按下后,電流會通過該按鍵,通過P3口中相對應的管腳進入單片機,使單片機變為高電平。當單片機檢測到高電平的時候,會做出相應反應,繼而實現貪吃蛇游戲。
在這里插入圖片描述

六. 程序流程

本實驗中主程序工作流程如下圖5所示,系統上電后首先對LED進行初始化,接着對定時器初始化,並啟動定時器,之后執行程序主題邏輯部分,程序主題邏輯執行一遍后檢查是否有中斷發生。本實驗中有兩個中斷源:一個是驅動貪吃蛇自動前行的定時中斷,另一個是用戶控制貪吃蛇移動方向的按鍵中斷。任意中斷的到來都將改變貪吃蛇當前狀態。若當前沒有中斷發生,主程序將繼續判斷蛇頭是否碰壁或發生頭尾相撞。若是,則結束游戲,否則返回繼續執行程序主體循環即可。
在這里插入圖片描述

七. 附 錄

7.1 Proteus電路仿真圖

在這里插入圖片描述

7.2 代碼

  1 #include <reg52.h>
  2 #define uchar unsigned char
  3 #define SNAKE 22             //最大長度
  4 #define TIME 40               //顯示延時時間
  5 #define SPEED 88              //速度控制
  6 #define  keyenable 1
  7 
  8 sbit led = P0^0;
  9 sbit up=P3^2; 
 10 sbit down=P3^4;
 11 sbit right=P3^3;
 12 sbit left=P3^1;
 13 
 14 uchar x[SNAKE+1];
 15 uchar y[SNAKE+1];          
 16 uchar time,n,i,e;         //延時時間,當前蛇長,通用循環變量,當前速度        
 17 char fx,fy;             //位移偏移量
 18 
 19 /***************************
 20         延時程序
 21 ****************************/
 22 void delay(char MS)
 23 {
 24     char us,usn;
 25     while(MS!=0)
 26     {
 27         usn = 0;
 28         while(usn!=0)
 29         {
 30             us=0xff;
 31             while (us!=0)
 32             {us--;};
 33             usn--;
 34         }
 35         MS--;
 36     }
 37 }
 38 /****************************
 39           判斷碰撞
 40 *****************************/
 41 bit knock()
 42 {
 43     bit k;
 44     k=0;
 45     if(x[1]>7||y[1]>7)
 46         k=1;                           //撞牆
 47     for(i=2;i<n;i++)
 48         if((x[1]==x[i])&(y[1]==y[i]))
 49             k=1;                       //撞自己
 50     return k;
 51 }
 52 /*****************************
 53       上下左右鍵位處理
 54 ******************************/
 55 void turnkey() 
 56 {
 57     if(keyenable)
 58     {
 59         if(left)
 60         {
 61             fy=0;
 62             if(fx!=1)
 63                 fx=-1; 
 64             else fx=1;
 65         }
 66         if(right)
 67         {
 68             fy=0;
 69             if(fx!=-1)
 70                 fx=1; 
 71             else fx=-1;
 72         }
 73         if(up)
 74         {
 75             fx=0;
 76             if(fy!=-1)
 77                 fy=1; 
 78             else fy=-1;
 79         }
 80         if(down)
 81         {
 82             fx=0;
 83             if(fy!=1)
 84                 fy=-1; 
 85             else fy=1;
 86         }
 87     }
 88 }
 89 /*******************************
 90           乘方程序
 91 ********************************/
 92 uchar mux(uchar temp) 
 93 {
 94     if(temp==7) return 128;
 95     if(temp==6) return 64;
 96     if(temp==5) return 32;
 97     if(temp==4) return 16;
 98     if(temp==3) return 8;
 99     if(temp==2) return 4;
100     if(temp==1) return 2;
101     if(temp==0) return 1;
102     return 0;
103 }
104 /*******************************
105        顯示時鍾 顯示程序
106 *******************************/
107 void timer0(uchar k)
108 {
109     while(k--)
110     {
111         for(i=0;i<SNAKE+1;i++)
112         {
113             P2=mux(x[i]);
114             P1=255-mux(y[i]);
115             turnkey();                   //上下左右鍵位處理
116             delay(TIME);                //顯示延遲
117             P2=0x00;
118             P1=0xff;
119         }
120     }
121 } 
122 /*******************************
123              主程序
124 *******************************/    
125 void main(void)
126 {
127     e=SPEED;
128     P0=0x00;
129     P1=0xff;
130     P2=0x00;
131     P3=0x00;
132     while(1)       
133     {
134         for(i=3;i<SNAKE+1;i++)
135             x[i]=100;
136         for(i=3;i<SNAKE+1;i++)
137             y[i]=100;                       //初始化
138         x[0]=4;
139         y[0]=4;                            //設置食物                            
140         n=3;                              //貪吃蛇長
141         x[1]=1;y[1]=0;                      //貪吃蛇頭
142         x[2]=0;y[2]=0;                      //貪吃蛇尾
143         fx=0;
144         fy=0;                              //位移偏移
145         while(1)
146         {
147             if(keyenable)
148                 break;
149                 timer0(1);
150         }
151         while(1)         
152          {
153             timer0(e);
154               if(knock())
155             {
156                 e=SPEED;
157                 break;
158             }                                //判斷碰撞
159             if((x[0]==x[1]+fx)&(y[0]==y[1]+fy))  //是否吃東西
160             {
161                 n++;
162                   if(n==SNAKE+1)
163                   {
164                     n=3;
165                     e=e+10;
166                       for(i=3;i<SNAKE+1;i++)
167                         x[i]=100;
168                       for(i=3;i<SNAKE+1;i++)
169                         y[i]=100;
170                  }
171                   x[0]=x[n-2];
172                   y[0]=y[n-2];
173             }
174                for(i=n-1;i>1;i--)
175             {
176                 x[i]=x[i-1];
177                 y[i]=y[i-1];
178             }        
179               x[1]=x[2]+fx;
180             y[1]=y[2]+fy;                     //移動
181          }                                        
182     }            
183 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM