|
|
一年前做的小玩意了,硬件丟失了,程序還在,以前都是寫在一個(gè)文件內(nèi),翻出來分成幾個(gè)文件,程序注釋寫的很詳細(xì),希望對(duì)初入單片機(jī)的師兄有所幫助
單片機(jī)源程序如下:
- //=================================================================================================================================================================
- //軟件功能:貪吃蛇
- //硬件描述:最小系統(tǒng)+4x(8x8點(diǎn)陣)+ (1x(HC154)+3x(74HC14D)) + 1x(HC595)
- //程序描述:74595.c中有串進(jìn)并出程序
- // delay.c中有延遲函數(shù)
- // dispaly.c中有點(diǎn)陣顯示函數(shù)
- // anjian.c中有按鍵函數(shù)
- // related.c中有初始化參數(shù)函數(shù)、游戲結(jié)束圖案函數(shù)、點(diǎn)陣顯示清除函數(shù)、糖果隨機(jī)函數(shù)、蛇顯示變化函數(shù)
- //功能概括描述:16x16點(diǎn)陣用于顯示、5個(gè)按鍵有旋轉(zhuǎn)按鍵、上、下、左、右按鍵
- // 上、下、左、右按鍵用于控制蛇上下左右移動(dòng)
- // 有轉(zhuǎn)折點(diǎn)判斷(理論上蛇可以打15折)、蛇碰壁判斷、蛇速度改變判斷
- //=================================================================================================================================================================
- #include "reg52.h" //51頭文件
- #include "intrins.h" //部分運(yùn)算符所需頭文件
- #include "74595.h" //74595程序
- #include "delay.h"
- #include "display.h"
- #include "anjian.h"
- #include "related.h"
- #define uchar unsigned char
- #define uint unsigned int
- //=================================================================================================================================================================
- //sbit Beep=P2^7; //蜂鳴器
- uint HUANCUN[16],STX,SWX,GCUNY; //緩存顯示數(shù)組,蛇頭橫坐標(biāo),蛇尾橫坐標(biāo),轉(zhuǎn)折點(diǎn)存儲(chǔ)數(shù)組,果子位置存儲(chǔ)
- uchar SSS,t,STY,SWY,GUO,CBN,GCUNX,Q,cus; //蛇方向變量,定時(shí)器計(jì)時(shí)變量,蛇頭縱坐標(biāo),蛇尾縱坐標(biāo),轉(zhuǎn)折點(diǎn)反向存儲(chǔ)數(shù)組,糖果,計(jì)時(shí)變量,隨機(jī)數(shù),蛇方向前一個(gè)狀態(tài)變量
- uchar idata ZZS[16];
- uint idata ZZD[16];
- //=================================================================================================================================================================
- void Init() //初始化
- {
- TMOD=0x01; //工作方式1
- EA=1; //CPU中斷開啟
- ET0=1; //定時(shí)器T0中斷開啟
- TH0=(65536-5000)/256; //定時(shí)5ms
- TL0=(65536-5000)%256;
- TR0=0; //定時(shí)器關(guān)閉狀態(tài)
- KS=1; //開始鍵置高電平
- // Beep=0;
- }
- //=================================================================================================================================================================
- void main()
- {
- Init();
- while(1)
- {
- Q=rand()%256; //隨機(jī)代碼放在while(1)函數(shù)中不停運(yùn)轉(zhuǎn)
- if(TR0==0){ //如果定時(shí)器在關(guān)閉狀態(tài)
- J_S(); //清除緩存
- K_S(); //各種數(shù)據(jù)初始化
- }else{
- if(GUO!=1){ //如果沒有糖果
- SUI_JI(); //調(diào)用隨機(jī)子程序
- t--; //蛇的速度加快
- CBN=t; //CBN用于保存改變后的t
- }
- }
- XIANSI(); //循環(huán)顯示函數(shù)
- }
- }
- //=================================================================================================================================================================
- void time0() interrupt 1
- {
- TH0=(65536-5000)/256;
- TL0=(65536-5000)%256;
- AN_J(); //調(diào)用按鍵子程序
- if((--CBN==0)||(cus!=SSS)){
- CBN=t; //CBN隨t的變化而變化
- SE_BH(); //調(diào)用蛇變子程序
- }
- }
- //=================================================================================================================================================================
復(fù)制代碼- #include "related.h"
- //=================================================================================================================================================================
- extern uchar SSS,t,STY,SWY,GUO,GCUNX,Q;
- extern uint HUANCUN[16],STX,SWX,GCUNY;
- extern uchar idata ZZS[16];
- extern uint idata ZZD[16];
- //=================================================================================================================================================================
- //功能描述:開始鍵按下后,初始化各種參數(shù)
- //=================================================================================================================================================================
- void K_S()
- {
- uchar i;
- if(KS==0){ //如果開始鍵按下
- QC_HC();
- SSS=2; //蛇方向向右
- t=50; //蛇初始速度
- SWY=7; //蛇尾初始縱坐標(biāo)
- STY=7; //蛇頭初始縱坐標(biāo)
- STX=0x0040; //蛇頭初始橫坐標(biāo)
- SWX=0x0100; //蛇尾初始橫坐標(biāo)
- HUANCUN[7]=0x01c0; //初始化蛇全身
- ZZS[0]=SSS; //存儲(chǔ)蛇的方向
- for(i=0;i<16;i++){
- ZZD[i]=0xffff;
- }
- GUO=0; //無糖果
- TR0=1; //定時(shí)器開啟
- }
- }
- //=================================================================================================================================================================
- //功能描述:游戲結(jié)束后顯示預(yù)設(shè)圖案
- //=================================================================================================================================================================
- void J_S() //結(jié)束子程序
- {
- QC_HC();
- HUANCUN[2]=0x0ff0; //顯示笑臉
- HUANCUN[3]=0x1008;
- HUANCUN[4]=0x2424;
- HUANCUN[5]=0x2a54;
- HUANCUN[6]=0x2004;
- HUANCUN[7]=0x2004;
- HUANCUN[8]=0x2004;
- HUANCUN[9]=0x2004;
- HUANCUN[10]=0x2244;
- HUANCUN[11]=0x2184;
- HUANCUN[12]=0x1008;
- HUANCUN[13]=0x0ff0;
- }
- //=================================================================================================================================================================
- //功能描述:16x16點(diǎn)陣顯示清除
- //=================================================================================================================================================================
- void QC_HC() //清除緩存子程序
- {
- uchar i;
- for(i=0;i<16;i++){ //緩存清零
- HUANCUN[i]=0;
- }
- }
- //=================================================================================================================================================================
- //功能說明:”糖果“隨機(jī)函數(shù)
- //程序說明:Q取0~255之間的數(shù),對(duì)應(yīng)16x16點(diǎn)陣上的256個(gè)點(diǎn)
- // Q/16取16x16點(diǎn)陣的哪一行,0x0001<<(Q%16)取16x16點(diǎn)陣的哪一列
- // Q隨機(jī)出一個(gè)數(shù)后,有可能點(diǎn)陣上的點(diǎn)是亮著的,要重新隨機(jī),直到隨機(jī)到?jīng)]亮著的點(diǎn)
- // 然后改變對(duì)應(yīng)緩存顯示數(shù)組HUANCUN[]里的數(shù)據(jù)
- // 16x16點(diǎn)陣是以左上角為原點(diǎn)的一個(gè)坐標(biāo)(不過y軸不是負(fù)的),記錄下對(duì)應(yīng)點(diǎn)的橫坐標(biāo)和縱坐標(biāo)
- // 改變“糖果”的狀態(tài)變量GUO=1,就是說當(dāng)前有“糖果”在
- //=================================================================================================================================================================
- void SUI_JI()
- {
- while(HUANCUN[Q/16]&(0x0001<<(Q%16))) //判斷隨機(jī)數(shù)對(duì)應(yīng)的點(diǎn)陣上的點(diǎn)是否是滅的狀態(tài)
- {
- Q=rand()%256; //如果是亮的,那么再隨機(jī)一次,直到隨機(jī)到滅的點(diǎn)
- }
- HUANCUN[Q/16]|=(0x0001<<(Q%16)); //讓這個(gè)點(diǎn)亮起來
- GCUNX=Q/16; //記錄該點(diǎn)的橫坐標(biāo)和縱坐標(biāo)
- GCUNY=(0x0001<<(Q%16));
- GUO=1; //記錄糖果狀態(tài)
- }
- //=================================================================================================================================================================
- //功能說明:當(dāng)蛇尾處在轉(zhuǎn)折點(diǎn)處時(shí),這個(gè)轉(zhuǎn)折點(diǎn)數(shù)據(jù)沒用了,判斷蛇還有沒有轉(zhuǎn)折點(diǎn),如果有,覆蓋掉這個(gè)轉(zhuǎn)折點(diǎn)
- // 根據(jù)改變后的轉(zhuǎn)折點(diǎn),確定蛇尾的坐標(biāo)
- //=================================================================================================================================================================
- void ZZ_X()
- {
- uchar i;
- if(ZZS[1]!=0){ //如果有第二個(gè)轉(zhuǎn)折點(diǎn)
- for(i=0;i<15;i++){ //把第一個(gè)轉(zhuǎn)折點(diǎn)覆蓋
- ZZD[i]=ZZD[i+1];
- ZZS[i]=ZZS[i+1];
- }
- }
- switch(ZZS[0]) //判斷改變后蛇的方向,而后改變蛇尾坐標(biāo)
- {
- case 1:
- SWY--;
- break;
- case 2:
- SWX>>=1;
- break;
- case 3:
- SWY++;
- break;
- case 4:
- SWX<<=1;
- break;
- }
- }
- //=================================================================================================================================================================
- //思維說明:蛇移動(dòng)是不是要判斷前面有沒有障礙物?這個(gè)障礙物有可能是蛇的身體,也有可能是糖果。還有,蛇會(huì)不會(huì)碰壁呢?
- //程序說明:根據(jù)蛇的方向(SSS)來分成4種情況,
- // 蛇頭就是一個(gè)點(diǎn),這個(gè)點(diǎn)被記錄下橫(STY)和縱坐標(biāo)(STX),再加上記錄下的方向(SSS),可以確定蛇頭的下一個(gè)位置
- // 當(dāng)SSS=1時(shí),蛇向上移動(dòng),把蛇頭橫坐標(biāo)(STX)和緩存顯示數(shù)組HUANCUN[STY-1]相與,確定該位置是否被點(diǎn)亮,為什么是STY-1呢?點(diǎn)陣第一行對(duì)應(yīng)HUANCUN[0]
- // 當(dāng)該位置沒被點(diǎn)亮?xí)r,表示蛇可以移動(dòng)上去了,把蛇頭的坐標(biāo)改變
- // 否則,把該位置的坐標(biāo)和糖果的坐標(biāo)比較,如果是糖果位置,蛇頭一樣可變。其他情況游戲結(jié)束,關(guān)定時(shí)器TR0
- // 其他3種情況分析同上
- // 蛇尾也不能忘了,一條蛇只標(biāo)蛇頭可不行
- // 如果蛇吃了糖果,那么蛇頭長了一點(diǎn),蛇尾不用變,蛇頭坐標(biāo)變后跳出函數(shù)就行了
- // 否則,就要讓蛇尾滅掉HUANCUN[SWY]&=(~SWX);
- // 再則,一條蛇可會(huì)轉(zhuǎn)彎的哦,那么必須要有轉(zhuǎn)折點(diǎn),不止一個(gè),要判斷,如果需要的話,要做改變
- //=================================================================================================================================================================
- void SE_BH() //蛇變子程序
- {
- switch(SSS)
- {
- case 1:
- if(STY>0){ //大于0是要判斷的,因?yàn)橄旅鍴UANCUN[STY-1]
- if((HUANCUN[STY-1]&STX)==0) //判斷下一個(gè)蛇坐標(biāo)是否是滅的
- STY--; //蛇頭坐標(biāo)改變
- else{
- if(((STY-1)==GCUNX)&&(STX==GCUNY)){ //否則,判斷該點(diǎn)是否是糖果點(diǎn)
- STY--; //蛇頭坐標(biāo)改變
- GUO=0; //糖果變量清零
- }else
- TR0=0; //定時(shí)器關(guān)閉
- return; //跳出
- }
- }else{
- TR0=0;
- return;
- }
- break;
- case 2:
- if((HUANCUN[STY]&(STX>>1))==0)
- STX>>=1;
- else{
- if((STY==GCUNX)&&((STX>>1)==GCUNY)){
- STX>>=1; //蛇頭橫坐標(biāo)右移一位
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- case 3:
- if((HUANCUN[STY+1]&STX)==0)
- STY++; //蛇頭縱坐標(biāo)減一位
- else{
- if(((STY+1)==GCUNX)&&(STX==GCUNY)){
- STY++;
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- case 4:
- if((HUANCUN[STY]&(STX<<1))==0)
- STX<<=1;
- else{
- if((STY==GCUNX)&&((STX<<1)==GCUNY)){
- STX<<=1;
- GUO=0;
- }else
- TR0=0;
- return;
- }
- break;
- }
- if((STX!=0)&&(STY>=0)&&(STY<16)){ //如果蛇頭沒超出邊界
- HUANCUN[STY]|=STX; //讓蛇頭亮起
- HUANCUN[SWY]&=(~SWX); //讓蛇尾滅掉
- switch(ZZS[0])
- {
- case 1:
- if(SWY!=ZZD[0])
- SWY--;
- else ZZ_X();
- break;
- case 2:
- if(SWX!=ZZD[0])
- SWX>>=1;
- else ZZ_X();
- break;
- case 3:
- if(SWY!=ZZD[0])
- SWY++;
- else ZZ_X();
- break;
- case 4:
- if(SWX!=ZZD[0])
- SWX<<=1;
- else ZZ_X();
- break;
- }
- }else{
- TR0=0;
- // return;
- }
- }
- //=================================================================================================================================================================
復(fù)制代碼
- #include "anjian.h"
- extern uchar cus,STY,SSS;
- extern uint STX;
- extern uchar idata ZZS[16];
- extern uint idata ZZD[16];
- //=================================================================================================================================================================
- //思維說明:4個(gè)按鍵控制蛇的方向,當(dāng)蛇往一個(gè)方向移動(dòng)的時(shí)候,控制蛇在這一線上的移動(dòng)方向的兩個(gè)按鍵會(huì)失效,只有兩個(gè)鍵有用
- //程序說明:SSS表示蛇方向的一個(gè)變量,有4個(gè)方向,取值范圍是1~4
- // 當(dāng)蛇的方向改變是,存儲(chǔ)轉(zhuǎn)折點(diǎn)的橫或縱坐標(biāo)放在數(shù)組ZZD[],存儲(chǔ)轉(zhuǎn)折點(diǎn)的方向存在ZZS[]
- // 蛇尾是跟著存儲(chǔ)起來的轉(zhuǎn)折點(diǎn)轉(zhuǎn)向的,一個(gè)點(diǎn)的坐標(biāo)用橫坐標(biāo)和縱坐標(biāo)兩個(gè)坐標(biāo)表示的,這里為了節(jié)省存儲(chǔ)空間,
- // 當(dāng)蛇在橫向上移動(dòng)的時(shí)候,可以只存橫坐標(biāo),為什么存橫坐標(biāo)?因?yàn)檫@個(gè)時(shí)候縱坐標(biāo)不變
- // 當(dāng)蛇在縱向上移動(dòng)的時(shí)候,可以只存縱坐標(biāo)
- //=================================================================================================================================================================
- void AN_J() //按鍵子程序
- {
- static uchar a=1,b=1,c=1,d=1; //定義4個(gè)方向鍵的狀態(tài)變量
- uchar i;
- cus=SSS; //保存蛇的方向
- if(SHANG!=a){ //比較按鍵當(dāng)前狀態(tài)和前一個(gè)狀態(tài)是否一致
- if(a==1){ //前一個(gè)狀態(tài)是否是高電平
- if((SSS!=1)&&(SSS!=3)){ //蛇的狀態(tài)是左右的時(shí)候,才生效
- SSS=1;
- }
- }
- a=SHANG; //鎖住,直到下一次按鍵按下才會(huì)再進(jìn)來
- }
- if(YOU!=b){
- if(b==1){
- if((SSS!=2)&&(SSS!=4)){
- SSS=2;
- }
- }
- b=YOU;
- }
- if(XIA!=c){
- if(c==1){
- if((SSS!=1)&&(SSS!=3)){
- SSS=3;
- }
- }
- c=XIA;
- }
- if(ZUO!=d){
- if(d==1){
- if((SSS!=2)&&(SSS!=4)){
- SSS=4;
- }
- }
- d=ZUO;
- }
- if(cus!=SSS){ //如果蛇的方向改變了
- for(i=0;i<16;i++){ //從第一個(gè)轉(zhuǎn)折點(diǎn)開始判斷
- if(ZZD[i]==0xffff){ //如果轉(zhuǎn)折點(diǎn)是0xffff,說明后面沒有轉(zhuǎn)折點(diǎn)了
- ZZS[i+1]=SSS; //把當(dāng)前蛇的方向存儲(chǔ)起來
- if((cus==1)||(cus==3)){ //如果蛇前一個(gè)方向是上下
- ZZD[i]=STY; //把轉(zhuǎn)折點(diǎn)的縱坐標(biāo)存儲(chǔ)起來
- }else ZZD[i]=STX; //否則,存橫坐標(biāo)
- break; //跳出
- }
- }
- }
- }
- //=================================================================================================================================================================
復(fù)制代碼
原理圖: 無
仿真: 無
代碼:
貪吃蛇.rar
(58.42 KB, 下載次數(shù): 101)
2020-1-21 23:21 上傳
點(diǎn)擊文件名下載附件
|
評(píng)分
-
查看全部評(píng)分
|