C51平台加点阵屏可以贪吃蛇,程序实现如下,但还不够智能,只能看一步路,还是会出现把自己困死的情况,看提供一种思路,请大家能加以补充,提供更好的思路,感谢大家
单片机:STC89C52RC
点阵:8*8单色点阵
点阵驱动:
行:74HC595
列:P0口
主函数
#include "config.h"
//*********主函数*************//
void main()
{
initTimer0();
while(1)startSnake();
}
贪吃蛇源码
/*********************************************************************
贪吃蛇源码snake.c
**********************************************************************/
#include "config.h"
#define snake_fast 5
//******与蛇相关的结构体定义*************//
static struct Food
{
unsigned char x; // 食物的横坐标
unsigned char y; // 食物的纵坐标
// unsigned char yes;
}food; // 食物结构体
struct Snake
{
char x[SNAKE_Max_Long];
char y[SNAKE_Max_Long];
unsigned char Long; // 蛇的长度
unsigned char Life; // 蛇的生命
// unsigned char Score; // 蛇的分数,本例中没使用
unsigned char Level; // 蛇的等级
unsigned char Dir; // 蛇移动方向
}snake; // 蛇结构体
struct VSnake
{
char x[SNAKE_Max_Long];
char y[SNAKE_Max_Long];
unsigned char Long; // 蛇的长度
unsigned char Life; // 蛇的生命
// unsigned char Score; // 蛇的分数,本例中没使用
unsigned char Level; // 蛇的等级
unsigned char Dir; // 蛇移动方向
}vsnake; // 蛇结构体
//****************************************//
enum Dir{up, down, left, right}; //方向枚举
//***********变量声明***************//
unsigned char DispRAM[8]={0}; // 蛇坐标缓存
unsigned char tCount;
unsigned char keyValue=right;
unsigned char speedLevel=snake_fast;
extern uchar keyVal; // 来源于key.c
//**********************************//
// 用此函数来产生食物最好使蛇的长度不要那么长,蛇越长,点越难找,递归越深
static void createFood()
{
unsigned char i;
food.x = rand()%WIDTH;
food.y = rand()%LENGTH;
for(i=0; i<snake.Long; i++)
{
if(food.x==snake.x[i] && food.y==snake.y[i])
createFood();
}
}
//****************初始化蛇的位置等***********************//
static void initSnake()
{
//********清除内存数据**********//
unsigned char i;
for(i=0; i<SNAKE_Max_Long; i++)
{
snake.x[i]=-1;
snake.y[i]=-1;
}
//********初始化蛇参数**********//
snake.Long=2; // 初始化蛇的长度为两节
snake.Life=1; //初始化蛇活着
snake.Dir=right;
snake.x[1]=0;
snake.y[1]=2;
snake.x[0]=1;
snake.y[0]=2;
createFood();
}
//********************刷新界面*******************//
static void drawSnake()
{
unsigned char i=0;
for(i=0; i<8; i++) DispRAM[i]=0;
for(i=0; i<snake.Long; i++)
DispRAM[snake.y[i]] |= 1<<snake.x[i];
scanDisplay(DispRAM);
drawPoint(food.x, food.y);
}
char SnakeTryDead()
{
char i;
//**********************蛇之dead***************************//
// 限定蛇活动范围,超范围就dead
if((vsnake.x[0]>(WIDTH-1)) || (vsnake.x[0]<0) || (vsnake.y[0]>(LENGTH-1)) || (vsnake.y[0]<0))
{
return 0;
}
// 蛇自杀检测
for(i=4; i<=vsnake.Long; i++)
{
if(vsnake.x[i-1]==vsnake.x[0] && vsnake.y[i-1]==vsnake.y[0])
{
return 0;
}
}
return 1;
}
char SnakeAutuRun(char myDir)
{
char i;
char scal=1;
vsnake.Dir = snake.Dir;
vsnake.Long=snake.Long;
for(i=0;i<=snake.Long;i++)
{
vsnake.x[i]=snake.x[i];
vsnake.y[i]=snake.y[i];
}
switch(myDir)
{
case up: if(vsnake.Dir != down) vsnake.Dir=up; break;
case down: if(vsnake.Dir != up) vsnake.Dir=down; break;
case left: if(vsnake.Dir != right) vsnake.Dir=left; break;
case right: if(vsnake.Dir != left) vsnake.Dir=right; break;
default: break;
}
// 蛇身体坐标移动,蛇头方向坐标逐渐向蛇尾方向移动
for(i=vsnake.Long; i>0; i--)
{
vsnake.y[i]=vsnake.y[i-1];
vsnake.x[i]=vsnake.x[i-1];
}
// 重新获得蛇的头部位置
switch(vsnake.Dir)
{
case up: vsnake.y[0]-=1; break;
case down: vsnake.y[0]+=1; break;
case left: vsnake.x[0]-=1; break;
case right: vsnake.x[0]+=1; break;
default: break;
}
// 蛇吃到食物
if(vsnake.x[0]==food.x && vsnake.y[0]==food.y)
{
scal+=1;
}
if(SnakeTryDead())
{
return scal;
}
else
{
return 0;
}
}
char SnakeGetApple()
{
char step=0;
char i=0;
if(food.x>snake.x[0])
step = 3;
else if(food.x<snake.x[0])
step = 2;
if(food.y>snake.y[0])
step = 1;
else if(food.y<snake.y[0])
step = 0;
return step;
}
//********************蛇运动坐标刷新*******************//
static void runSnake()
{
unsigned char i;
char step;
step=SnakeGetApple();
if(SnakeAutuRun(step))
keyVal=step;
else
{
for(i=0;i<4;i++)
{
if(SnakeAutuRun(i))
keyVal=i;
}
}
changeDir(keyVal);
// 蛇身体坐标移动,蛇头方向坐标逐渐向蛇尾方向移动
for(i=snake.Long; i>0; i--)
{
snake.y[i]=snake.y[i-1];
snake.x[i]=snake.x[i-1];
}
// 重新获得蛇的头部位置
switch(snake.Dir)
{
case up: snake.y[0]-=1; break;
case down: snake.y[0]+=1; break;
case left: snake.x[0]-=1; break;
case right: snake.x[0]+=1; break;
default: break;
}
// 蛇吃到食物
if(snake.x[0]==food.x && snake.y[0]==food.y)
{
snake.Long++;
createFood();
}
}
//*******************方向按键处理***********************//
static void changeDir(unsigned char key)
{
// 方向按键的规则
switch(key)
{
case up: if(snake.Dir != down) snake.Dir=up; break;
case down: if(snake.Dir != up) snake.Dir=down; break;
case left: if(snake.Dir != right) snake.Dir=left; break;
case right: if(snake.Dir != left) snake.Dir=right; break;
default: break;
}
}
//********************启动贪吃蛇游戏(主函数)*********************//
void startSnake()
{
uchar i=0;
int j;
initSnake();
while(snake.Life)
{
changeDir(keyValue);
// 蛇运行的速度,由speedLevel决定
if(tCount >= speedLevel)
{
tCount=0;
runSnake();
}
//**********************蛇之dead***************************//
// 限定蛇活动范围,超范围就dead
if((snake.x[0]>(WIDTH-1)) || (snake.x[0]<0) || (snake.y[0]>(LENGTH-1)) || (snake.y[0]<0))
{
for(j=0;j<1000;j++)
{
drawSnake();
}
snake.Life=0;
snake.Level=1;
speedLevel=snake_fast;
keyVal=right;
}
// 蛇自杀检测
for(i=4; i<=snake.Long; i++)
{
if(snake.x[i-1]==snake.x[0] && snake.y[i-1]==snake.y[0])
{
for(j=0;j<1000;j++)
{
drawSnake();
}
delayMs(500); // 延一下时
snake.Life=0;
snake.Level=1;
speedLevel=snake_fast;
keyVal=right;
}
}
//***********************************************************//
// 等级越高速度越快
if(snake.Long >= SNAKE_Max_Long)
{
for(j=0;j<100;j++)
{
drawSnake();
}
initSnake();
// speedLevel-=5;
keyVal=right;
if(++snake.Level > 5)
{
// 大神,你已经打爆机了,现在从头再来。。。
snake.Level=1;
speedLevel=snake_fast;
}
tCount=0;
}
drawSnake();
}
}
贪吃蛇头文件
#ifndef __SNAKE_H
#define __SNAKE_H
#define WIDTH 8
#define LENGTH 8
#define SNAKE_Max_Long 25 // 蛇最大长度
static void createFood();
static void initSnake();
static void drawSnake();
static void runSnake();
static void changeDir(unsigned char key);
void startSnake();
#endif
延时函数
#include "config.h"
/**************************************************************************
****** 下面所有延时函数均从软件STC-ISP中获得,以12MHz晶振为时钟源
****** STC-ISP软件下载地址:WWW.STCMCU.COM
**************************************************************************/
//void delayUs(unsigned int i)
//{
// while(i--)
// _nop_();
//}
void delay1Ms() //@12.000MHz
{
unsigned char i, j;
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
void delayMs(unsigned int i)
{
while(i--)
{
delay1Ms();
}
}
中断函数
#include "config.h"
extern unsigned char tCount; //来源于snake.c文件
extern unsigned char keyValue; //来源于snake.c文件
//******定时器0初始化*************//
void initTimer0()
{
TMOD |= 0x01;
TL0 = TIMER;
TH0 = TIMER>>8;
TR0 = 1;
ET0 = 1;
EA = 1;
}
//******定时器0中断服务处理*************//
void timer0Handle() interrupt 1
{ // 20ms中断
TL0 = TIMER;
TH0 = TIMER>>8;
keyValue=scanKey();
tCount++;
}
显示函数
#include "8x8lattice.h"
void hc595Write(unsigned char writeVal)
{
unsigned char i;
ST_CP=0;
for(i=0; i<8; i++)
{
SH_CP=0;
DS=((writeVal<<i)&0x80)?1:0;
SH_CP=1;
}
ST_CP=1;
}
void hc238Write(unsigned char writeVal)
{
switch(writeVal)
{
case 0: P0=~(0x01);break;
case 1: P0=~(0x02);break;
case 2: P0=~(0x04);break;
case 3: P0=~(0x08);break;
case 4: P0=~(0x10);break;
case 5: P0=~(0x20);break;
case 6: P0=~(0x40);break;
case 7: P0=~(0x80);break;
default: P0=~(0x00); break;
}
}
void drawPoint(unsigned char x, unsigned char y)
{
hc238Write(y);
hc595Write(0x00);
hc595Write((1<<x));
}
void scanDisplay(unsigned char *pbuff)
{
unsigned char i=0;
hc595Write(0x00);
for(i=0; i<8; i++)
{
hc238Write(i);
hc595Write(pbuff[i]);
hc595Write(0x00);
}
}
显示函数头文件
#ifndef __8X8LATTICE_H
#define __8X8LATTICE_H
#include <reg52.h>
#include <intrins.h>
//=====hc595 引脚定义========
sbit DS = P3^4;
sbit SH_CP = P3^6;
sbit ST_CP = P3^5;
//=====hc238 引脚定义========
//sbit hc238A = P2^0;
//sbit hc238B = P2^1;
//sbit hc238C = P2^2;
//sbit hc238EN = P2^6;
void hc595Write(unsigned char writeVal);
void hc238Write(unsigned char writeVal);
void drawPoint(unsigned char x, unsigned char y);
void scanDisplay(unsigned char *pbuff);
#endif
|