第二十九课 点阵之五 玩贪吃蛇
程序讲解
/*--------------------------------------------------------------*/
//LED8*8显示
/*--------------------------------------------------------------*/
//按键配置
// 上S7
// 左S10 中S11 右S12
// 下S15
#include <reg52.h>
#include "74HC595.H"
#include "Beep.H"
#include "Key_Board.H"
/*--------------------------------------------------------------*/
//全局变量定义
#define len 30 //最大长度
unsigned char disram[8]; //显示缓冲区
unsigned char x[len],y[len]; //蛇身坐标
char dx, dy; //点坐标
unsigned char speed; //移动速度
unsigned char level; //关数
unsigned char life; //生命值
volatile void key_pro(void);
/*--------------------------------------------------------------*/
//定时器初始化
void T0_init(void)
{
TMOD |= 0x01; //定时器0工作在方式1(16位)
TH0 = 0xf8; //2ms
TL0 = 0x36;
IE |= 0x82; //开总中断和定时器0中断
PT0 = 1; //定时器0 中断优先级最高
TR0 = 1; //允许定时器0工作
}
/*--------------------------------------------------------------*/
//定时器初始化
void T1_init(void)
{
TMOD |= 0x10; //定时器1工作在方式2(8位自动装载)
TH1 = 0x00; //65ms
TL1 = 0x00;
IE |= 0x88; //开总中断和定时器1中断
TR1 = 1; //允许定时器1工作
}
/*-------------- ------------------------------------------------*/
//清除显示缓冲区,即清屏
void clr_ram(void)
{
unsigned char i;
for(i = 0; i < 8; i++)
disram = 0x00;
}
/*--------------------------------------------------------------*/
//画点函数,擦点或者绘点(将点的坐标(dx、dy)转换的数据缓冲区)
//点阵左上角坐标为(0, 0) 右下角坐标为(7, 7)
//横坐标为x:0~7 纵坐标为y:0~7
//k = 1 --绘点 k = 0 --擦点
void point1(unsigned char x, unsigned char y, bit k)
{
if(k) disram[x] |= 0x01 << y;
else disram[x] &= ~(0x01 << y);
}
/*--------------------------------------------------------------*/
//定时器中断服务 用来显示点阵
void T0_intservice(void) interrupt 1
{
static unsigned char n;
TR1 = 0; //关闭定时器1
TH0 = 0xf8; //2ms
TL0 = 0x36;
Ser_IN(0x01 << n); //列选
Ser_IN(~disram[n]); //行数据
Par_OUT(); //输出
n++; if(n == 8) n = 0; //循环扫描
TR1 = 1; //开定时器1
}
/*--------------------------------------------------------------*/
//定时器中断服务 用来按键扫描和产生食物的随机坐标
void T1_intservice(void) interrupt 3
{
TH1 = 0x00;
TL1 = 0x00;
key_pro(); //按键扫描
}
/*--------------------------------------------------------------*/
//延时100000+0us 函数定义
void delay(void)
{
unsigned char i,j,k;
for(i=7;i>0;i--)
for(j=74;j>0;j--)
for(k=95;k>0;k--);
}
/*--------------------------------------------------------------*/
//按键扫描 及处理
volatile void key_pro(void)
{
key_scan();
if(key == 6) //上
{
dx = 0; dy = -1;
}
if(key == 14) //下
{
dx = 0; dy = 1;
}
if(key == 9) //左
{
dy = 0; dx = -1;
}
if(key == 11) //右
{
dy = 0; dx = 1;
}
}
/*--------------------------------------------------------------*/
//定点显示,一次只显示一个点
void gotoxy(unsigned char x, unsigned char y)
{
Ser_IN(0x01 << x); //列选
Ser_IN(~(0x01 << y)); //行数据
Par_OUT(); //上升沿输出
delay();
speaker(); //声音
}
/*--------------------------------------------------------------*/
//通关演示
void congrate(void)
{
char i, j;
TR0 = 0;
TR1 = 0;
for(j = 0; j < 5; j++)
{
for(i = j ; i < 8-j; i++)gotoxy(j, i); //此时j 对应x,i 对应y,x不变 y增大,即垂直下移
for(i = j+1 ; i < 8-j; i++)gotoxy(i, 7-j); //此时i 对应x,7- j 对应y,x增大 y 不变,即水平右移
for(i = j+1 ; i < 8-j; i++)gotoxy(7-j, 7-i); //此时7- j 对应x,7- i 对应y,x不变y减小 ,即垂直上移
for(i = j+1 ; i < 7-j; i++)gotoxy(7-i, j); //此时7- i 对应x,j 对应y,x减小 y不变,即水平左移
}
for(j = 4; j >= 0; j--)
{
for(i = 6-j ; i >= j+1; i--)gotoxy(7-i, j); //此时7- i 对应x,j 对应y,x减小 y不变,即水平左移
for(i = 7-j ; i >= j+1; i--)gotoxy(7-j, 7-i); //此时 7- j 对应x,7- i 对应y,x不变y减小 ,即垂直上移
for(i = 7-j ; i >= j+1; i--)gotoxy(i, 7-j); //此时 i 对应x,7- j 对应y,x增大 y 不变,即水平右移
for(i = 7-j ; i >= j; i--)gotoxy(j, i); //此时 j 对应x,i 对应y,x不变 y增大,即垂直下移
}
}
/*--------------------------------------------------------------*/
//主函数
void main (void)
{
unsigned char i; //通用循环变量
unsigned char num; //蛇的长度
bit food, over; //食物和结束标志位
unsigned char foodx, foody; //食物坐标
life = 3; //设定生命次数
speed = 8; //设定初始速度
num = 2; //设定初始蛇身长度
T0_init(); //定时器初始化
T1_init();
clr_ram(); //清显示缓冲区
x[0] = 1; //初始化位置
y[0] = 2;
dx = 1; //向右运动
while(1)
{
x[0] += dx; y[0] += dy;
x[0] &= 0x07; y[0] &= 0x07; //穿墙
if(!food) //放置食物
{
again: foodx = TL1&0x07; //随机
foody = TH1&0x07;
for(i = 0; i < num; i++)
{
if(foodx == x && foody == y) //如果显示食物的坐标和蛇身重叠
goto again; //则重新获取食物
}
point1(foodx, foody, 1); //显示食物
food = 1; //置食物标志位
}
if(x[0] == foodx && y[0] == foody) //吃到食物
{
speaker(); //声音指示
num++;
food = 0; //清食物标志位
}
for(i = 0; i < num; i++) //显示蛇身
point1(x, y, 1);
point1(x, y, 0); //清蛇尾
for(i = 1; i < num; i++) //判断是否自撞
{
if((x[0] == x) && (y[0] == y)) //蛇头坐标和蛇身某点坐标相同则自撞
over = 1; //置结束标志位
}
for(i = 0; i < speed; i++) delay(); //蛇运动速度
for(i = 0; i < num; i++) //蛇移动蛇身
{
x[num-i] = x[num-i-1]; //前一点的坐标给后一点
y[num-i] = y[num-i-1];
}
if(num > 10 + level) //过关
{
if(num > 28) //通关!!!
{
while(1){congrate();inverse = ~inverse;}
}
delay(); speaker(); //声音指示
if(speed > 1) speed--; //速度加一
num = 2; //重定蛇长
level += 1; //总的蛇长增加1
clr_ram(); //清除屏幕
goto again; //新的一关开始
}
if(over) //判断是否结束
{
clr_ram(); //清除屏幕
num = 2; //重新设定蛇长
point1(foodx, foody, 1); //重新放置食物
x[0] = 1; y[0] = 2; //起点位置
dx = 1; //向右运动
over = 0; //清结束标志位
life--; //生命值减1
}
if(!life) congrate(); //生命用完
}
}
本节重点:
1、前面知识的综合应用,关键在于理解
演示视频:
http://v.youku.com/v_show/id_XOTIzNjU3NDg=.html
相关程序:https://static.assets-stash.eet-china.com/album/old-resources/2009/6/5/44739cf9-2cc5-4ee8-9385-0e99e3fa7878.rar
用户206768 2009-6-9 07:27
用户209148 2009-6-6 12:23
用户518079 2009-6-5 20:36
tengjingshu_112148725 2009-6-5 14:30