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

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 2492|回復(fù): 6
打印 上一主題 下一主題
收起左側(cè)

基于51板子得貪吃蛇游戲,想知道哪錯(cuò)了,謝謝

[復(fù)制鏈接]
回帖獎(jiǎng)勵(lì) 1 黑幣 回復(fù)本帖可獲得 1 黑幣獎(jiǎng)勵(lì)! 每人限 1 次
跳轉(zhuǎn)到指定樓層
樓主
本帖最后由 lynn710 于 2018-8-13 20:01 編輯

急用,多謝指正
#include"reg52.h"
#include "intrins.h"



sbit RS=P2^6; //并行的指令/數(shù)據(jù)選擇信號(hào), H數(shù)據(jù), L命令
sbit RW=P2^5; //并行讀寫選擇信號(hào), H讀, L寫
sbit E=P2^7; //并行使能端, H有效, L無效
sbit PSB=P3^2; //并/串接口選擇, H并,L串
sbit RET=P3^4; //復(fù)位, L有效
#define  LcdData P0
unsigned char Check_Busy(void);
void Lcd_WriteData(unsigned char);
unsigned char Lcd_ReadData(void);
void Lcd_WriteCmd(unsigned char);
void Lcd_PutPixel(unsigned char,unsigned char,unsigned char);
unsigned char Lcd_ReadPixel(unsigned char,unsigned char);
void Lcd_HoriLine(unsigned char,unsigned char,unsigned char Length,unsigned char Color);
void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color);
void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color);
void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color);
void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color);
void Lcd_Clear(unsigned char);
void Lcd_WriteStr(unsigned char,unsigned char,unsigned char *);
void Lcd_Reset(void);

unsigned char OSReadKey(void);
unsigned char KeyDown();                 //檢測(cè)按鍵函數(shù)
void Delay10ms(void);   //延時(shí)10ms

double Random(void);
void InitRandom(unsigned long InitVal);
void InitCpu(void);
void DrawBoardf(void);
void Drawboardt(void);
void PrintScore(void);
void PrintSpeed(void);
void GameOver(void);
void GamePlayo(void);
void GamePlayt(void);
void delay(unsigned int t);
//void Timer0Int(void) interrupt 1    ;

sbit kxuanze=P3^1;
sbit kenter=P3^3;

void delayus(unsigned int j);
void delayms(unsigned int x);
void init(void);
void lcd_wcd(unsigned char com_dat,unsigned char date);
void lcd_st(unsigned char *st);
void scankey(void);
void menu(void);
void jiemian(void);
void moshi(void);
void moshi1(void);
void moshi2(void);
void speed(void);
void Speed1(void);
void Speed2(void);
void Speed3(void);
void Speed4(void);
void game(void);




















/*************
測(cè)試LCD是否處于忙狀態(tài)
如果忙則返回0x80,否則返回0
**************/
unsigned char Lcd_CheckBusy(void)
{
    unsigned char Busy;
        LcdData=0xff;
    RS=0;
    RW=1;
    E=1;
    _nop_();
    Busy=LcdData&0x80;
    E=0;
    return Busy;
}

/*********************************
向LCD寫入字節(jié)數(shù)據(jù)
**********************************/
void Lcd_WriteData(unsigned char Data)
{  
        while(Lcd_CheckBusy());
        RS=1;
        RW=0;
        E=0;
        _nop_();  
        _nop_();
        LcdData=Data;
        E=1;
        _nop_();
        _nop_();
        E=0;
}

/***********************************
從LCD中讀出數(shù)據(jù)
************************************/
unsigned char Lcd_ReadData(void)
{
        unsigned char Temp;
        while(Lcd_CheckBusy());
        LcdData=0xff;
        RS=1;
        RW=1;
        E=1;
        _nop_();
           Temp=LcdData;
           E=0;
           return Temp;
}

/*************************************
向LCD中寫入指令代碼
**************************************/
void Lcd_WriteCmd(unsigned char CmdCode)
{  
        while(Lcd_CheckBusy());
           RS=0;
           RW=0;
           E=0;
           _nop_();  
        _nop_();
           LcdData=CmdCode;
           _nop_();
        _nop_();
           E=1;
           _nop_();  
        _nop_();
           E=0;
}



void set_postion(unsigned char x,unsigned char y)
{
unsigned char postion;
switch(x)
{
case 0:x=0x80;break;   
case 1:x=0x90;break;
case 2:x=0x88;break;
case 3:x=0x98;break;
default:break;
}
postion=x+y;
Lcd_WriteCmd(postion);
}


/*************************************
向LCD指定起始位置寫入一個(gè)字符串
*************************************/
void Lcd_WriteStr(unsigned char x,unsigned char y,unsigned char *Str)
{
        if((y>3)||(x>7))
                return;//如果指定位置不在顯示區(qū)域內(nèi),則不做任何寫入直接返回
        EA=0;
        switch(y)
        {
                case 0:
                                Lcd_WriteCmd(0x80+x);
                                break;
                case 1:
                                Lcd_WriteCmd(0x90+x);
                                break;                               
                case 2:
                                Lcd_WriteCmd(0x88+x);
                                break;
                case 3:
                                Lcd_WriteCmd(0x98+x);
                                break;
        }
        while(*Str>0)
        {  
                Lcd_WriteData(*Str);
                  Str++;     
        }
        EA=1;
}

/**************************************
為加速邏輯運(yùn)算而設(shè)置的掩碼表,這是以犧牲空間而換取時(shí)間的辦法
***************************************/
code unsigned int MaskTab[]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
                                                         0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
/***************************************
向LCD指定坐標(biāo)寫入一個(gè)象素,象素顏色有兩種,0代表白(無顯示),1代表黑(有顯示)
****************************************/
void Lcd_PutPixel(unsigned char x,unsigned char y,unsigned char Color)
{
        unsigned char z,w;
        unsigned int Temp;
        if(x>=128||y>=64)
                return;
        Color=Color%2;
        w=15-x%16;//確定對(duì)這個(gè)字的第多少位進(jìn)行操作
        x=x/16;//確定為一行上的第幾字

        if(y<32) //如果為上頁(yè)
                z=0x80;
        else     //否則如果為下頁(yè)
                z=0x88;

        y=y%32;
        EA=0;
        Lcd_WriteCmd(0x36);
        Lcd_WriteCmd(y+0x80);        //行地址
        Lcd_WriteCmd(x+z);     //列地址
        Temp=Lcd_ReadData();//先空讀一次
        Temp=(unsigned int)Lcd_ReadData()<<8;//再讀出高8位
        Temp|=(unsigned int)Lcd_ReadData();//再讀出低8位
        EA=1;
        if(Color==1) //如果寫入顏色為1
                Temp|=MaskTab[w];//在此處查表實(shí)現(xiàn)加速
        else         //如果寫入顏色為0
                Temp&=~MaskTab[w];//在此處查表實(shí)現(xiàn)加速
        EA=0;
        Lcd_WriteCmd(y+0x80);        //行地址
        Lcd_WriteCmd(x+z);     //列地址
    Lcd_WriteData(Temp>>8);//先寫入高8位,再寫入低8位
    Lcd_WriteData(Temp&0x00ff);
        Lcd_WriteCmd(0x30);
        EA=1;
}

/******************************************
從LCD指定坐標(biāo)讀取象素顏色值
*******************************************/
unsigned char Lcd_ReadPixel(unsigned char x,unsigned char y)
{
        unsigned char z,w;
        unsigned int Temp;
        x=x%128;
        y=y%64;
        w=15-x%16;//確定對(duì)這個(gè)字的第多少位進(jìn)行操作
        x=x/16;//確定為一行上的第幾字

        if(y<32) //如果為上頁(yè)
                z=0x80;
        else     //否則如果為下頁(yè)
                z=0x88;

        y=y%32;
        Lcd_WriteCmd(0x36);
        Lcd_WriteCmd(y+0x80);        //行地址
        Lcd_WriteCmd(x+z);     //列地址
        Temp=Lcd_ReadData();//先空讀一次
        Temp=(unsigned int)Lcd_ReadData()<<8;//再讀出高8位
        Temp|=(unsigned int)Lcd_ReadData();//再讀出低8位

        if((Temp&&MaskTab[w])==0)
                return 0;
        else
                return 1;
}

/***************************************
向LCD指定位置畫一條長(zhǎng)度為L(zhǎng)ength的指定顏色的水平線
****************************************/
void Lcd_HoriLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
        unsigned char i;
        if(Length==0)
                return;
        for(i=0;i<Length;i++)
        {
                Lcd_PutPixel(x+i,y,Color);
        }
}

/***************************************
向LCD指定位置畫一條長(zhǎng)度為L(zhǎng)ength的指定顏色的垂直線
****************************************/
void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
        unsigned char i;
        if(Length==0)
                return;
        for(i=0;i<Length;i++)
        {
                Lcd_PutPixel(x,y+i,Color);
        }
}

/*******************************************
向LCD指定起始坐標(biāo)和結(jié)束坐標(biāo)之間畫一條指定顏色的直線
********************************************/
void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color)
{
        unsigned int x,y;
        unsigned int d_x,d_y;//d_x=x2-x1;d_y=y2-y1;
        int err=0;
        unsigned char temp=0;
        if(y2<y1)
        {
                x=x1;
                y=y1;
                x1=x2;
                y1=y2;
                x2=x;
                y2=y;
        }
        d_y=y2-y1;
        if (d_y==0)
        {
                if (x1>x2)
                {
                        x=x1;
                        x1=x2;
                        x2=x;
                }
                for (x=x1;x<=x2;x++)
                        Lcd_PutPixel(x,y1,Color);
        }

        else
        {
                if(x2>=x1)
                {
                        temp=1;
                        d_x=x2-x1;
                }
                else
                        d_x=x1-x2;
                x=x1;
                y=y1;
                Lcd_PutPixel(x,y,1);

                if(temp&&(d_y<=d_x))
                        while(x!=x2)
                        {
                                if(err<0)
                                {
                                        x=x+1;
                                        err=err+(y2-y);
                                }
                                else
                                {
                                        x=x+1;
                                        y=y+1;
                                        err=err+(y2-y)-(x2-x);
                                }
                                Lcd_PutPixel(x,y,Color);
                        }

                else if(temp&&(d_y>d_x))
                        while(y!=y2)
                        {
                                d_x=x2-x;
                                d_y=y2-y;
                                if(err<0)
                                {
                                        x=x+1;
                                        y=y+1;
                                        err=err+d_y-d_x;
                                }
                                else
                                {
                                        y=y+1;
                                        err=err-d_x;
                                }
                                Lcd_PutPixel(x,y,Color);

                        }

                else if(!temp&&(d_y<=d_x))
                        while(x!=x2)
                        {
                                d_x=x-x2;
                                d_y=y2-y;
                                if(err<0)
                                {
                                        x=x-1;
                                        err=err+d_y;
                                }
                                else
                                {
                                        x=x-1;
                                        y=y+1;
                                        err=err+d_y-d_x;
                                }
                                Lcd_PutPixel(x,y,Color);
                        }

                else if(!temp &&(d_y>d_x))
                        while(y!=y2)
                        {
                                d_x=x-x2;
                                d_y=y2-y;
                                if(err<0)
                                {
                                        x=x-1;
                                        y=y+1;
                                        err=err+d_y-d_x;
                                }
                                else
                                {
                                        y=y+1;
                                        err=err-d_x;
                                }
                                Lcd_PutPixel(x,y,Color);
                        }
        }
}

/*******************************************
向LCD指定左上角坐標(biāo)和右下角坐標(biāo)畫一個(gè)指定顏色的矩形
********************************************/
void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color)
{
        unsigned char Temp;
        if(x0>x1)
        {
                Temp=x0;
                x0=x1;
                x1=Temp;
        }       
        if(y0>y1)
        {
                Temp=y0;
                y0=y1;
                y1=Temp;
        }
        Lcd_VertLine(x0,y0,y1-y0+1,Color);
        Lcd_VertLine(x1,y0,y1-y0+1,Color);
        Lcd_HoriLine(x0,y0,x1-x0+1,Color);
        Lcd_HoriLine(x0,y1,x1-x0+1,Color);       
}

/****************************************
對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
*****************************************/
void CircleDot(unsigned char x,unsigned char y,char xx,char yy,unsigned char Color)//內(nèi)部函數(shù),對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
{
        Lcd_PutPixel((x+yy),(y+xx),Color);//第 1 個(gè) 8 分圓
        Lcd_PutPixel((x+xx),(y+yy),Color);//第 2 個(gè) 8 分圓
        Lcd_PutPixel((x-xx),(y+yy),Color);//第 3 個(gè) 8 分圓
        Lcd_PutPixel((x-yy),(y+xx),Color);//第 4 個(gè) 8 分圓
        Lcd_PutPixel((x-yy),(y-xx),Color);//第 5 個(gè) 8 分圓
        Lcd_PutPixel((x-xx),(y-yy),Color);//第 6 個(gè) 8 分圓
        Lcd_PutPixel((x+xx),(y-yy),Color);//第 7 個(gè) 8 分圓
        Lcd_PutPixel((x+yy),(y-xx),Color);//第 8 個(gè) 8 分圓
}

/******************************************
向LCD指定圓心坐標(biāo)畫一個(gè)半徑為r的指定顏色的圓
*******************************************/
void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color)//中點(diǎn)法畫圓
{//中點(diǎn)法畫圓
        unsigned char xx,yy;
        char deltax,deltay,d;
        xx=0;
        yy=r;
        deltax=3;
        deltay=2-r-r;
        d=1-r;
        CircleDot(x,y,xx,yy,Color);//對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
        while (xx<yy)
        {
                if (d<0)
                {
                        d+=deltax;
                        deltax+=2;
                        xx++;
                }
                else
                {
                        d+=deltax+deltay;
                        deltax+=2;
                        deltay+=2;
                        xx++;
                        yy--;
                }
                CircleDot(x,y,xx,yy,Color);//對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
        }
}

/*****************************************
清除Lcd全屏,如果清除模式Mode為0,則為全屏清除為顏色0(無任何顯示)
否則為全屏清除為顏色1(全屏填充顯示)
******************************************/
void Lcd_Clear(unsigned char Mode)
{
        unsigned char x,y,ii;
        unsigned char Temp;
        if(Mode%2==0)
                Temp=0x00;
        else
                Temp=0xff;
        Lcd_WriteCmd(0x36);//擴(kuò)充指令 繪圖顯示
        for(ii=0;ii<9;ii+=8)   
                for(y=0;y<0x20;y++)     
                        for(x=0;x<8;x++)
                        {        
                                EA=0;
                                Lcd_WriteCmd(y+0x80);        //行地址
                                Lcd_WriteCmd(x+0x80+ii);     //列地址     
                                Lcd_WriteData(Temp); //寫數(shù)據(jù) D15-D8
                                Lcd_WriteData(Temp); //寫數(shù)據(jù) D7-D0
                                EA=1;
                        }
        Lcd_WriteCmd(0x30);
}

/****************************************
LCD初始化
*****************************************/
void Lcd_Reset(void)
{  
        PSB=1;
        Lcd_WriteCmd(0x30);       //選擇基本指令集
        Lcd_WriteCmd(0x0c);       //開顯示(無游標(biāo)、不反白)
        Lcd_WriteCmd(0x01);       //清除顯示,并且設(shè)定地址指針為00H
        Lcd_WriteCmd(0x06);       //指定在資料的讀取及寫入時(shí),設(shè)定游標(biāo)的移動(dòng)方向及指定顯示的移位
}


































#define OS_LONG_EYK_EN 1//如果應(yīng)用中需要處理長(zhǎng)按鍵動(dòng)作,則定義為1,否則定義為0(如果應(yīng)用中不需要處理長(zhǎng)按動(dòng)作,則建議定義為0,以節(jié)省代碼空間)
#define GPIO_KEY P1

unsigned char KeyValue;//用來存放讀取到的鍵值
unsigned char code DIG_CODE[17]={
0,0,0,0,0,5,0,0,6,0,4,0,0,3,0,0,0};




void Delay10ms(void)   //誤差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
/***********************************************
功能說明:按鍵驅(qū)動(dòng)掃描
入口參數(shù):無
出口參數(shù):掃描一次鍵盤以獲得按鍵句柄
注:交OSReadKey()函數(shù)調(diào)用
***********************************************/
unsigned char KeyDown(void)
{
        char a=0;
        GPIO_KEY=0x0f;
        if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
        {
                Delay10ms();//延時(shí)10ms進(jìn)行消抖
                if(GPIO_KEY!=0x0f)//再次檢測(cè)鍵盤是否按下
                {
                       
                        //測(cè)試列
                        GPIO_KEY=0X0F;
                        switch(GPIO_KEY)
                        {
                                case(0X07):        KeyValue=0;break;
                                case(0X0b):        KeyValue=1;break;
                                case(0X0d): KeyValue=2;break;
                                case(0X0e):        KeyValue=3;break;
                        }
                        //測(cè)試行
                        GPIO_KEY=0XF0;
                        switch(GPIO_KEY)
                        {
                                case(0X70):        KeyValue=KeyValue;break;
                                case(0Xb0):        KeyValue=KeyValue+4;break;
                                case(0Xd0): KeyValue=KeyValue+8;break;
                                case(0Xe0):        KeyValue=KeyValue+12;break;
                        }
                        while((a<50)&&(GPIO_KEY!=0xf0))         //檢測(cè)按鍵松手檢測(cè)
                        {
                                Delay10ms();
                                a++;
                        }
                }
        }

        return KeyValue;          
}
/**********************************************
功能說明:讀取按鍵動(dòng)作
入口參數(shù):無
出口參數(shù):返回按鍵動(dòng)作
注意:
沒有按鍵動(dòng)作,則返回0,
使用矩陣按鍵:向上S12;向下S6;向左S12;向右S9;
***********************************************/
unsigned char OSReadKey(void)
{
        static unsigned char KeyEventCnt=0;
        static unsigned char KeySampleCnt=0;
        static unsigned char KeyBuffer=0;
#define SHORT_ON_DITHERING_COUNTER 3//定義短按按下去抖時(shí)間
#define SHORT_OFF_DITHERING_COUNTER 3//定義短按松開去抖時(shí)間,一般與短按按下去抖時(shí)間相同

#if OS_LONG_KEY_EN>0
        static unsigned int LongKeySampleCnt=0;
        #define LONG_ON_DITHERING_COUNTER 250//定義長(zhǎng)按按下確認(rèn)需要的時(shí)間,如果是每1MS調(diào)用一次OSReadKey(),則1000意味著這個(gè)時(shí)間為1S
        #define LONG_OFF_DITHERING_COUNTER 3//定義長(zhǎng)按松開去抖時(shí)間,一般和短按去抖時(shí)間相同
#endif
        unsigned char KeyTemp;
        KeyTemp=DIG_CODE[KeyDown()];
        switch(KeyEventCnt)
        {
                case 0:
                        if(KeyTemp!=0)
                        {
                                KeySampleCnt=0;
                                KeyBuffer=KeyTemp;
                                KeyEventCnt=1;     
                        }
                        return 0;//no key on,return 0
                        break;
               
                #if OS_LONG_KEY_EN>0       
                case 1:
                        if(KeyTemp!=KeyBuffer)
                        {
                                KeyEventCnt=0;
                                return 0;//is dithering,return 0
                        }
                        else
                        {
                                if(++KeySampleCnt>SHORT_ON_DITHERING_COUNTER)
                                {
                                        KeySampleCnt=0;
                                        KeyEventCnt=2;
                                        LongKeySampleCnt=0;
                                        return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
                                }
                                else
                                        return 0;//not sure that key on,return 0                 
                        }
                        break;
                               
                case 2:
                        if(++LongKeySampleCnt>LONG_ON_DITHERING_COUNTER)
                        {
                                KeySampleCnt=0;
                                KeyEventCnt=3;
                                return ((KeyBuffer-1)<<2)+2; //sure that key long on,return (KeyBuffer-1)<<2+2
                        }
                        else
                        {
                                if(KeyTemp!=KeyBuffer)
                                {
                                        if(++KeySampleCnt>SHORT_OFF_DITHERING_COUNTER)
                                        {
                                                KeyEventCnt=0;
                                                return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
                                        }
                                        else
                                                return 0;
                                }
                                else
                                {
                                        KeySampleCnt=0;
                                        return 0;
                                }
                        }
                        break;
               
                case 3:
                        if(KeyTemp!=KeyBuffer)
                        {
                                if(++KeySampleCnt>LONG_OFF_DITHERING_COUNTER)
                                {
                                        KeyEventCnt=0;
                                        return ((KeyBuffer-1)<<2)+4;  //after long key on turn to off,(KeyBuffer-1)<<2+4
                                }
                                else
                                        return 0;
                        }
                        else
                        {
                                KeySampleCnt=0;
                                return 0;
                        }
                        break;
               
                #else
                case 1:
                        if(KeyTemp!=KeyBuffer)
                        {
                                KeyEventCnt=0;
                                return 0;//is dithering,return 0
                        }
                        else
                        {
                                if(++KeySampleCnt>=SHORT_ON_DITHERING_COUNTER)
                                {
                                        KeySampleCnt=0;
                                        KeyEventCnt=2;
                                        return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
                                }
                                else
                                        return 0;//not sure that key on,return 0                 
                        }
                        break;
                               
                case 2:
                        if(KeyTemp!=KeyBuffer)
                        {
                                if(++KeySampleCnt>=SHORT_OFF_DITHERING_COUNTER)
                                {
                                        KeyEventCnt=0;
                                        return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
                                }
                                else
                                        return 0;
                        }
                        else
                        {
                                KeySampleCnt=0;
                                return 0;
                        }
                        break;
                #endif

                default:break;
        }
        return 0;
}




































