基于STC89C52单片机贪吃蛇做法

2018-11-16 17:01

#ifndef _glb_h_ #define _glb_h_

#define uchar unsigned char #define uint unsigned int

#define LOW 0 #define HIGH 1

//初始化指令

#define CLEAR_SCREEN 0x01 //清屏指令:清屏且AC值为00H #define AC_INIT 0x02 //将AC设置为00H。且游标移到原点位置

#define CURSE_ADD 0x06 //设定游标移到方向及图像整体移动方向(默认游标右移,图像整体不动)

#define FUN_MODE 0x30 //工作模式:8位基本指令集

#define DISPLAY_ON 0x0c //显示开,显示游标,且游标位置反白 #define DISPLAY_OFF 0x08 //显示关

#define CURSE_DIR 0x14 //游标向右移动:AC=AC+1

#define SET_CG_AC 0x40 //设置AC,范围为:00H~3FH #define SET_DD_AC 0x80

#define FUN_MODEK 0x36 //扩展指令集,8位指令 #define X1address 0x80 //上半屏X轴起始地址 #define X2address 0x88 //下半屏X轴起始地址 #define Yaddress 0x80 //Y轴起始地址

/*--------------------------------------------------------------------------------------------------- 液晶屏

----------------------------------------------------------------------------------------------------*/

#define DataPort P0 sbit RS = P3^5; sbit RW = P3^6; sbit E = P3^4; sbit PSB = P3^7; sbit WELA = P2^7; sbit DULA = P2^6; sbit speed=P2^0; sbit beep=P2^3;

/*

#define DataPort P1 sbit RS = P2^0; sbit RW = P2^1; sbit E = P2^3; sbit PSB = P2^4; //sbit WELA = P2^7; //sbit DULA = P2^6; */

/*--------------------------------------------------------------------------------------------------- 贪吃蛇

----------------------------------------------------------------------------------------------------*/ //定义复位不自动清零全局变量

//#pragma DATA_SEG NOINIT_RAM

sbit LEFT=P2^4;//左 sbit RIGHT=P2^1;//右 sbit UP=P2^5;//上 sbit DOWN=P2^2;//下 //sbit Led1=P1^7; //sbit Led2=P1^6;

/*sbit LEFT=P0^2;//左 sbit RIGHT=P0^3;//右 sbit UP=P0^0;//上

sbit DOWN=P0^1;//下*/

sbit Led7=P1^0; sbit Led6=P1^1; sbit Led5=P1^3; sbit Led4=P1^4; //sbit Led3=P3^3; //sbit Led2=P3^2; //sbit Led1=P3^1; //sbit Led0=P3^0;

#endif

#ifndef _Init_h_ #define _Init_h_

/*------------------------------------------------------------------------------------------------------------ Init_12864

-------------------------------------------------------------------------------------------------------------*/

void Delayus(unsigned char i); void Delayms(unsigned int i); void Check_Busy();

void Write_Cmd(unsigned char Cmd); void Write_Data(unsigned char Data); //uchar Read_Status(); uchar Read_Data(); void Init_IO(); void Init_12864(); //void disp(); void CGRAM();

void LCD_PutString(unsigned char x,unsigned char y,unsigned char code *s); void ClrScreen();

void Clr_GDRAM(void);

void LCD_PutGraphic(unsigned char code *img); void SetGraphicMode(); void Keyscan(); void statuschange();

void Draw_Point(uchar X,uchar Y,uchar clour); void Draw_zhi(uchar X1,uchar X2,uchar Y); void Draw_shu(uchar X,uchar Y1,uchar Y2);

void Draw_line(uchar x0,uchar y0,uchar x1,uchar y1); void Draw_all_lines(); void Stat_Point(); void Last_Point(); void Add_Point(); void Bump_Wall(); void Self_Bump();

/*------------------------------------------------------------------------------------------------------------ Init_Time

-------------------------------------------------------------------------------------------------------------*/ //void Init_Time();

//void exter0() interrupt 1

#endif

#include #include \

uint timestatus=0;

void Init_Time() { TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%6; EA=1; ET0=1; TR0=1; }

void Timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%6; timestatus++; if(speed==0) { if(timestatus>2) timestatus=0; } if(timestatus>10) timestatus=0; }

