《单片机原理及应用》课程设计
题 目: 基于AT89C52的贪吃蛇小游戏
专 业: 电气工程及其自动化
姓 名: 杨从宏 11121845 (报告设计)
宋凯 11121676 (实物制作)
刘伟军 11121951 (程序)
指导老师: 高守玮
成绩:
基于AT89C52的贪吃蛇小游戏
课程设计内容
利用89c51单片机设计一款8*8led点阵的贪吃蛇游戏。
游戏说明:游戏界面为一块8*8的led显示板,贪吃蛇的起点为左下角三个点,被吃的点随机产生。接通电源后,左下角的三个点亮起来,按一下游戏的上键后,游戏开始。游戏开始后,用上、下、左、右四个键控制贪吃蛇的行走方向,当贪吃蛇吃到随机产生的红点,就会加长,并同时产生另外一个红点,此时通过用上、下、左、右四个键控制贪吃蛇的行走方向去吃下一个点,吃的越多,蛇身就越长,谁的蛇身最长,谁就获胜。当贪吃蛇碰到游戏边界时,游戏结束,并恢复游戏的初始态,当再次按下上键时,游戏重新开始。
关于贪吃蛇
《圣经》里,蛇引诱夏娃吃了苹果之后,就被贬为毒虫,是阴险的象征。因此蛇吃东西是将整只动物吞进去的,大概在文艺复兴的时候就有人发明的一种游戏,是现在贪吃蛇的前身。后来慢慢的发展就变成了今天的贪吃蛇游戏。
贪吃蛇,之所以取这样的名字,其用意还是很明显的,贪吃蛇其实并不贪,它是人不断向前追求的象征,就像现代的人只有不断努力向前才能得到自己想要的。而食物也是随机出现的,就像现在社会存在的机会,而我们只有找好自己的目标才能成功。
虽然现在市面上存在着各种各样的游戏版本,可是贪吃蛇其市场还是相当大的。因为它的特殊性在于它能吸引人更深入,爱不释手,随着游戏速度不断加快,其刺激性也更强。 贪吃蛇游戏制作可以说该游戏的优势在于它的简单易行,不论是手机、还是小游戏机、电脑,都能很快顺利的运行。对于在外忙碌的人,不可能花费大量时间在娱乐上,大型游戏是行不通的,这样的小游戏刚好迎合了他们的需求。但是它的缺点也主要在它的简单性,游戏本身太 过于简单,无法满足大型游戏主的需求。但是这样的小游戏主要对象是针对那些需要有些小东西来调剂生活的人们,给他们的生活带来些精彩。
设计要求分析
利用方向键来改变蛇的运行方向,并且蛇不能向后走。
在随机的地方产生食物。
吃到食物后蛇的身体加长,碰到壁或自身游戏结束,否则正常进行。
C程序和proteus仿真原理图
#include "main.h"
unsigned char table[31]={0,10,20};
unsigned char count;
unsigned char Direction;
unsigned char T;
int tt;
unsigned char Flag_Shift,Flag_Over,flag3,Flag_Dot,Flag_Draw;
unsigned char u;
void main()
{
Init();
while(1)
{
if (Flag_Dot == 1) //开启按键按下
Random_Dot(); //随即显示一个点
if (Flag_Shift == 1)
Shift(); //贪食蛇移动
Scan_Key();
Display();
}
}
//发送一个字节数据
void Send_Byte( unsigned char dat)
{
unsigned char i;
LEDARRAY_CLK = 0;
_nop_();
LEDARRAY_LAT = 0;
_nop_();
for( i = 0 ; i < 8 ; i++ )
{
if( dat&0x01 )
{
LEDARRAY_DI = 1;
}
else
{
LEDARRAY_DI = 0;
}
LEDARRAY_LAT = 0;
LEDARRAY_CLK = 1; //上升沿发送数据
// _nop_();
LEDARRAY_CLK = 0;
// _nop_();
dat >>= 1;
}
}
//延时函数,延时1s
void Delay_ms( unsigned int m)
{
unsigned int j;
unsigned int i;
for(i = 0 ; i < m ; i++)
{
for(j = 0 ; j < 123 ; j++);
}
}
//延时函数
void delay(int n)
{
while(n--);
}
//重新初始化
void ReInit()
{
TH0=(65535-50000)/256;
TL0=(65535-50000)%256;
TR0=0;
T=0;
Direction=0;
count=3;
table[0]=0;
table[1]=10;
table[2]=20;
P0=0x00;
P2=0xff;
Delay_ms(500);
Flag_Over=0;
Flag_Dot=2;
Flag_Draw=1;
table[count]=0;
}
//显示
void Display()
{
int x,y;
int j;
unsigned char i;
unsigned char temp = 0x7f;
for (j=0;j<=count;j++) //显示蛇身和食物
{
y=table[j]/10; //十位放列值,行值:1 = 选通 0 = 不选
x=table[j]%10; //个位放行值,列值:0 = 选通 1 = 不选
temp = 0x7f;
for(i = 0 ; i < y ; i++)
{
temp = (temp>>1)|0x80;
}
Send_Byte(temp); //发送列值
temp = 0x80;
for(i = 0 ; i < x ; i++)
{
temp = (temp>>1)&0x7f;
}
Send_Byte(temp); //发送列值
LEDARRAY_LAT = 1; //锁存数据
_nop_();
LEDARRAY_LAT = 0;
_nop_();
delay(50);
}
}
//初始化
void Init()
{
Flag_Draw=1;
Flag_Dot=2;
tt=0;
T=0;
Flag_Shift=0;
Flag_Over=0;
count=3; //蛇身长度为3
EA=1; //开总中断
IT0=1; //低电平触发
ET0=1; //定时器0中断使能
ET1=1; //定时器1中断使能
TMOD=0x21; //定时器0模式1,定时器1模式2
TH0=(65535-50000)/256; //定时器0设定初值
TL0=(65535-50000)%256;
TH1=0x00; //定时器1设定初值
TH1=0x00;
Direction=0; //方向
TR0=0; //定时器0不开启
TR1=1; //定时器1开启
}
//按键扫描
void Scan_Key()
{
if(KEY_Right == 0)
{
if (Flag_Dot==2)
{
Flag_Dot=1; //启动游戏
TR0 = 1; //开始移动
}
if(Direction != Left)
Direction = Right;
}
if(KEY_Down == 0)
{
if(Direction != Up)
Direction = Down;
}
if(KEY_Left == 0)
{
if(Direction != Right)
Direction = Left;
}
if(KEY_Up == 0)
{
if(Direction != Down)
Direction = Up;
}
}
void Shift()
{
int k;
if ( Flag_Draw == 1 )
{
for(k=0;k0)
table[count-1]=table[count-1]-10;
else
Flag_Over=1;
break;
case Up: //向上
if (table[count-1]%10>0)
table[count-1]=table[count-1]-1;
else
Flag_Over=1;
break;
default:
break;
}
Flag_Shift=0;
if (Flag_Over == 0)
{
for (k=0;k