#define uchar unsigned char
#define uint unsigned int

static unsigned long Seed = 1;
#define A 48271L
#define M 2147483647L
#define Q (M / A)
#define R (M % A)




void delay(unsigned int t)
{  
unsigned int i,j;
for(i=0;i<t;i++)
        for(j=0;j<10;j++);   
}


/************************************
偽隨機(jī)數(shù)發(fā)生器
*************************************/
double Random(void)
{
long TmpSeed;
TmpSeed=A*(Seed%Q)-R*(Seed/Q);
if(TmpSeed>=0)
        Seed=TmpSeed;
else
        Seed=TmpSeed+M;
return (double)Seed/M;
}

/**************************************
為偽隨機(jī)數(shù)發(fā)生器播種
***************************************/
void InitRandom(unsigned long InitVal)
{
Seed=InitVal;
}

/*********************************
初始化MPU
**********************************/
void InitCpu(void)
{
TMOD=0x01;
TH0=0;
TL0=0;
TR0=1;
ET0=1;
EA=1;
}

#define N 25
struct Food
{
unsigned char x;
unsigned char y;
unsigned char yes;
}food;//食物結(jié)構(gòu)體
struct Snake
{
unsigned char x[N];
unsigned char y[N];
unsigned char node;
unsigned char direction;
unsigned char life;
}snake;//蛇結(jié)構(gòu)體

unsigned char Flag=0;
unsigned char Score=0;
unsigned char Speed;                   //speed越大,速度越慢
unsigned char KeyBuffer=0;
#define FUNC 1                                   //(P3^1)表示級(jí)別
#define UP 2                                   //(P3^3)表示左
#define DOWN 3                                   //(P3^5)表示右
#define LEFT 4                                   //(P3^4)表示下
#define RIGHT 5                                   //(P3^2)表示上
#define PASSSCORE 20                   //預(yù)定義過關(guān)成績(jī)
void Timer0Int(void) interrupt 1
{
switch(OSReadKey())
{
        case 5:
                        KeyBuffer=FUNC;                                                  //表示級(jí)別
                        /*if(++Speed>=10)
                                Speed=1;
                           Flag|=1<<1;//速度變化標(biāo)志置1*/
                        break;
        case 21:
                        KeyBuffer=DOWN;                                                 //表示右
                        /*if(snake.direction!=2)
                                snake.direction=1;*/
                        break;
        case 13:
                        KeyBuffer=UP;                                                 //表示左
                        /*if(snake.direction!=1)
                                snake.direction=2;*/
                        break;
        case 9:
                        KeyBuffer=RIGHT;                                         //表示上
                        /*if(snake.direction!=4)
                                snake.direction=3;*/
                        break;
           case 17:
                        KeyBuffer=LEFT;                                                 //表示下
                        /*if(snake.direction!=3)
                                snake.direction=4;*/
                        break;
        default:
                        break;
}
}

/******************************
畫墻壁,初始化界面
*******************************/
void DrawBoardf(void)
{
unsigned char n;
for(n=0;n<31;n++)
{
        Lcd_Rectangle(3*n,0,3*n+2,2,1);
        Lcd_Rectangle(3*n,60,3*n+2,62,1);
}
for(n=0;n<21;n++)
{
        Lcd_Rectangle(0,3*n,2,3*n+2,1);
        Lcd_Rectangle(90,3*n,92,3*n+2,1);               
}
Lcd_HoriLine(93,31,35,1);
Lcd_HoriLine(93,63,35,1);
}





void Drawboardt(void)
{
unsigned char n;
for(n=0;n<21;n++)
{
        Lcd_Rectangle(0,3*n,2,3*n+2,1);
        Lcd_Rectangle(90,3*n,92,3*n+2,1);               
}
Lcd_HoriLine(93,31,35,1);
Lcd_HoriLine(93,63,35,1);
}


/***************************
打印成績(jī)
****************************/
void PrintScore(void)
{
unsigned char Str[3];                                          
Lcd_WriteStr(6,0,"成績(jī)");
Str[0]=(Score/10)|0x30;//十位
Str[1]=(Score%10)|0x30;//個(gè)位
Str[2]=0;                                          
Lcd_WriteStr(7,1,Str);
}

/********************************
打印速度級(jí)別
*********************************/
void PrintSpeed(void)
{
unsigned char Str[2];
Lcd_WriteStr(6,2,"級(jí)別");
Str[0]=Speed|0x30;
Str[1]=0;
Lcd_WriteStr(7,3,Str);
}

/***********************************
游戲結(jié)束處理
************************************/
void GameOver(void)
{
unsigned char n;
Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱出食物
for(n=1;n<snake.node;n++)
{
        Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,0);//消隱食物,蛇頭已到墻壁內(nèi),故不用消去               
}
if(snake.life==0)//如果蛇還活著
        Lcd_WriteStr(2,1,"過關(guān)");
else             //如果蛇死了
        Lcd_WriteStr(2,1,"輸了");
Lcd_WriteStr(1,2,"游戲結(jié)束");
}

/********************************
游戲的具體過程,也是貪吃蛇算法的關(guān)鍵部分
*********************************/
void GamePlayo(void)
{
unsigned char n;
InitRandom(TL0);
food.yes=1;//1表示需要出現(xiàn)新事物,0表示已經(jīng)存在食物尚未吃掉
snake.life=0;//表示蛇還活著
snake.direction=DOWN;
snake.x[0]=6;snake.y[0]=6;
snake.x[1]=3;snake.y[1]=6;
snake.node=2;
PrintScore();
PrintSpeed();
while(1)
{
        if(food.yes==1)
        {
                while(1)
                {
                        food.x=Random()*85+3;
                        food.y=Random()*55+3;//獲得隨機(jī)數(shù)

                        while(food.x%3!=0)
                                food.x++;
                        while(food.y%3!=0)
                                food.y++;
                    for(n=0;n<snake.node;n++)//判斷產(chǎn)生的食物坐標(biāo)是否和蛇身重合
                        {
                                if((food.x==snake.x[n])&&(food.y==snake.y[n]))
                                        break;
                        }
                        if(n==snake.node)
                        {
                                food.yes=0;
                                break;//產(chǎn)生有效的食物坐標(biāo)
                        }
                }
        }
        if(food.yes==0)
        {
                Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
        }       
        for(n=snake.node-1;n>0;n--)
        {
                snake.x[n]=snake.x[n-1];
                snake.y[n]=snake.y[n-1];
        }
        switch(snake.direction)
        {
                case DOWN:snake.x[0]+=3;break;
                case UP:snake.x[0]-=3;break;
                case RIGHT:snake.y[0]-=3;break;
                case LEFT:snake.y[0]+=3;break;
                default:break;
        }
        for(n=3;n<snake.node;n++)//從第三節(jié)開始判斷蛇頭是否咬到自己
        {
                if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
                {
                        GameOver();
                        snake.life=1;
                        break;
                }
        }
        if(snake.x[0]<3||snake.x[0]>=90||snake.y[0]<3||snake.y[0]>=60)//判蛇頭是否撞到墻壁
        {
                GameOver();
                snake.life=1;
        }
        if(snake.life==1)
                break;//蛇死,則跳出while(1)循環(huán)
        if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
        {
                Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱食物
                snake.x[snake.node]=200;
                snake.y[snake.node]=200;//產(chǎn)生蛇新的節(jié)坐標(biāo)先放在看不見的位置
                snake.node++;//蛇節(jié)數(shù)加1
                food.yes=1;//食物標(biāo)志置1
                if(++Score>=PASSSCORE)
                {
                        PrintScore();
                        GameOver();
                        break;
                }
                PrintScore();
        }
        for(n=0;n<snake.node;n++)
        {
                Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
        }//根據(jù)蛇的節(jié)數(shù)畫出蛇
        delay(Speed*1000);          //調(diào)速
        delay(Speed*1000);
        Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0);
        switch(KeyBuffer)
        {
                case FUNC:
                                KeyBuffer=0;
                                if(++Speed>=10)
                                        Speed=1;
                                   PrintSpeed();
                                break;
                case DOWN:
                                KeyBuffer=0;
                                if(snake.direction!=UP)
                                        snake.direction=DOWN;
                                break;
                case UP:
                                KeyBuffer=0;
                                if(snake.direction!=DOWN)
                                        snake.direction=UP;
                                break;
                case RIGHT:
                                KeyBuffer=0;
                                if(snake.direction!=LEFT)
                                        snake.direction=RIGHT;
                                break;
                   case LEFT:
                                KeyBuffer=0;
                                if(snake.direction!=RIGHT)
                                        snake.direction=LEFT;
                                break;
                default:
                                break;
        }                       
}//結(jié)束while(1)
}


void GamePlayt(void)
{
unsigned char n;
InitRandom(TL0);
food.yes=1;//1表示需要出現(xiàn)新事物,0表示已經(jīng)存在食物尚未吃掉
snake.life=0;//表示蛇還活著
snake.direction=DOWN;
snake.x[0]=6;snake.y[0]=6;
snake.x[1]=3;snake.y[1]=6;
snake.node=2;
PrintScore();
PrintSpeed();
while(1)
{
        if(food.yes==1)
        {
                while(1)
                {
                        food.x=Random()*85+3;
                        food.y=Random()*55+3;//獲得隨機(jī)數(shù)

                        while(food.x%3!=0)
                                food.x++;
                        while(food.y%3!=0)
                                food.y++;
                    for(n=0;n<snake.node;n++)//判斷產(chǎn)生的食物坐標(biāo)是否和蛇身重合
                        {
                                if((food.x==snake.x[n])&&(food.y==snake.y[n]))
                                        break;
                        }
                        if(n==snake.node)
                        {
                                food.yes=0;
                                break;//產(chǎn)生有效的食物坐標(biāo)
                        }
                }
        }
        if(food.yes==0)
        {
                Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
        }       
        for(n=snake.node-1;n>0;n--)
        {
                snake.x[n]=snake.x[n-1];
                snake.y[n]=snake.y[n-1];
        }
        switch(snake.direction)
        {
                case DOWN:snake.x[0]+=3;break;
                case UP:snake.x[0]-=3;break;
                case RIGHT:snake.y[0]-=3;break;
                case LEFT:snake.y[0]+=3;break;
                default:break;
        }
        for(n=3;n<snake.node;n++)//從第三節(jié)開始判斷蛇頭是否咬到自己
        {
                if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
                {
                        GameOver();
                        snake.life=1;
                        break;
                }
        }







        if(snake.x[0]<3||snake.x[0]>=90)//判蛇頭是否撞到墻壁
        {
                GameOver();
                snake.life=1;
        }
        if(snake.life==1)
                break;//蛇死,則跳出while(1)循環(huán)

        if(snake.y[0]<3||snake.y[0]>=60)          
        {  if(snake.y[0]<3)
           snake.y[0]=59;
//                    for(n=0;n<snake.node;n++)
//                {
//                        Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
//                }//根據(jù)蛇的節(jié)數(shù)畫出蛇
           if(snake.y[0]>=60)
           snake.y[0]=3;
//                  for(n=0;n<snake.node;n++)
//                {
//                        Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
//                }//根據(jù)蛇的節(jié)數(shù)畫出蛇
//               
       
        }
        if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
        {
                Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱食物
                snake.x[snake.node]=200;
                snake.y[snake.node]=200;//產(chǎn)生蛇新的節(jié)坐標(biāo)先放在看不見的位置
                snake.node++;//蛇節(jié)數(shù)加1
                food.yes=1;//食物標(biāo)志置1
                if(++Score>=PASSSCORE)
                {
                        PrintScore();
                        GameOver();
                        break;
                }
                PrintScore();
        }
        for(n=0;n<snake.node;n++)
        {
                Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
        }//根據(jù)蛇的節(jié)數(shù)畫出蛇
        delay(Speed*1000);          //調(diào)速
        delay(Speed*1000);
        Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0);
        switch(KeyBuffer)
        {
                case FUNC:
                                KeyBuffer=0;
                                if(++Speed>=10)
                                        Speed=1;
                                   PrintSpeed();
                                break;
                case DOWN:
                                KeyBuffer=0;
                                if(snake.direction!=UP)
                                        snake.direction=DOWN;
                                break;
                case UP:
                                KeyBuffer=0;
                                if(snake.direction!=DOWN)
                                        snake.direction=UP;
                                break;
                case RIGHT:
                                KeyBuffer=0;
                                if(snake.direction!=LEFT)
                                        snake.direction=RIGHT;
                                break;
                   case LEFT:
                                KeyBuffer=0;
                                if(snake.direction!=RIGHT)
                                        snake.direction=LEFT;
                                break;
                default:
                                break;
        }                       
}//結(jié)束while(1)
}



























unsigned char flag,flag1,s1num;




void delayus(unsigned int j)
{
unsigned char i;
for(i=j;i>0;i--);
}

void delayms(unsigned int x)
{
unsigned char i,j;
for(i=x;i>0;i--)
for(j=110;j>0;j--);
}



void init(void)
{
PSB=1;
Lcd_WriteCmd(0x01);
delayms(5);
Lcd_WriteCmd(0x30);
delayms(5);
Lcd_WriteCmd(0x0c);
delayms(5);
}



void scankey(void)
{
        if(kxuanze==0)  //選擇鍵
                {
                delayms(10);
                if(kxuanze==0)                   //如果S1確定按下
                {s1num++;                         //變量加一
                        while(!kxuanze);                         //等待按鍵松開
                        if(s1num==1)                  //等待按鍵松開
                        {
                        set_postion(0,4);           //一行三列(第一菜單的界面)
                        Lcd_WriteCmd(0x0f);                //光標(biāo)閃爍
                        }
                        }
                        if(s1num==2)                         //變量為2
                        {
                        set_postion(1,2);                 //二行三列
                        Lcd_WriteCmd(0x0f);                 //光標(biāo)閃爍
                        }
                        if(s1num==3)                         //變量為3
                        {
                        set_postion(2,2);
                        Lcd_WriteCmd(0x0f);
                        }
                        if(s1num==4)
                        {
                        s1num=0;
                        }
                        }
                        if(s1num!=0)   //如果slnum不等于0,目的是為了讓S1鍵起作用后S2鍵才發(fā)揮相應(yīng)的作用
                        {
                                if(kenter==0)         //如果S2按下(確定鍵)
                                {
                                delayms(10);   //延時(shí)消抖
                                if(kenter==0)                   //如果S2(確定鍵)確實(shí)按下
                                        {
                                        ++flag;                         //flag自加1,設(shè)置變量的目的是為了方便設(shè)置子菜單中的下一級(jí)菜單
                                        while(!kenter);                  //等待按鍵松開
                                        if((s1num==1)&&(flag==1))        //與選擇鍵中選中的相應(yīng)欄目對(duì)應(yīng)
                                                {
                                                flag1=1;
                                                s1num=0;
                                                Lcd_WriteCmd(0x01);         //清屏
                                                delayms(5);
                                                Lcd_WriteCmd(0x0f);
                                                delayms(5);                          //目的為了當(dāng)進(jìn)入父菜單后的子菜單,S1鍵能發(fā)揮作用
                                                game ();
                                                }
                                                }
                                        if((s1num==2)&&(flag==1))
                                                { flag1=1;
                                                s1num=0;
                                                Lcd_WriteCmd(0x01);         //清屏
                                                delayms(5);
                                                Lcd_WriteCmd(0x0f);
                                                delayms(5);
                                                speed();                          //目的為了當(dāng)進(jìn)入父菜單后的子菜單,S1鍵能發(fā)揮作用
                                                }
                                        if((s1num==1)&&(flag==2))  //如果變量為2.,進(jìn)入子菜單的下一級(jí)菜單,下s1num==1,否則會(huì)進(jìn)入誤操作
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                Speed1();
                                                }
                                        if((s1num==2)&&(flag==2))  //if((s1num==2)&&(flag==2)&&(flag==1))
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                Speed2();
                                                }
                                        if((s1num==3)&&(flag==2))
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                Speed3();
                                                }
                                        if((s1num==4)&&(flag==2))
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                Speed4();
                                                }
                                        if((s1num==3)&&(flag==1))
                                                {
                                                flag1=1;
                                                s1num=0;                          //目的為了當(dāng)進(jìn)入父菜單后的子菜單,S1鍵能發(fā)揮作用
                                                Lcd_WriteCmd(0x01);         //清屏
                                                delayms(5);
                                                Lcd_WriteCmd(0x0f);
                                                delayms(5);
                                                moshi();
                                                }
                                        if((s1num==1)&&(flag==2))
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                moshi1();
                                                }
                                        if((s1num==2)&&(flag==2))
                                                {
                                                Lcd_WriteCmd(0x0C);
                                                delayms(5);
                                                Lcd_WriteCmd(0x01);
                                                delayms(5);
                                                moshi2();
                                                }
                                        if(s1num==4)
                                                {
                                                s1num=0;
                                                }
                                        if(flag==3)
                                                {
                                                flag=0;
                                                }
                                        }
                                }
                       
                       
       
}






void jiemian(void)
{
Lcd_WriteStr(0,1,"Welcome to");
Lcd_WriteStr(2,2,"貪吃蛇");
                                          
delayms(20000);
Lcd_WriteCmd(0x01);
}

void menu(void)
{
Lcd_WriteStr(0,1,"開始游戲");
Lcd_WriteStr(1,1,"速度選擇");
Lcd_WriteStr(2,1,"模式設(shè)置");

}




void speed(void)
{
Lcd_WriteStr(0,1,"Speed1");

Lcd_WriteStr(1,1,"Speed2");       

Lcd_WriteStr(2,1,"Speed3");       

Lcd_WriteStr(3,1,"Speed4");                                          

}




void moshi(void)
{
Lcd_WriteStr(0,1,"mosho1");       


Lcd_WriteStr(1,1,"moshi2");                                                  

}



void moshi1(void)
{
unsigned char moshi;
moshi=1;
void Drawboardo();
void GamePlayf();
}


void moshi2(void)
{
unsigned char moshi;
moshi=2;
void Drawboardt();
void GamePlayt();
}



void Speed1(void)
{
unsigned char Speed=1;
}                                                          



                                                       

void Speed2(void)
{
unsigned char Speed=2;
}                                                          






void Speed3(void)
{
unsigned char Speed=3;
                                          
}                                                          





void Speed4(void)
{
unsigned char Speed=4;
}                                                          



void game(void)
{

        InitCpu();//初始化CPU
        Lcd_Reset(); //初始化LCD屏
        //Lcd_WriteStr(2,1,"Welcome");
        delay(5000);
        Lcd_WriteCmd(0x01);   //清除顯示,并且設(shè)定地址指針為00H
        Lcd_Clear(0);//清屏
        switch(Speed)
        {
         case '1':
         Speed1();
         break;
         case '2':
         Speed2();
         break;
         case '3':
         Speed3();
         break;
         case '4':
         Speed4();
         break;
         default:
         Speed4();

        }
        switch(moshi)
        {
         case '1':
         moshi1();
         break;
         case '2':
         moshi2;
         break;
         default:
         moshi2();       
        }
        GameOver();//游戲結(jié)束

}



IMG_20180813_195553.jpg (123.35 KB, 下載次數(shù): 24)

題目要求

題目要求

1534161529241.jpg (2.61 MB, 下載次數(shù): 23)

1534161529241.jpg

tanchishe.zip

59.33 KB, 下載次數(shù): 8

多c多h版

tanchishe.zip

30.28 KB, 下載次數(shù): 6

一個(gè)函數(shù)版

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

使用道具 舉報(bào)

沙發(fā)
ID:155507 發(fā)表于 2018-8-13 23:34 | 只看該作者
少了這個(gè)

#define OS_LONG_EYK_EN 1 //如果應(yīng)用中需要處理長(zhǎng)按鍵動(dòng)作,則定義為1,否則定義為0(如果應(yīng)用中不需要處理長(zhǎng)按動(dòng)作,則建議定義為0,以節(jié)省代碼空間)
#define GPIO_KEY P1

回復(fù)

使用道具 舉報(bào)

板凳
ID:377361 發(fā)表于 2018-8-14 15:16 | 只看該作者
angmall 發(fā)表于 2018-8-13 23:34
少了這個(gè)

#define OS_LONG_EYK_EN 1 //如果應(yīng)用中需要處理長(zhǎng)按鍵動(dòng)作,則定義為1,否則定義為0(如果應(yīng) ...

我加了還是那個(gè)錯(cuò)
回復(fù)

使用道具 舉報(bào)

地板
ID:155507 發(fā)表于 2018-8-14 18:15 | 只看該作者
這個(gè)試試

#define OS_LONG_KEY_EN 1
回復(fù)

使用道具 舉報(bào)

5#
ID:377361 發(fā)表于 2018-8-15 02:09 | 只看該作者
angmall 發(fā)表于 2018-8-14 18:15
這個(gè)試試

#define OS_LONG_KEY_EN 1

大神,沒有錯(cuò)了,但是單片機(jī)運(yùn)行好像卡住了,我一直按復(fù)位鍵前面的部分功能才可能好用,后面的一直用不了,但我各功能分開檢測(cè)得時(shí)候是都好用得
回復(fù)

使用道具 舉報(bào)

6#
ID:377361 發(fā)表于 2018-8-15 02:35 | 只看該作者
#include"reg52.h"
#include "intrins.h"
sbit RS=P2^6; //并行的指令/數(shù)據(jù)選擇信號(hào), H數(shù)據(jù), L命令
sbit RW=P2^5; //并行讀寫選擇信號(hào), H讀, L寫
sbit E=P2^7; //并行使能端, H有效, L無效
sbit PSB=P3^2; //并/串接口選擇, H并,L串
sbit RET=P3^4; //復(fù)位, L有效
sbit kxuanze=P3^1;
sbit kenter=P3^3;
#define  LcdData P0
#define N 25
unsigned char moshiceshi;
unsigned char flag,s1num;
#define OS_LONG_EYK_EN   1          //如果應(yīng)用中需要處理長(zhǎng)按鍵動(dòng)作,則定義為1,否則定義為0(如果應(yīng)用中不需要處理長(zhǎng)按動(dòng)作,則建議定義為0,以節(jié)省代碼空間)
#define GPIO_KEY P1
unsigned char KeyValue;//用來存放讀取到的鍵值
unsigned char code DIG_CODE[17]={
0,0,0,0,0,5,0,0,6,0,4,0,0,3,0,0,0};
#define uchar unsigned char
#define uint unsigned int
static unsigned long Seed = 1;
#define A 48271L
#define M 2147483647L
#define Q (M / A)
#define R (M % A)
struct Food
{
unsigned char x;
unsigned char y;
unsigned char yes;
}food;//食物結(jié)構(gòu)體
struct Snake
{
unsigned char x[N];
unsigned char y[N];
unsigned char node;
unsigned char direction;
unsigned char life;
}snake;//蛇結(jié)構(gòu)體
unsigned char Flag_gamedisplay=0;
unsigned char Score=0;
unsigned char Speed_tiaosu;     //speed越大,速度越慢
unsigned char KeyBuffer=0;
#define FUNC 1       //(P3^1)表示級(jí)別
#define UP 2       //(P3^3)表示左
#define DOWN 3       //(P3^5)表示右
#define LEFT 4       //(P3^4)表示下
#define RIGHT 5       //(P3^2)表示上
#define PASSSCORE 20     //預(yù)定義過關(guān)成績(jī)

void Lcd_WriteData(unsigned char);
unsigned char Check_Busy(void);
unsigned char Lcd_ReadData(void);
void Lcd_WriteCmd(unsigned char);
void Lcd_PutPixel(unsigned char,unsigned char,unsigned char);
//unsigned char Lcd_ReadPixel(unsigned char,unsigned char);
void Lcd_HoriLine(unsigned char,unsigned char,unsigned char Length,unsigned char Color);
void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color);
void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color);
void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color);
void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color);
void Lcd_Clear(unsigned char);
void Lcd_WriteStr(unsigned char,unsigned char,unsigned char *);
void Lcd_Reset(void);
unsigned char OSReadKey(void);
unsigned char KeyDown();   //檢測(cè)按鍵函數(shù)
void Delay10ms(void);   //延時(shí)10ms
double Random(void);
void InitRandom(unsigned long InitVal);
void InitCpu(void);
void DrawBoardf();
void Drawboardt(void);
void PrintScore(void);
void PrintSpeed(void);
void GameOver(void);
void Gameplayt(void);
void GamePlayf(void);
void delay(unsigned int t);
void delayus(unsigned int j);
void lcd_st(unsigned char *st);
void scankey(void);
void moshi(void);
void zhujiemian(void);
unsigned char moshi1(void);
unsigned char moshi2(void);
void speed(void);
void Speed1(void);
void Speed2(void);
void Speed3(void);
void Speed4(void);
void game(void);

void main()
{
Lcd_Reset();
Lcd_WriteStr(0,0,"Welcome");
Lcd_WriteStr(2,2,"貪吃蛇");
delay(20000000);
zhujiemian();
while(1)
{
  scankey();
}
}

/*************
測(cè)試LCD是否處于忙狀態(tài)
如果忙則返回0x80,否則返回0
**************/
unsigned char Lcd_CheckBusy(void)
{
    unsigned char Busy;
   LcdData=0xff;
    RS=0;
    RW=1;
    E=1;
    _nop_();
    Busy=LcdData&0x80;
    E=0;
    return Busy;
}
/*********************************
向LCD寫入字節(jié)數(shù)據(jù)
**********************************/
void Lcd_WriteData(unsigned char LCD_Data)
{  
while(Lcd_CheckBusy());
RS=1;
RW=0;
E=0;
_nop_();  
_nop_();
LcdData=LCD_Data;
E=1;
_nop_();
_nop_();
E=0;
}
/***********************************
從LCD中讀出數(shù)據(jù)
************************************/
unsigned char Lcd_ReadData(void)
{
unsigned char Temp;
//while(Lcd_CheckBusy());
  LcdData=0xff;
  RS=1;
RW=1;
E=1;
_nop_();
    Temp=LcdData;
    E=0;
    return Temp;
}
/*************************************
向LCD中寫入指令代碼
**************************************/
void Lcd_WriteCmd(unsigned char CmdCode)
{  
while(Lcd_CheckBusy());
    RS=0;
    RW=0;
    E=0;
    _nop_();  
_nop_();
    LcdData=CmdCode;
    _nop_();
_nop_();
    E=1;
    _nop_();  
_nop_();
    E=0;
}
void set_postion(unsigned char x,unsigned char y)
{
unsigned char postion;
switch(x)
{
case 0:x=0x80;break;   
case 1:x=0x90;break;
case 2:x=0x88;break;
case 3:x=0x98;break;
default:break;
}
postion=x+y;
Lcd_WriteCmd(postion);
}
/*************************************
向LCD指定起始位置寫入一個(gè)字符串
*************************************/
void Lcd_WriteStr(unsigned char x,unsigned char y,unsigned char *Str)
{
if((y>3)||(x>7))
  return;//如果指定位置不在顯示區(qū)域內(nèi),則不做任何寫入直接返回
EA=0;
switch(y)
{
  case 0:
    Lcd_WriteCmd(0x80+x);
    break;
  case 1:
    Lcd_WriteCmd(0x90+x);
    break;   
  case 2:
    Lcd_WriteCmd(0x88+x);
    break;
  case 3:
    Lcd_WriteCmd(0x98+x);
    break;
}
while(*Str>0)
{  
  Lcd_WriteData(*Str);
    Str++;     
}
EA=1;
}
/**************************************
為加速邏輯運(yùn)算而設(shè)置的掩碼表,這是以犧牲空間而換取時(shí)間的辦法
***************************************/
code unsigned int MaskTab[]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,
        0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};
/***************************************
向LCD指定坐標(biāo)寫入一個(gè)象素,象素顏色有兩種,0代表白(無顯示),1代表黑(有顯示)
****************************************/
void Lcd_PutPixel(unsigned char x,unsigned char y,unsigned char Color)
{
unsigned char z,w;
unsigned int Temp;
if(x>=128||y>=64)
  return;
Color=Color%2;
w=15-x%16;//確定對(duì)這個(gè)字的第多少位進(jìn)行操作
x=x/16;//確定為一行上的第幾字
if(y<32) //如果為上頁(yè)
  z=0x80;
else     //否則如果為下頁(yè)
  z=0x88;
y=y%32;
EA=0;
Lcd_WriteCmd(0x36);
Lcd_WriteCmd(y+0x80);        //行地址
Lcd_WriteCmd(x+z);     //列地址
Temp=Lcd_ReadData();//先空讀一次
Temp=(unsigned int)Lcd_ReadData()<<8;//再讀出高8位
Temp|=(unsigned int)Lcd_ReadData();//再讀出低8位
EA=1;
if(Color==1) //如果寫入顏色為1
  Temp|=MaskTab[w];//在此處查表實(shí)現(xiàn)加速
else         //如果寫入顏色為0
  Temp&=~MaskTab[w];//在此處查表實(shí)現(xiàn)加速
EA=0;
Lcd_WriteCmd(y+0x80);        //行地址
Lcd_WriteCmd(x+z);     //列地址
    Lcd_WriteData(Temp>>8);//先寫入高8位,再寫入低8位
    Lcd_WriteData(Temp&0x00ff);
Lcd_WriteCmd(0x30);
EA=1;
}
/***************************************
向LCD指定位置畫一條長(zhǎng)度為L(zhǎng)ength的指定顏色的水平線
****************************************/
void Lcd_HoriLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
unsigned char i;
if(Length==0)
  return;
for(i=0;i<Length;i++)
{
  Lcd_PutPixel(x+i,y,Color);
}
}
/***************************************
向LCD指定位置畫一條長(zhǎng)度為L(zhǎng)ength的指定顏色的垂直線
****************************************/
void Lcd_VertLine(unsigned char x,unsigned char y,unsigned char Length,unsigned char Color)
{
unsigned char i;
if(Length==0)
  return;
for(i=0;i<Length;i++)
{
  Lcd_PutPixel(x,y+i,Color);
}
}
/*******************************************
向LCD指定起始坐標(biāo)和結(jié)束坐標(biāo)之間畫一條指定顏色的直線
void Lcd_Line(unsigned char x1,unsigned char y1,unsigned char x2,unsigned char y2,unsigned char Color)
{
unsigned int x,y;
unsigned int d_x,d_y;//d_x=x2-x1;d_y=y2-y1;
int err=0;
unsigned char temp=0;
if(y2<y1)
{
  x=x1;
  y=y1;
  x1=x2;
  y1=y2;
  x2=x;
  y2=y;
}
d_y=y2-y1;
if (d_y==0)
{
  if (x1>x2)
  {
   x=x1;
   x1=x2;
   x2=x;
  }
  for (x=x1;x<=x2;x++)
   Lcd_PutPixel(x,y1,Color);
}
else
{
  if(x2>=x1)
  {
   temp=1;
   d_x=x2-x1;
  }
  else
   d_x=x1-x2;
  x=x1;
  y=y1;
  Lcd_PutPixel(x,y,1);
  if(temp&&(d_y<=d_x))
   while(x!=x2)
   {
    if(err<0)
    {
     x=x+1;
     err=err+(y2-y);
    }
    else
    {
     x=x+1;
     y=y+1;
     err=err+(y2-y)-(x2-x);
    }
    Lcd_PutPixel(x,y,Color);
   }
  else if(temp&&(d_y>d_x))
   while(y!=y2)
   {
    d_x=x2-x;
    d_y=y2-y;
    if(err<0)
    {
     x=x+1;
     y=y+1;
     err=err+d_y-d_x;
    }
    else
    {
     y=y+1;
     err=err-d_x;
    }
    Lcd_PutPixel(x,y,Color);
   }
  else if(!temp&&(d_y<=d_x))
   while(x!=x2)
   {
    d_x=x-x2;
    d_y=y2-y;
    if(err<0)
    {
     x=x-1;
     err=err+d_y;
    }
    else
    {
     x=x-1;
     y=y+1;
     err=err+d_y-d_x;
    }
    Lcd_PutPixel(x,y,Color);
   }
  else if(!temp &&(d_y>d_x))
   while(y!=y2)
   {
    d_x=x-x2;
    d_y=y2-y;
    if(err<0)
    {
     x=x-1;
     y=y+1;
     err=err+d_y-d_x;
    }
    else
    {
     y=y+1;
     err=err-d_x;
    }
    Lcd_PutPixel(x,y,Color);
   }
}
}
********************************************/
/*******************************************
向LCD指定左上角坐標(biāo)和右下角坐標(biāo)畫一個(gè)指定顏色的矩形
********************************************/
void Lcd_Rectangle(unsigned char x0,unsigned char y0,unsigned char x1,unsigned char y1,unsigned char Color)
{
unsigned char Temp;
if(x0>x1)
{
  Temp=x0;
  x0=x1;
  x1=Temp;
}
if(y0>y1)
{
  Temp=y0;
  y0=y1;
  y1=Temp;
}
Lcd_VertLine(x0,y0,y1-y0+1,Color);
Lcd_VertLine(x1,y0,y1-y0+1,Color);
Lcd_HoriLine(x0,y0,x1-x0+1,Color);
Lcd_HoriLine(x0,y1,x1-x0+1,Color);
}
/****************************************
對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
void CircleDot(unsigned char x,unsigned char y,char xx,char yy,unsigned char Color)//內(nèi)部函數(shù),對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
{
Lcd_PutPixel((x+yy),(y+xx),Color);//第 1 個(gè) 8 分圓
Lcd_PutPixel((x+xx),(y+yy),Color);//第 2 個(gè) 8 分圓
Lcd_PutPixel((x-xx),(y+yy),Color);//第 3 個(gè) 8 分圓
Lcd_PutPixel((x-yy),(y+xx),Color);//第 4 個(gè) 8 分圓
Lcd_PutPixel((x-yy),(y-xx),Color);//第 5 個(gè) 8 分圓
Lcd_PutPixel((x-xx),(y-yy),Color);//第 6 個(gè) 8 分圓
Lcd_PutPixel((x+xx),(y-yy),Color);//第 7 個(gè) 8 分圓
Lcd_PutPixel((x+yy),(y-xx),Color);//第 8 個(gè) 8 分圓
}
*****************************************/
/******************************************
向LCD指定圓心坐標(biāo)畫一個(gè)半徑為r的指定顏色的圓
void Lcd_Circle(unsigned char x,unsigned char y,unsigned char r,unsigned char Color)//中點(diǎn)法畫圓
{//中點(diǎn)法畫圓
unsigned char xx,yy;
char deltax,deltay,d;
xx=0;
yy=r;
deltax=3;
deltay=2-r-r;
d=1-r;
CircleDot(x,y,xx,yy,Color);//對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
while (xx<yy)
{
  if (d<0)
  {
   d+=deltax;
   deltax+=2;
   xx++;
  }
  else
  {
   d+=deltax+deltay;
   deltax+=2;
   deltay+=2;
   xx++;
   yy--;
  }
  CircleDot(x,y,xx,yy,Color);//對(duì)稱法畫圓的8個(gè)鏡像點(diǎn)
}
}
*******************************************/
/*****************************************
清除Lcd全屏,如果清除模式Mode為0,則為全屏清除為顏色0(無任何顯示)
否則為全屏清除為顏色1(全屏填充顯示)
******************************************/
void Lcd_Clear(unsigned char Mode)
{
unsigned char x,y,ii;
unsigned char Temp;
if(Mode%2==0)
  Temp=0x00;
else
  Temp=0xff;
Lcd_WriteCmd(0x36);//擴(kuò)充指令 繪圖顯示
for(ii=0;ii<9;ii+=8)   
  for(y=0;y<0x20;y++)     
   for(x=0;x<8;x++)
   {  
    EA=0;
    Lcd_WriteCmd(y+0x80);        //行地址
    Lcd_WriteCmd(x+0x80+ii);     //列地址     
    Lcd_WriteData(Temp); //寫數(shù)據(jù) D15-D8
    Lcd_WriteData(Temp); //寫數(shù)據(jù) D7-D0
    EA=1;
   }
Lcd_WriteCmd(0x30);
}
/****************************************
LCD初始化
*****************************************/
void Lcd_Reset(void)
{  
PSB=1;
Lcd_WriteCmd(0x30);       //選擇基本指令集
delay(5);
Lcd_WriteCmd(0x0c);       //開顯示(無游標(biāo)、不反白)
delay(5);
Lcd_WriteCmd(0x01);       //清除顯示,并且設(shè)定地址指針為00H
delay(5);
Lcd_WriteCmd(0x06);       //指定在資料的讀取及寫入時(shí),設(shè)定游標(biāo)的移動(dòng)方向及指定顯示的移位
}

void Delay10ms(void)   //誤差 0us
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=38;b>0;b--)
            for(a=130;a>0;a--);
}
void delay(unsigned int t)
{  
unsigned int i,j;
for(i=0;i<t;i++)
for(j=0;j<10;j++);   
}
/***********************************************
按鍵驅(qū)動(dòng)掃描
掃描一次鍵盤以獲得按鍵句柄
注:交OSReadKey()函數(shù)調(diào)用
***********************************************/
unsigned char KeyDown(void)
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//讀取按鍵是否按下
{
  Delay10ms();//延時(shí)10ms進(jìn)行消抖
  if(GPIO_KEY!=0x0f)//再次檢測(cè)鍵盤是否按下
  {
   
   //測(cè)試列
   GPIO_KEY=0X0F;
   switch(GPIO_KEY)
   {
    case(0X07): KeyValue=0;break;
    case(0X0b): KeyValue=1;break;
    case(0X0d): KeyValue=2;break;
    case(0X0e): KeyValue=3;break;
   }
   //測(cè)試行
   GPIO_KEY=0XF0;
   switch(GPIO_KEY)
   {
    case(0X70): KeyValue=KeyValue;break;
    case(0Xb0): KeyValue=KeyValue+4;break;
    case(0Xd0): KeyValue=KeyValue+8;break;
    case(0Xe0): KeyValue=KeyValue+12;break;
   }
   while((a<50)&&(GPIO_KEY!=0xf0))  //檢測(cè)按鍵松手檢測(cè)
   {
    Delay10ms();
    a++;
   }
  }
}

return KeyValue;   
}
/**********************************************
功能說明:讀取按鍵動(dòng)作
入口參數(shù):無
出口參數(shù):返回按鍵動(dòng)作
注意:
沒有按鍵動(dòng)作,則返回0,
使用矩陣按鍵:向上S12;向下S6;向左S12;向右S9;
***********************************************/
unsigned char OSReadKey(void)
{
static unsigned char KeyEventCnt=0;
static unsigned char KeySampleCnt=0;
static unsigned char KeyBuffer=0;
#define SHORT_ON_DITHERING_COUNTER 3//定義短按按下去抖時(shí)間
#define SHORT_OFF_DITHERING_COUNTER 3//定義短按松開去抖時(shí)間,一般與短按按下去抖時(shí)間相同
#if OS_LONG_EYK_EN>0
static unsigned int LongKeySampleCnt=0;
#define LONG_ON_DITHERING_COUNTER 250//定義長(zhǎng)按按下確認(rèn)需要的時(shí)間,如果是每1MS調(diào)用一次OSReadKey(),則1000意味著這個(gè)時(shí)間為1S
#define LONG_OFF_DITHERING_COUNTER 3//定義長(zhǎng)按松開去抖時(shí)間,一般和短按去抖時(shí)間相同
#endif
unsigned char KeyTemp;
KeyTemp=DIG_CODE[KeyDown()];
switch(KeyEventCnt)
{
  case 0:
   if(KeyTemp!=0)
   {
    KeySampleCnt=0;
    KeyBuffer=KeyTemp;
    KeyEventCnt=1;     
   }
   return 0;//no key on,return 0
   break;
  
  #if OS_LONG_EYK_EN>0
  case 1:
   if(KeyTemp!=KeyBuffer)
   {
    KeyEventCnt=0;
    return 0;//is dithering,return 0
   }
   else
   {
    if(++KeySampleCnt>SHORT_ON_DITHERING_COUNTER)
    {
     KeySampleCnt=0;
     KeyEventCnt=2;
     LongKeySampleCnt=0;
     return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
    }
    else
     return 0;//not sure that key on,return 0                 
   }
   break;
   
  case 2:
   if(++LongKeySampleCnt>LONG_ON_DITHERING_COUNTER)
   {
    KeySampleCnt=0;
    KeyEventCnt=3;
    return ((KeyBuffer-1)<<2)+2; //sure that key long on,return (KeyBuffer-1)<<2+2
   }
   else
   {
    if(KeyTemp!=KeyBuffer)
    {
     if(++KeySampleCnt>SHORT_OFF_DITHERING_COUNTER)
     {
      KeyEventCnt=0;
      return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
     }
     else
      return 0;
    }
    else
    {
     KeySampleCnt=0;
     return 0;
    }
   }
   break;
  
  case 3:
   if(KeyTemp!=KeyBuffer)
   {
    if(++KeySampleCnt>LONG_OFF_DITHERING_COUNTER)
    {
     KeyEventCnt=0;
     return ((KeyBuffer-1)<<2)+4;  //after long key on turn to off,(KeyBuffer-1)<<2+4
    }
    else
     return 0;
   }
   else
   {
    KeySampleCnt=0;
    return 0;
   }
   break;
  
  #else
  case 1:
   if(KeyTemp!=KeyBuffer)
   {
    KeyEventCnt=0;
    return 0;//is dithering,return 0
   }
   else
   {
    if(++KeySampleCnt>=SHORT_ON_DITHERING_COUNTER)
    {
     KeySampleCnt=0;
     KeyEventCnt=2;
     return ((KeyBuffer-1)<<2)+1;//sure that key on,return (KeyBuffer-1)<<2+1
    }
    else
     return 0;//not sure that key on,return 0                 
   }
   break;
   
  case 2:
   if(KeyTemp!=KeyBuffer)
   {
    if(++KeySampleCnt>=SHORT_OFF_DITHERING_COUNTER)
    {
     KeyEventCnt=0;
     return ((KeyBuffer-1)<<2)+3;//after short on to off,(KeyBuffer-1)<<2+3
    }
    else
     return 0;
   }
   else
   {
    KeySampleCnt=0;
    return 0;
   }
   break;
  #endif
  default:break;
}
return 0;
}

/************************************
偽隨機(jī)數(shù)發(fā)生器
*************************************/
double Random(void)
{
long TmpSeed;
TmpSeed=A*(Seed%Q)-R*(Seed/Q);
if(TmpSeed>=0)
Seed=TmpSeed;
else
Seed=TmpSeed+M;
return (double)Seed/M;
}
/**************************************
為偽隨機(jī)數(shù)發(fā)生器播種
***************************************/
void InitRandom(unsigned long InitVal)
{
Seed=InitVal;
}
/*********************************
初始化MPU
**********************************/
void InitCpu(void)
{
TMOD=0x01;
TH0=0;
TL0=0;
TR0=1;
ET0=1;
EA=1;
}
void Timer0Int(void) interrupt 1
{
switch(OSReadKey())
{
case 5:
   KeyBuffer=FUNC;        //表示級(jí)別
   break;
case 21:
   KeyBuffer=DOWN;       //表示右
   break;
case 13:
   KeyBuffer=UP;       //表示左
    break;
case 9:
   KeyBuffer=RIGHT;      //表示上
   break;
    case 17:
   KeyBuffer=LEFT;       //表示下
   break;
default:
   break;
}
}
/******************************
畫墻壁,初始化界面
*******************************/
void DrawBoardf()
{
unsigned char n;
for(n=0;n<31;n++)
  {
   Lcd_Rectangle(3*n,0,3*n+2,2,1);
   Lcd_Rectangle(3*n,60,3*n+2,62,1);
  }
for(n=0;n<21;n++)
  {
   Lcd_Rectangle(0,3*n,2,3*n+2,1);
   Lcd_Rectangle(90,3*n,92,3*n+2,1);  
  }
Lcd_HoriLine(93,31,35,1);
Lcd_HoriLine(93,63,35,1);
}
void Drawboardt(void)
{
unsigned char n;
for(n=0;n<21;n++)
{
Lcd_Rectangle(0,3*n,2,3*n+2,1);
Lcd_Rectangle(90,3*n,92,3*n+2,1);  
}
Lcd_HoriLine(93,31,35,1);
Lcd_HoriLine(93,63,35,1);
}