#ifndef _Interrupt_h_ #define _Interrupt_h_

void Init_Time();

#endif

#include #include \

/*游戏的初始化值*/

uchar gamestatus=0; uchar flag=1; //折点个数标志

uchar a[]={20,0,0,0,0,0,0,0}; //其中(a[0],b[0])为初始蛇头坐标,(a[1],b[1])为初始蛇尾坐标,之后蛇尾坐标为(a[flag],b[flag])。 uchar b[]={32,32,0,0,0,0,0,0}; //后面(a[i],b[i])记录拐点坐标,其中(a[flag-1],b[flag-1])为第一个拐点的坐标

uchar c[]={0,0,0,0,0,0,0,0}; //c[i]记录方向,其中a[0]为当前方向 uchar x=54,y=32,pointstatus,allpoints;

/*--------------------------------------------------------------------------------- 延时函数

---------------------------------------------------------------------------------*/ void Delayus(unsigned char i) { int j; for(j=2;j>0;j--) for(;i>0;i--); }

void Delayms(unsigned int i) { unsigned int j; for(;i>0;i--) for(j=110;j>0;j--); }

/*--------------------------------------------------------------------------------- 检测忙位

---------------------------------------------------------------------------------*/ void Check_Busy() {

E=0;

RS=0; RW=1; E=1; DataPort=0xff; while((DataPort&0x80)==0x80); //忙则等待,忙标志检测BF,可以将BF读到DB7进行检测 E=0; }

/*--------------------------------------------------------------------------------- 写命令

---------------------------------------------------------------------------------*/ void Write_Cmd(unsigned char Cmd) { Check_Busy(); RS=0; RW=0; DataPort=Cmd; Delayus(2); E=1; Delayus(5); E=0; }

/*--------------------------------------------------------------------------------- 写数据

---------------------------------------------------------------------------------*/ void Write_Data(unsigned char Data) { Check_Busy(); RS=1; RW=0; E=1; DataPort=Data; Delayus(2); E=0; Delayus(5); }

/*--------------------------------------------------------------------------------- 读状态

---------------------------------------------------------------------------------*/ /*uchar Read_Status()

{ uchar i;

DataPort=0xff; RW=1; RS=0; E=0;

Delayus(2); E=1;

Delayus(5); i=DataPort; Delayus(5); E=0; return(i); } */

/*--------------------------------------------------------------------------------- 读数据

---------------------------------------------------------------------------------*/ uchar Read_Data() { uchar i;

//while((Read_Status() & 0x80 )!=0x00); //忙检测 Check_Busy(); RW=1; RS=1; E=0;

Delayus(2); E=1;

Delayus(5); i=DataPort; Delayus(5); E=0; return i; }

/*--------------------------------------------------------------------------------- 计算并显示得分

---------------------------------------------------------------------------------*/ void Write_Score(uchar x,uchar y,uchar shu) {

uchar d1,d2,add,ah; d1=shu/10;

d2=shu; if(x==0) ah=0x80; else if(x==1) ah=0x90; else if(x==2) ah=0x88; else ah=0x98;

add=ah+y; //某一行显示分数 Write_Cmd(add); Write_Data( d1+'0'); Write_Data( d2+'0'); }

/*--------------------------------------------------------------------------------- IO口初始化

---------------------------------------------------------------------------------*/ void Init_IO() { Led4=1; Led5=1; Led6=1; Led7=1; }

/*--------------------------------------------------------------------------------- 液晶屏初始化

---------------------------------------------------------------------------------*/ void Init_12864() { //WELA=0; //DULA=1; Delayms(1); PSB=1; Delayms(1); Write_Cmd(0x30); Delayms(1); Write_Cmd(0x30); Delayms(1); Write_Cmd(0x0f); Delayms(1); Write_Cmd(0x01);

Delayms(1); //Write_Cmd(0x06); //DelayVs2x(50); }

/*void disp() { unsigned char i; unsigned char a=0x10; Write_Cmd(0x80); for(i=0;i<16;i++) { Write_Data(a); a++; Delayms(2); } } */

/*--------------------------------------------------------------------------------- 用户自定义字符

---------------------------------------------------------------------------------*/ /*void CGRAM() { int i; Write_Cmd(0x30); Write_Cmd(0x40); for(i=0;i<16;i++) { Write_Data(0x10); Write_Data(0x10); } } */

/*--------------------------------------------------------------------------------- 显示字符 x:横坐标值,范围0-8 y:纵坐标值,范围1-4

---------------------------------------------------------------------------------*/

void LCD_PutString(unsigned char x,unsigned char y,unsigned char code *s) { switch(y)

{ case 1: Write_Cmd(0x80+x);break; case 2: Write_Cmd(0x90+x);break; case 3: Write_Cmd(0x88+x);break; case 4: Write_Cmd(0x98+x);break; default:break; } while(*s>0) { Write_Data(*s); s++; Delayms(5); } }

/*--------------------------------------------------------------------------------- 清屏

---------------------------------------------------------------------------------*/ void ClrScreen() { Write_Cmd(0x01); Delayus(5); }

/*---------------------------------------------------------------------------------

清除液晶GDRAM内部的随机数据 ---------------------------------------------------------------------------------*/

void Clr_GDRAM(void) {

uchar x,y,i,j;

Write_Cmd(0x34); //鎵撳紑鎵╁睍鎸囦护闆? y=0x80; x=0x80;

for(i=0;i<32;i++) {

Write_Cmd(y); Write_Cmd(x); for(j=0;j<16;j++) {

Write_Data(0x00);

} y++; }

y=0x80; x=0x88;

for(i=0;i<32;i++) {

Write_Cmd(y); Write_Cmd(x); for(j=0;j<16;j++) {

Write_Data(0x00); } y++; }

Write_Cmd(0x30); //鍥炲埌鍩烘湰鎸囦护闆? }

/*--------------------------------------------------------------------------------- 显示图片

---------------------------------------------------------------------------------*/ /*void LCD_PutGraphic(unsigned char code *img) { int i,j; //显示上半屏内容设置 for(i=0;i<16;i++) { Write_Cmd(0x80); for(j=0;j<16;j++) { Write_Data(*img); img++; } Write_Cmd(0x90); for(j=0;j<16;j++) { Write_Data(*img); img++; } }

//显示下半屏内容设置 for(i=0;i<32;i++) { Write_Cmd(0x88); for(j=0;j<16;j++) { Write_Data(*img); img++; } Write_Cmd(0x98); for(j=0;j<16;j++) { Write_Data(*img); img++; } } }*/

/*--------------------------------------------------------------------------------- 设置到绘图模式

---------------------------------------------------------------------------------*/ /*void SetGraphicMode() { Write_Cmd(0x36); Delayms(2); } */

/*------------------------------------------------------------------------------------------------------------ 按键函数

-------------------------------------------------------------------------------------------------------------*/ void Keyscan() { Led4=1; Led5=1; Led6=1; Led7=1; if(RIGHT==0) { Delayms(5);

if(RIGHT==0) { Led4=0; gamestatus=0; } }

if(DOWN==0) { Delayms(5); if(DOWN==0) { Led5=0; gamestatus=1; } } if(UP==0) { Delayms(5); if(UP==0) { Led6=0; gamestatus=3; } } if(LEFT==0) { Delayms(5); if(LEFT==0) { Led7=0; gamestatus=2; } } }

/*------------------------------------------------------------------------------------------------------------ 状态发生改变处理函数 必须跟在按键涵数后面!!!!

-------------------------------------------------------------------------------------------------------------*/ void statuschange() {

uchar i;

if((gamestatus!=c[0])&&((gamestatus%2)!=(c[0]%2))) //只有gamestatus由奇数变为偶数或由偶数变为奇数时,才改变方向 { flag++; //方向改变,折点个数加1 for(i=flag;i>0;i--) { a[i]=a[i-1]; b[i]=b[i-1]; c[i]=c[i-1]; }

c[0]=gamestatus; } }

/*------------------------------------------------------------------------------------------------------------ 画点函数 ,在屏幕上画一个点

-------------------------------------------------------------------------------------------------------------*/ void Draw_Point(uchar X,uchar Y,uchar clour) // clour为0时画点,为其它清除这个点 {

uchar x_pos,y_pos,x_bit;

uint read_H,read_L,data_H,data_L;

//计算LCD位置 x_pos=X/16; //取16*16首地址 if(Y>31)

x_pos+=8; //计算该点所属LCD液晶中X坐标位置,上半屏0-7,下半屏8-15

x_bit=X; //该点位于所在16bit中的第几位 y_pos=Y2; //y坐标32行的第几行

Write_Cmd(0x34); //打开扩展指令集 操作GDRAM是扩展指令集

Write_Cmd(0x36); //使用扩充指令集,绘图显示ON

Write_Cmd(0x80+y_pos); // 写入第一行8个32*16模块的垂直起始地址,在写入地址时,要先输入垂直地址,再输入水平地址 这是规定好的 Write_Cmd(0x80+x_pos); //第一行水平的起始地址为80H //以后写入数据后,地址计数器(AC)会自动加一

Read_Data(); //此处为什么要中上不知道为什么????

read_H = Read_Data(); //高八位! read_L = Read_Data(); //低八位!

if(x_bit<8) //该点位于高八位 { if(clour==0) //画点 { data_H=read_H|(1<<(7-x_bit)); //把1左移7-x_bit位 } else { data_H=read_H&~(1<<(7-x_bit)); }

data_L=read_L; } else //该点位于低八位 { data_H=read_H; if(clour==0) { data_L=read_L|(1<<(15-x_bit)); } else { data_L=read_L&~(1<<(15-x_bit)); } } Write_Cmd(0x80+y_pos); Write_Cmd(0x80+x_pos); Write_Data(data_H); //写高八位数据 Write_Data(data_L); //写低八位数据

Write_Cmd(0x30); //回到基本指令集 Write_Cmd(0x0c); }

/*------------------------------------------------------------------------------------------------------------ 在整个屏幕上画一条直线

-------------------------------------------------------------------------------------------------------------*/

void Draw_zhi(uchar X1,uchar X2,uchar Y) //X1代表线首横坐标,X2代表线尾横坐标,Y代表纵坐标 { uchar i,temp ;

if(X1>X2) //X轴上,起点大于终点,交换数据 {

temp=X2; X2=X1;

X1=temp; }

for(i=X1;i<=X2;i++) {

Draw_Point(i,Y,0); } }

