自己編的貪吃蛇程序,最多就用到了數組,很適合小白,注釋比較全
如何將要點亮的坐標轉化成點陣屏需要的碼表
紅色的位置坐標為(0,0)
假設我們要點亮藍色的位置,即點亮坐標(2,0)和(2,1),由點陣屏的知識我們知道,我們需要的碼表tabel[8]={
1 1 0 1 1 1 1 1 --> 0xdf
1 1 0 1 1 1 1 1 --> 0xdf
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
1 1 1 1 1 1 1 1 --> 0xff
}
很容易發現,需要點亮的位置就要置零
所以我們可以先設一個tabel={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}
假設我們的坐標存在一個二維數組里snake[20][2]={{2,0},{2,1}}(后面不賦值的就默認為0,0了)
縱坐標正好就表示我們要修改tabel的第幾個數
比如坐標(2,0),我們需要將tabel[0]的0xff的第六位(從右往左數)置零
所以我們可以從這里找到聯系(同標紅和同標藍的數據有聯系),用以下方法
for(i=0;i<n;i++)//這里的n表示要顯示點的個數,此處為n=2
{
tabel[snake[ i][1]]=tabel[snake[ i][1]]^(unsigned char)pow(2,7-snake[ i][0]);
}
其中pow函數是求2的n次方的,包含在頭文件<math.h>里,返回值是double
所以要強制類型轉換成unsigned char,我們拿縱坐標對應的那個tabel的0xff
與 2的(7-橫坐標)次方 按位異或,有點拗口 看例子:
當i=0時,snake[0]={2,0}
pow(2,7-snake[ i][0])=100000
11111111與100000按位異或=11011111即0xdf
當i=2時,snake[1]={2,1}
pow(2,7-snake[ i][0])=100000
11111111與100000按位異或=11011111即0xdf
當i>=2時,tabel為初始值0xff
因此實現了坐標轉碼表
作者:小仙峰
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機貪吃蛇源程序如下:
- #include<reg51.h>
- #include<math.h>
- #include<intrins.h>
- #define max 20//最大蛇長
- #define delay 300//delay越小越快
- sbit DIO=P3^4;//串行數據口
- sbit SHCP=P3^5;//移位寄存器時鐘
- sbit STCP=P3^6;//輸出鎖存器時鐘
- sbit up=P1^0;//獨立鍵盤上
- sbit down=P1^1;//獨立鍵盤下
- sbit left=P1^2;//左
- sbit right=P1^3;//右
- unsigned char n,i,j,ifdie,button,ret;//依次為當前蛇長,通用循環變量(i和j),是否死亡,上下左右命令儲存,果子,eating的返回值
- unsigned char snake[max][2]={1,0,0,0};//蛇的每一個點的坐標數組,蛇頭(1,0),第二段為(0,0)
- unsigned char tabel[8] ={0};//這個相當于一個8*8矩陣,用于裝坐標轉換成的的74HC595需要的8個16進制碼
- unsigned char apple[2]={3,3};//初始果子位置,隨機數有點麻煩
- void direction(void);//判斷上下左右函數
- void eating(void);//判斷吃果子函數
- void die(void);//判斷死亡函數
- void send_byte(unsigned char byte);//74HC595串入并出要用到的函數
- void show(void);//以上都是處理蛇的坐標,這個函數就是將要顯示的坐標轉換成74HC595能識別的16進制碼
- void main()
- {
- ifdie=1;//先賜死
- while(ifdie)
- {
- ifdie=0;//然后重生
- n=2;//初始蛇長為2
- snake[0][0]=1; snake[0][1]=0;//蛇每次重生在左上角
- snake[1][0]=0; snake[1][1]=0;//蛇每次重生在左上角
- apple[0]=3; apple[1]=3;//果子回到初始位置
- button=0;//重生后要把按鍵賦零
- while(ifdie!=1)//蛇沒死我們就循環執行
- {
- ret=0;//每一輪開始都設沒吃到果子
- direction();//判斷方向,改變坐標
- eating();//判斷如果吃到果子身長+1
- die();//判斷死沒死
- show();//將蛇身的坐標轉碼展示到點陣屏上
- if(n==max)
- ifdie=1;//蛇長最大了,賜死吧
- }
- }
- }
- void direction(void)//判斷方向
- {
- if(button==1&&snake[0][1]!=snake[1][1]+1)//向上
- {
- for(i=n-1;i>0;i--)//后一個蛇身坐標等于前一個蛇身坐標
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][1]--;//蛇頭縱坐標減一
- }
- if(button==2&&snake[0][1]!=snake[1][1]-1)//向下
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][1]++;
- }
- if(button==3&&snake[0][0]!=snake[1][0]+1)//向左
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][0]--;
- }
- if(button==4&&snake[0][0]!=snake[1][0]-1)//向右
- {
- for(i=n-1;i>0;i--)
- {
- for(j=0;j<2;j++)
- snake[i][j]=snake[i-1][j];
- }
- snake[0][0]++;
- }
- }
- void eating(void)
- {
- if(snake[0][0]==apple[0]&&snake[0][1]==apple[1])//當蛇頭坐標與果子坐標相同時
- {
- for(j=0;j<2;j++)
- {
- snake[n][j]=snake[n-1][j];//吃到果子后,蛇的下一節長出來
- apple[j]=snake[n-1][j];//不會隨機數,所以下一個果子出現在蛇尾
- }
- n++;//蛇長加一
- ret = 1;//告訴下面的步驟:吃到了果子
- }
- }
- void die(void)
- {
- if(snake[0][0]==8||snake[0][0]==255||snake[0][1]==8||snake[0][1]==255)//蛇頭出界
- ifdie=1;//死掉
- for(i=4;i<n;i++)//因為撞自己蛇長至少要五,所以i從四開始
- {
- if(snake[0][0]==snake[i][0]&&snake[0][1]==snake[i][1])
- ifdie=1;//如果蛇頭和蛇身坐標重合,死掉
- }
- }
- void send_byte(unsigned char byte)//這是清翔講的8*8點陣屏+74HC595的標配函數
- {
- unsigned char dat;
- dat=byte;
- for(j=0;j<8;j++)
- {
- SHCP=0;
- STCP=0;
- if(dat & 0X01)
- DIO=1;
- else
- DIO=0;
- SHCP=1;
- dat>>=1;
- }
- }
- void show(void)//這個比較關鍵,把坐標轉化成8個16進制數
- {
- unsigned char lie=0x80;
- unsigned int z;
- unsigned char t;
- for( i=0;i<8;i++)
- tabel[i]=0xff;//先重置tabel,全都賦值0xff
- if(ret) t=n-1;//如果這一輪吃到了果子,那么蛇長加了一,而實
- else t=n;// 際上這一輪需要顯示的是沒加一的蛇(因為蛇頭和果子重合)
- for(i=0;i<t;i++)//具體思路略
- tabel[snake[i][1]]=tabel[snake[i][1]]^(unsigned char)pow(2,7-snake[i][0]);
- if(ret==0) tabel[apple[1]]=tabel[apple[1]]^(unsigned char)pow(2,7-apple[0]);
- if(n==max)//如果蛇長達到最大了,我們就讓全屏亮
- {
- for(i=0;i<8;i++)
- {
- tabel[i]=0;
- }
- }
- for(z=0;z<delay;z++)//這里也是使用74HC595的步驟
- {
- for(i=0;i<8;i++)
- {
- send_byte(tabel[i]);
- send_byte(lie);
- STCP=0;
- STCP=1;
- lie=_cror_ (lie,1);
- }
- if(up==0)//由于需要全程掃描按鍵是否被按下,那就在顯示過程中掃描
- button=1;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
貪吃蛇小仙峰版.zip
(148.21 KB, 下載次數: 98)
2019-1-24 22:26 上傳
點擊文件名下載附件
|