/***************************
打印成績(jī)
****************************/
void PrintScore(void)
{
unsigned char Str[3];        
Lcd_WriteStr(6,0,"成績(jī)");
Str[0]=(Score/10)|0x30;//十位
Str[1]=(Score%10)|0x30;//個(gè)位
Str[2]=0;        
Lcd_WriteStr(7,1,Str);
}
/********************************
打印速度級(jí)別
*********************************/
void PrintSpeed(void)
{
unsigned char Str[2];
Lcd_WriteStr(6,2,"級(jí)別");
Str[0]=Speed_tiaosu|0x30;
Str[1]=0;
Lcd_WriteStr(7,3,Str);
}
/***********************************
游戲結(jié)束處理
************************************/
void GameOver(void)
{
unsigned char n;
Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱出食物
for(n=1;n<snake.node;n++)
{
Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,0);//消隱食物,蛇頭已到墻壁內(nèi),故不用消去  
}
if(snake.life==0)//如果蛇還活著
Lcd_WriteStr(2,1,"過關(guān)");
else             //如果蛇死了
Lcd_WriteStr(2,1,"輸了");
Lcd_WriteStr(1,2,"游戲結(jié)束");
}
/********************************
游戲的具體過程,也是貪吃蛇算法的關(guān)鍵部分
*********************************/
void GamePlayf(void)
{
unsigned char n;
InitRandom(TL0);
food.yes=1;//1表示需要出現(xiàn)新事物,0表示已經(jīng)存在食物尚未吃掉
snake.life=0;//表示蛇還活著
snake.direction=DOWN;
snake.x[0]=6;snake.y[0]=6;
snake.x[1]=3;snake.y[1]=6;
snake.node=2;
PrintScore();
PrintSpeed();
while(1)
{
if(food.yes==1)
{
  while(1)
  {
   food.x=Random()*85+3;
   food.y=Random()*55+3;//獲得隨機(jī)數(shù)
   while(food.x%3!=0)
    food.x++;
   while(food.y%3!=0)
    food.y++;
      for(n=0;n<snake.node;n++)//判斷產(chǎn)生的食物坐標(biāo)是否和蛇身重合
   {
    if((food.x==snake.x[n])&&(food.y==snake.y[n]))
     break;
   }
   if(n==snake.node)
   {
    food.yes=0;
    break;//產(chǎn)生有效的食物坐標(biāo)
   }
  }
}
if(food.yes==0)
{
  Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
}
for(n=snake.node-1;n>0;n--)
{
  snake.x[n]=snake.x[n-1];
  snake.y[n]=snake.y[n-1];
}
switch(snake.direction)
{
  case DOWN:snake.x[0]+=3;break;
  case UP:snake.x[0]-=3;break;
  case RIGHT:snake.y[0]-=3;break;
  case LEFT:snake.y[0]+=3;break;
  default:break;
}
for(n=3;n<snake.node;n++)//從第三節(jié)開始判斷蛇頭是否咬到自己
{
  if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
  {
   GameOver();
   snake.life=1;
   break;
  }
}
if(snake.x[0]<3||snake.x[0]>=90||snake.y[0]<3||snake.y[0]>=60)//判蛇頭是否撞到墻壁
{
  GameOver();
  snake.life=1;
}
if(snake.life==1)
  break;//蛇死,則跳出while(1)循環(huán)
if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
{
  Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱食物
  snake.x[snake.node]=200;
  snake.y[snake.node]=200;//產(chǎn)生蛇新的節(jié)坐標(biāo)先放在看不見的位置
  snake.node++;//蛇節(jié)數(shù)加1
  food.yes=1;//食物標(biāo)志置1
  if(++Score>=PASSSCORE)
  {
   PrintScore();
   GameOver();
   break;
  }
  PrintScore();
}
for(n=0;n<snake.node;n++)
{
  Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
}//根據(jù)蛇的節(jié)數(shù)畫出蛇
delay(Speed_tiaosu*1000);   //調(diào)速
delay(Speed_tiaosu*1000);
Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0);
switch(KeyBuffer)
{
  case FUNC:
    KeyBuffer=0;
    if(++Speed_tiaosu>=10)
     Speed_tiaosu=1;
       PrintSpeed();
    break;
  case DOWN:
    KeyBuffer=0;
    if(snake.direction!=UP)
     snake.direction=DOWN;
    break;
  case UP:
    KeyBuffer=0;
    if(snake.direction!=DOWN)
     snake.direction=UP;
    break;
  case RIGHT:
    KeyBuffer=0;
    if(snake.direction!=LEFT)
     snake.direction=RIGHT;
    break;
     case LEFT:
    KeyBuffer=0;
    if(snake.direction!=RIGHT)
     snake.direction=LEFT;
    break;
  default:
    break;
}   
}
}
void Gameplayt(void)
{
unsigned char n;
InitRandom(TL0);
food.yes=1;//1表示需要出現(xiàn)新事物,0表示已經(jīng)存在食物尚未吃掉
snake.life=0;//表示蛇還活著
snake.direction=DOWN;
snake.x[0]=6;snake.y[0]=6;
snake.x[1]=3;snake.y[1]=6;
snake.node=2;
PrintScore();
PrintSpeed();
while(1)
{
if(food.yes==1)
{
  while(1)
  {
   food.x=Random()*85+3;
   food.y=Random()*55+3;//獲得隨機(jī)數(shù)
   while(food.x%3!=0)
    food.x++;
   while(food.y%3!=0)
    food.y++;
      for(n=0;n<snake.node;n++)//判斷產(chǎn)生的食物坐標(biāo)是否和蛇身重合
   {
    if((food.x==snake.x[n])&&(food.y==snake.y[n]))
     break;
   }
   if(n==snake.node)
   {
    food.yes=0;
    break;//產(chǎn)生有效的食物坐標(biāo)
   }
  }
}
if(food.yes==0)
{
  Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,1);
}
for(n=snake.node-1;n>0;n--)
{
  snake.x[n]=snake.x[n-1];
  snake.y[n]=snake.y[n-1];
}
switch(snake.direction)
{
  case DOWN:snake.x[0]+=3;break;
  case UP:snake.x[0]-=3;break;
  case RIGHT:snake.y[0]-=3;break;
  case LEFT:snake.y[0]+=3;break;
  default:break;
}
for(n=3;n<snake.node;n++)//從第三節(jié)開始判斷蛇頭是否咬到自己
{
  if(snake.x[n]==snake.x[0]&&snake.y[n]==snake.y[0])
  {
   GameOver();
   snake.life=1;
   break;
  }
}
if(snake.x[0]<3||snake.x[0]>=90)//判蛇頭是否撞到墻壁
{
  GameOver();
  snake.life=1;
}
if(snake.life==1)
  break;//蛇死,則跳出while(1)循環(huán)
if(snake.y[0]<3||snake.y[0]>=60)   
{  if(snake.y[0]<3)
    snake.y[0]=59;
//      for(n=0;n<snake.node;n++)
//  {
//   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
//  }//根據(jù)蛇的節(jié)數(shù)畫出蛇
    if(snake.y[0]>=60)
    snake.y[0]=3;
//    for(n=0;n<snake.node;n++)
//  {
//   Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
//  }//根據(jù)蛇的節(jié)數(shù)畫出蛇
//  

}
if(snake.x[0]==food.x&&snake.y[0]==food.y)//判蛇是否吃到食物
{
  Lcd_Rectangle(food.x,food.y,food.x+2,food.y+2,0);//消隱食物
  snake.x[snake.node]=200;
  snake.y[snake.node]=200;//產(chǎn)生蛇新的節(jié)坐標(biāo)先放在看不見的位置
  snake.node++;//蛇節(jié)數(shù)加1
  food.yes=1;//食物標(biāo)志置1
  if(++Score>=PASSSCORE)
  {
   PrintScore();
   GameOver();
   break;
  }
  PrintScore();
}
for(n=0;n<snake.node;n++)
{
  Lcd_Rectangle(snake.x[n],snake.y[n],snake.x[n]+2,snake.y[n]+2,1);
}//根據(jù)蛇的節(jié)數(shù)畫出蛇
delay(Speed_tiaosu*1000);   //調(diào)速
delay(Speed_tiaosu*1000);
Lcd_Rectangle(snake.x[snake.node-1],snake.y[snake.node-1],snake.x[snake.node-1]+2,snake.y[snake.node-1]+2,0);
switch(KeyBuffer)
{
  case FUNC:
    KeyBuffer=0;
    if(++Speed_tiaosu>=10)
     Speed_tiaosu=1;
       PrintSpeed();
    break;
  case DOWN:
    KeyBuffer=0;
    if(snake.direction!=UP)
     snake.direction=DOWN;
    break;
  case UP:
    KeyBuffer=0;
    if(snake.direction!=DOWN)
     snake.direction=UP;
    break;
  case RIGHT:
    KeyBuffer=0;
    if(snake.direction!=LEFT)
     snake.direction=RIGHT;
    break;
     case LEFT:
    KeyBuffer=0;
    if(snake.direction!=RIGHT)
     snake.direction=LEFT;
    break;
  default:
    break;
}   
}
}


void scankey(void)
{





}

void speed(void)
{
Lcd_WriteStr(0,1,"Speed1");

Lcd_WriteStr(1,1,"Speed2");

Lcd_WriteStr(2,1,"Speed3");

Lcd_WriteStr(3,1,"Speed4");        
}
void moshi(void)
{
Lcd_WriteStr(0,1,"mosho1");

Lcd_WriteStr(1,1,"moshi2");         
}
void zhujiemian(void)
{
Lcd_WriteCmd(0x01);
  Lcd_WriteStr(0,0,"開始游戲");
Lcd_WriteStr(0,1,"速度選擇");
Lcd_WriteStr(0,2,"模式設(shè)置");
}
unsigned char moshi1()
{
moshiceshi=1;
DrawBoardf();
GamePlayf();
return moshiceshi;
zhujiemian();
}
unsigned char moshi2()
{
moshiceshi=2;
  Drawboardt();
  Gameplayt();
return moshiceshi;
zhujiemian();
}
void Speed1(void)
{
unsigned char Speed_tiaosu=1;
zhujiemian();
}         
void Speed2(void)
{
unsigned char Speed_tiaosu=2;
zhujiemian();

}         
void Speed3(void)
{
unsigned char Speed_tiaosu=3;
zhujiemian();
        
}         
void Speed4(void)
{
unsigned char Speed_tiaosu=4;
zhujiemian();
}         
void game(void)
{
  InitCpu();//初始化CPU
Lcd_Reset(); //初始化LCD屏
delay(5000);
Lcd_Clear(0);//清屏
switch(Speed_tiaosu)
{
  case '1':
  Speed1();
  break;
  case '2':
  Speed2();
  break;
  case '3':
  Speed3();
  break;
  case '4':
  Speed4();
  break;
  default:
  Speed4();
}
switch(moshiceshi)
{
  case '1':
  moshi1();
  break;
  case '2':
  moshi2();
  break;
  default:
  moshi1();
}
GameOver();//游戲結(jié)束
}


回復(fù)

使用道具 舉報(bào)

7#
ID:377361 發(fā)表于 2018-8-15 02:36 | 只看該作者
這是修改后的代碼,為什么程序會(huì)卡住呢???
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 成人一区二区三区在线观看 | 日本电影一区二区 | 色综合天天综合网国产成人网 | 久久久夜色精品亚洲 | 日本三级做a全过程在线观看 | 国产激情视频网 | www.国产一区 | 日韩视频在线一区 | 国产精品片 | 欧美一级免费 | 免费一区二区 | 青青艹在线视频 | 欧美成人a∨高清免费观看 91伊人 | 久久精品国产99国产精品亚洲 | 中文字幕电影在线观看 | 91精品久久久久久久久 | 日本精品一区二区在线观看 | 日韩欧美高清 | 久草资源在线视频 | 亚洲国产二区 | 久久久妇女国产精品影视 | 97精品视频在线观看 | 毛片黄片| 久久亚洲国产精品 | 91tv在线观看 | 日本三级视频 | 巨大荫蒂视频欧美另类大 | 九九精品在线 | 免费视频一区二区 | 一级黄色毛片 | 免费看国产a| av在线一区二区三区 | 一区二区av | 日日干天天操 | 成人在线| 国产精品黄视频 | 91色视频在线观看 | 一区在线视频 | 久久久国产精品一区 | 午夜爱爱毛片xxxx视频免费看 | 国产精品美女久久久 |