立即注冊(cè) 登錄
返回首頁(yè)

uid:71568的個(gè)人空間

日志

貪吃蛇

已有 500 次閱讀2015-1-3 20:30 | 貪吃蛇


------------------------------------------------*/
#include<reg52.h>    //包含頭文件,一般情況不需要改動(dòng),頭文件包含特殊功能寄存器的定義
#include <intrins.h> 
/*------------------------------------------------
                硬件端口定義
------------------------------------------------*/
sbit LATCH= P1^0;   //鎖存
sbit SRCLK= P1^1;      //時(shí)鐘
sbit SER  = P1^2;      //數(shù)據(jù)
sbit LATCH_B= P2^2;    //鎖存
sbit SRCLK_B= P2^1;   //時(shí)鐘
sbit SER_B= P2^0;      //鎖存                                      
sbit LED=P1^3;   //結(jié)束提示燈
//sbit key1=P3^0;   //上
//sbit key2=P3^1;   //下
//sbit key3=P3^2;   //左
//sbit key4=P3^3;      //右
//sbit key5=P3^4;   //暫停

/*------------------------------------------------
                全局變量定義
------------------------------------------------*/
unsigned char x[30],y[30];     //蛇身坐標(biāo)
unsigned char speed=10;        //控制速度變量  
unsigned char dx=0,dy=1;   //控制轉(zhuǎn)向變量,初始化為向左運(yùn)動(dòng)
bit stop_start,inverse;   //開(kāi)始/暫停標(biāo)志位,顏色顯示標(biāo)志位
bit up=1,down=1,left=1,right=1;//上下左右使能控制位
unsigned char tab[8];   //顯示緩沖數(shù)組
unsigned char  segout[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //8列掃描
/*------------------------------------------------
 uS延時(shí)函數(shù),含有輸入?yún)?shù) unsigned char t,無(wú)返回值
 unsigned char 是定義無(wú)符號(hào)字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時(shí)請(qǐng)使用匯編,大致延時(shí)
 長(zhǎng)度如下 T=tx2+5 uS 
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{   
    while(--t);
}
/*------------------------------------------------
 mS延時(shí)函數(shù),含有輸入?yún)?shù) unsigned char t,無(wú)返回值
 unsigned char 是定義無(wú)符號(hào)字符變量,其值的范圍是
 0~255 這里使用晶振12M,精確延時(shí)請(qǐng)使用匯編
------------------------------------------------*/
void DelayMs(int t) //大致延時(shí)1mS
{    
    while(t--)
    {     
    DelayUs2x(245);
DelayUs2x(245);
    }
}
/*------------------------------------------------
                發(fā)送字節(jié)程序
------------------------------------------------*/
void SendByte(unsigned char dat)
{    
  unsigned char i;        
    for(i=0;i<8;i++)
    {
    SRCLK=0;
    SER=dat&0x80;
    dat<<=1;
    SRCLK=1;
    }        
}
/*------------------------------------------------
                發(fā)送雙字節(jié)程序
     595級(jí)聯(lián),n個(gè)595,就需要發(fā)送n字節(jié)后鎖存
------------------------------------------------*/
void Send2Byte(unsigned char dat1,unsigned char dat2)
{    
    SendByte(dat1);
    SendByte(dat2);      
}
/*------------------------------------------------
                  595鎖存程序
 595級(jí)聯(lián)發(fā)送數(shù)據(jù)后,鎖存有效
------------------------------------------------*/
void Out595(void)
{
    LATCH=0;
    _nop_();
    LATCH=1;
}
/*------------------------------------------------
                發(fā)送位碼字節(jié)程序
               使用另外一片單獨(dú)595
------------------------------------------------*/
void SendSeg(unsigned char dat)
{    
unsigned char i;         
    for(i=0;i<8;i++)  //發(fā)送字節(jié)
    {
         SRCLK_B=0;
         SER_B=dat&0x80;
         dat<<=1;
         SRCLK_B=1;
    }
    LATCH_B=0;    //鎖存
    _nop_();
    LATCH_B=1;         
}  
/*--------------------------------------------------------------
按鍵掃描函數(shù)
--------------------------------------------------------------*/
void key_scan()
{
switch(P3)
{
case 0xfe: if(up)     //up
  {
  dx=-1;dy=0; //執(zhí)行向上功能
  down=0;left=1;right=1;   //向下功能失效,其他功能可用
  }     
break;
case 0xfd: if(down) //down
  {dx=1;dy=0;up=0;left=1;right=1;}     //  
break;
case 0xfb: if(left) //left
  {dx=0;dy=1;down=1;up=1;right=0;}     //
break;
case 0xf7: if(right) //right
  {dx=0;dy=-1;down=1;left=1;up=1;}     //  
break;
case 0xef:             //暫停/開(kāi)始鍵
DelayMs(10); //延時(shí)去抖
if(P3==0xef) //再次確認(rèn)按鍵是否按下
stop_start=~stop_start; //暫停/開(kāi)始標(biāo)志位取反(按一下暫停再按一下開(kāi)始)
while(P3==0xef); //等待按鍵釋放
break;
case 0xbf: 
DelayMs(10); //延時(shí)去抖
if(P3==0xbf) //再次確認(rèn)按鍵是否按下
speed+=2; //速度增大
while(P3==0xbf); //等待按鍵釋放
break;
case 0x7f: DelayMs(10); //延時(shí)去抖
if(P3==0x7f) //再次確認(rèn)按鍵是否按下
speed-=2; //速度減小
while(P3==0x7f); //等待按鍵釋放
break;
default: break;
}
}  
/*--------------------------------------------------------------
清除顯示緩沖區(qū),即清屏
--------------------------------------------------------------*/
void clr_ram(void)
{
    unsigned char i;
    for(i = 0; i < 8; i++) 
        tab[i] = 0x00;   //逐個(gè)清除數(shù)組內(nèi)容
}  
/*-------------------------------------------------------------- 
畫(huà)點(diǎn)函數(shù),擦點(diǎn)或者繪點(diǎn)
點(diǎn)陣左上角坐標(biāo)為(0, 0)    右下角坐標(biāo)為(7, 7)
橫坐標(biāo)為x:0~7        縱坐標(biāo)為y:0~7
k = 1 --繪點(diǎn)      k = 0 --擦點(diǎn) 
-------------------------------------------------------------*/   
void point1(unsigned char x, unsigned char y, bit k)
{
    if(k) tab[y] |= 0x01 << x; //保留原始點(diǎn),繪制新點(diǎn)
    else  tab[y] &= ~(0x01 << x); //保留其它點(diǎn),只擦其中一個(gè)點(diǎn)
}


/*------------------------------------------------------------
定時(shí)器0初始化
--------------------------------------------------------------*/
void T0_init(void)
{
    TMOD|= 0x01;
    TH0  = 0xf8;        //2ms
    TL0  = 0x36;
    IE  |= 0x82;
    TR0  = 1;
}
/*--------------------------------------------------------------
定時(shí)器1初始化
--------------------------------------------------------------*/
void T1_init(void)                    
{  
    TMOD|= 0x01;
    TH1  = 0x00;        //65ms
    TL1  = 0x00;
    IE  |= 0x88;
    TR1  = 1;
}
/*------------------------------------------------
                   主程序
------------------------------------------------*/
void main()
{
unsigned char i=0,foodx, foody; //食物坐標(biāo)
unsigned char num=2;            //蛇長(zhǎng)度
bit food,over;                  //食物和結(jié)束標(biāo)志位
  IT0  = 1;   //外部中斷0(即P3^2腳)選擇邊沿觸發(fā),下降沿有效
EX0  = 1;   //打開(kāi)外部中斷0
T0_init(); //定時(shí)器0初始化
T1_init(); //定時(shí)器1初始化
stop_start=0;                   //開(kāi)始/暫停標(biāo)志位置為開(kāi)始  
while(1)
{
x[0] += dx;   y[0] += dy; //根據(jù)dxdy不同的值來(lái)使蛇頭移動(dòng)
        x[0] &= 0x07; y[0] &= 0x07; //作用穿墻,x或y加到8時(shí)變?yōu)?
if(!food)                   //放置食物
        {
  again:    foodx = TL0&0x07;   //隨機(jī)取食物坐標(biāo),0~7,但不會(huì)超過(guò)7             
            foody = TH0&0x07; 
            for(i = 0; i < num; i++)
            {
                if(foodx==x[i]&&foody==y[i])  //若食物與蛇身重疊,                
goto again;  //則重放食物。
            }
// inverse=0;  //顏色標(biāo)志位置0,顯示紅色
            point1(foodx, foody, 1);          //顯示食物
            food = 1;                         //置食物標(biāo)志位
        }
if(x[0] == foodx && y[0] == foody)    //吃到食物    
        {
            num++;                            //蛇長(zhǎng)增加1節(jié)
            food = 0;                         //清食物標(biāo)志位
        }

for(;stop_start;);  //按下暫停鍵程序在此進(jìn)入死循環(huán)

// inverse=1;      //顏色標(biāo)志位置1,顯示綠色
for(i = 0; i < num; i++)              //顯示蛇身 
        point1(x[i], y[i], 1);

        point1(x[i], y[i], 0);                //清蛇尾
for(i = 1; i < num; i++)              //判斷是否自撞
        {
            if((x[0]==x[i])&&(y[0]==y[i]))
            over = 1;                         //置結(jié)束標(biāo)志位
        }
for(i=0;i<speed;i++) DelayMs(15);  //蛇運(yùn)動(dòng)速度
        
        for(i = 0; i < num; i++)              //蛇移動(dòng)蛇身
        {
            x[num-i] = x[num-i-1]; 
            y[num-i] = y[num-i-1];
        }
if(over)                      //判斷是否結(jié)束
        {
for(i=0;i<10;i++)  //LED閃5次
{  
LED=~LED;  
DelayMs(100);
}
clr_ram();                //清除屏幕
num = 2;                  //重新設(shè)定蛇長(zhǎng)
            point1(foodx, foody, 1);  //重新放置食物
            x[0] = 0; y[0] = 0;       //起點(diǎn)位置
            dx=0;dy=1;                //向左運(yùn)動(dòng)
            over = 0;  //清除結(jié)束標(biāo)志
}
}
}
/*--------------------------------------------------------------
定時(shí)器1中斷服務(wù)
--------------------------------------------------------------*/
void T1_intservice(void) interrupt 3
{
  
TH1  = 0x00;
    TL1  = 0x00;
key_scan();  
 }
/*--------------------------------------------------------------
定時(shí)器0中斷服務(wù)
--------------------------------------------------------------*/
void T0_intservice(void) interrupt 1
{
    static unsigned char n; //定義靜態(tài)變量
    TR1 = 0; //關(guān)閉定時(shí)器1
    TH0  = 0xf8;                       
    TL0  = 0x36;        //重裝初值,2ms 
SendSeg(segout[n]);    //發(fā)送列碼(相當(dāng)于數(shù)碼管中的位碼)
if(inverse)
    Send2Byte(0xff,~tab[n]);//發(fā)送點(diǎn)碼(相當(dāng)于數(shù)碼管中的段碼),顯示綠色,交換兩個(gè)量可改變顏色
    else
Send2Byte(~tab[n],0xff);//發(fā)送點(diǎn)碼(相當(dāng)于數(shù)碼管中的段碼),顯示紅色,交換兩個(gè)量可改變顏色
Out595(); //595鎖存程序
DelayMs(1);
Send2Byte(0xff,0xff);       //防止重影
Out595();
n++; if(n == 8) n = 0;      //循環(huán)掃描
    TR1 = 1; //打開(kāi)定時(shí)器1
}

 


路過(guò)

雞蛋

鮮花

握手

雷人

全部作者的其他最新日志

評(píng)論 (0 個(gè)評(píng)論)

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

Powered by 單片機(jī)教程網(wǎng)

返回頂部