/*------------------------------------------------------------------------------------------------------------ 在整个屏幕上画一条竖线

-------------------------------------------------------------------------------------------------------------*/ void Draw_shu(uchar X,uchar Y1,uchar Y2) //Y1代表线首纵坐标,Y2代表线尾纵坐标,X代表横坐标 {

uchar i ,temp;

if(Y1>Y2) //X轴上,起点大于终点,交换数据 {

temp=Y2; Y2=Y1;

Y1=temp; } for(i=Y1;i<=Y2;i++) {

Draw_Point(X,i,0); } }

/*------------------------------------------------------------------------------------------------------------ 在整个屏幕上画一条线

-------------------------------------------------------------------------------------------------------------*/ void Draw_line(uchar x0,uchar y0,uchar x1,uchar y1) //只能是横线或者是竖线,(x0,y0)为线首坐标。(x1,y1)为线尾坐标 { int dx,dy; //定义X.Y轴上增加的变量值

dx=x1-x0; //X轴方向上的增量 dy=y1-y0; //Y轴方向上的增量 if(dx==0) Draw_shu(x0,y0,y1);

if(dy==0) Draw_zhi(x0,x1,y0); }

/*------------------------------------------------------------------------------------------------------------ 画边界函数

-------------------------------------------------------------------------------------------------------------*/ void Draw_all_lines() {

uchar i;

for(i=0;i

/*------------------------------------------------------------------------------------------------------------ 开始点,蛇头

-------------------------------------------------------------------------------------------------------------*/ void Stat_Point() {

if(c[0]==0) {

a[0]=a[0]+1; //如果向右,直线长度加1 }

else if(c[0]==1) {

b[0]=b[0]+1; } else if(c[0]==2) {

a[0]=a[0]-1; } else {

b[0]=b[0]-1; }

}

/*------------------------------------------------------------------------------------------------------------ 最后点,蛇尾

-------------------------------------------------------------------------------------------------------------*/ void Last_Point() { if(c[flag-1]==0) //如果第一次拐之前,方向向右 { a[flag]=a[flag]+1; //蛇尾横坐标加1 }

else if(c[flag-1]==1) { b[flag]=b[flag]+1; }

else if(c[flag-1]==2) { a[flag]=a[flag]-1; }

else { b[flag]=b[flag]-1; }

if((a[flag]==a[flag-1])&&(b[flag]==b[flag-1])) {

flag--; } }

/*------------------------------------------------------------------------------------------------------------ 加点,如果吃到食物,就产生新的食物,并画上该点,把该点作为蛇头

-------------------------------------------------------------------------------------------------------------*/ void Add_Point() { if(c[0]==0) { if((a[0]+1)==x&&(b[0]==y)) {

a[0]=x; pointstatus=1; allpoints++; } } else if(c[0]==1) { if((b[0]+1)==y&&(a[0]==x)) { b[0]=y; pointstatus=1; allpoints++; } } else if(c[0]==2) { if((a[0]-1)==x&&(b[0]==y)) { a[0]=x; pointstatus=1; allpoints++; } } else { if((a[0])==x&&(b[0]-1)==y) { b[0]=y; pointstatus=1; allpoints++; } }

Draw_Point(x,y,0); //画上一个点,即产生食物 if(pointstatus) { beep=0; Delayms(10); beep=1; pointstatus=0;

//Draw_Point(x,y,1); //清除这个点 //Delayms(5000); //设置断点,用于测试 x=x+16; y=y+18; if(x>127) { x=1; } if(y>63) { y=0; } } }

/*------------------------------------------------------------------------------------------------------------ 判断是否撞边框

-------------------------------------------------------------------------------------------------------------*/ void Bump_Wall() { if((a[0]>127||a[0]<0)||(b[0]<0||b[0]>63)) { TR0=0; ClrScreen(); //Disp_HZ(0x98,hang4,8); LCD_PutString(0,3,\撞墙死亡了\ Write_Score(3,7,allpoints); } }

/*------------------------------------------------------------------------------------------------------------ 判断是否自身相撞

-------------------------------------------------------------------------------------------------------------*/ void Self_Bump() { uchar i,j; for(j=flag-1;j>=3;j--) { if(c[j]==0) { for(i=a[j+1];i

if((a[0]==i)&&(b[0]==b[j])) { TR0=0; ClrScreen(); //Disp_HZ(0x98,hang3,7); LCD_PutString(0,4,\死亡\ Write_Score(3,7,allpoints); } } } else if(c[j]==1) { for(i=b[j+1];i

for(i=b[j];i

} }

//Disp_HZ(0x98,hang3,7); LCD_PutString(0,4,\死亡\ Write_Score(3,7,allpoints); } }

#include #include \#include \

#include \

/*--------------------------------------------------------------------------------------------------------------------------- 声明全局变量,不能赋值,只是声明;本函数中用时会去其他函数(那个函数已对他进行了定义并赋了初值)中找,

----------------------------------------------------------------------------------------------------------------------------*/

extern uchar a[]; extern uchar b[]; extern uchar c[]; extern uchar flag; extern uint timestatus;

/*--------------------------------------------------------------------------------------------------- 主程序

----------------------------------------------------------------------------------------------------*/ void main(void) { WELA=0; DULA=0; Init_IO(); Init_12864(); Init_Time(); ClrScreen(); Clr_GDRAM(); while(1) { Keyscan(); statuschange(); if(timestatus==10) { timestatus=0; Add_Point(); //显示食物,若吃到,则更新首点坐标,并重新放置食物 Stat_Point(); //首点坐标更新 Draw_Point(a[0],b[0],0); //加上首点,即第一次画的点

Bump_Wall(); Draw_Point(a[flag],b[flag],1); //去掉尾点,即第一次画的点 Last_Point(); //尾点坐标更新 Self_Bump(); }

if(speed==0) { if(timestatus==2) { timestatus=0; Add_Point(); 并重新放置食物 Stat_Point(); Draw_Point(a[0],b[0],0); Bump_Wall(); Draw_Point(a[flag],b[flag],1); Last_Point(); Self_Bump(); } } Draw_all_lines(); } }

//显示食物,若吃到,则更新首点坐标,//首点坐标更新 //加上首点,即第一次画的点 //去掉尾点,即第一次画的点 //尾点坐标更新


基于STC89C52单片机贪吃蛇做法.doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:上海2017年农村信用社招聘:公基考试试卷

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: