#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
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
/*游戏的初始化值*/
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 \ /*--------------------------------------------------------------------------------------------------------------------------- 声明全局变量,不能赋值,只是声明;本函数中用时会去其他函数(那个函数已对他进行了定义并赋了初值)中找, ----------------------------------------------------------------------------------------------------------------------------*/ 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(); } } //显示食物,若吃到,则更新首点坐标,//首点坐标更新 //加上首点,即第一次画的点 //去掉尾点,即第一次画的点 //尾点坐标更新 百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库基于STC89C52单片机贪吃蛇做法在线全文阅读。
相关推荐: