这段代码是贪吃蛇的核心代码,一般贪吃蛇只有4个方向,这个是6个方向也就是3D的。
蛇能自己移动,用函数Snake_Move和Change_Direction实现。
我使用的是STC12C5A60S2,所以要更改的,只有以LED开头的函数
只要能实现一个点亮指定位置(x,y,z)灯的函数Led_Set_Bit
/******************************************************************************
* 文 件: Snake.c
* 作 者: ZhnJa
* 修改日期: 2013-7-10
* 说 明: 贪吃蛇相关
******************************************************************************/
#include "MyType.h"
#include "LED_CMD.H"
#include "snake.h"
#include "STC12C5A60S2.h"
#include <stdlib.h>
#define WidthMax 4 //蛇最寸高度
#define HeightMax 4 //蛇最大长度
#define LengthMax 4 //蛇最大长度
#define MaxLength 20 //总长度
#define Up 6
#define Down 5
#define Left 4
#define Right 3
#define For 2
#define Rea 1
typedef struct _Food //食物结构体
{
uchar x;/*食物的横座标*/
uchar y;/*实物的纵座标*/
uchar z;/*实物的z座标*/
uchar yes;/*是否出现食物的标志,0表示未产生,1表示产生*/
}Food;/*食物*/
typedef struct _Point //点结构体
{
uchar x;
uchar y;
uchar z;
}Point;
typedef struct _Snake
{
uchar x[MaxLength]; //蛇身节点的横座标
uchar y[MaxLength]; //蛇身节点的纵座标
uchar z[MaxLength]; //蛇节点
uchar node;/*蛇长度*/
uchar direction;/*蛇移动方向*/
uchar life;/*蛇是否存活标志,0死亡,1存活,2表示暂停*/
}Snake;
xdata Snake snake={{1,2,3},{1,1,1},{1,1,1},3,Up,1};
xdata Food food={1,4,4}; //食物
Point TailPoint;//存放蛇尾巴节点的临时变量
Point NextPoint;//存放蛇下一次移动的位置
/********************************************
* 蛇初始化
*参数:
*功能:
*********************************************/
void Init_Snake()
{
unsigned char i;
for(i=0;i<=2;i++)
LED_Set_Bit(snake.x[i],snake.y[i],snake.z[i]);
LED_Set_Bit(food.x,food.y,food.z);
}
/********************************************
* 蛇移动函数
*参数:无
*功能:删除最后一个节点,点亮下一个节点
*********************************************/
uchar Snake_Move()
{
uchar i;
TailPoint.x=snake.x[0]; //保存蛇尾
TailPoint.y=snake.y[0];
TailPoint.z=snake.z[0];
for(i=0;i<snake.node-1;i++) //依次向尾部方向移动蛇各个节点的座标
{
snake.x[i]=snake.x[i+1];
snake.y[i]=snake.y[i+1];
snake.z[i]=snake.z[i+1];
}
switch(snake.direction)
{
case Up:{snake.z[snake.node-1]+=1;break;}
case Down:{snake.z[snake.node-1]-=1;break;}
case Left:{snake.x[snake.node-1]-=1;break;}
case Right:{snake.x[snake.node-1]+=1;break;}
case For:{snake.y[snake.node-1]+=1;break;}
case Rea:{snake.y[snake.node-1]-=1;break;}
}
LED_Reset_Bit(TailPoint.x,TailPoint.y,TailPoint.z);
LED_Set_Bit(snake.x[snake.node-1],snake.y[snake.node-1],snake.z[snake.node-1]);
return 1;
}
bit IsLive()
{
uchar i=0;
//计算下一个点
NextPoint.x=snake.x[snake.node-1];
NextPoint.y=snake.y[snake.node-1];
NextPoint.z=snake.z[snake.node-1];
switch(snake.direction)
{
case Up:{NextPoint.z+=1;break;}
case Down:{NextPoint.z-=1;break;}
case Left:{NextPoint.x-=1;break;}
case Right:{NextPoint.x+=1;break;}
case For:{NextPoint.y+=1;break;}
case Rea:{NextPoint.y-=1;break;}
}
//判断蛇有没有撞到自身
for(i=0;i<=snake.node-1;i++)
{
if((snake.x[i]==NextPoint.x)&&(snake.y[i]==NextPoint.y)&&(snake.z[i]==NextPoint.z))
{
snake.life=0;
return 0;
break;
}
}
//判断蛇有没有撞到墙
if(NextPoint.x>=1&&NextPoint.x<=4
&&NextPoint.y>=1&&NextPoint.y<=4
&&NextPoint.z>=1&&NextPoint.z<=4)
return 1;
else
{
snake.life=0;
return 0;
}
}
bit Change_Direction()
{
uchar olddir=snake.direction;
if(snake.x[snake.node-1] < food.x)
snake.direction = Right;
else if(snake.x[snake.node-1] > food.x)
snake.direction = Left;
else if(snake.y[snake.node-1] <food.y)
snake.direction = For;
else if(snake.y[snake.node-1] > food.y)
snake.direction = Rea;
else if(snake.z[snake.node-1] > food.z)
snake.direction = Down;
else if(snake.z[snake.node-1] < food.z)
snake.direction = Up;
return 1;
}
//功能:吃食并且产生下一个实物的座标
//返回值:1表示吃到食物,0表示未吃到食物
bit EatFood(void)
{
uchar i;
if(((snake.x[snake.node-1])==food.x)&&((snake.y[snake.node-1])==food.y)&&(snake.z[snake.node-1]==food.z)) //如果吃到食物
{
for(i=snake.node;i>0;i--) //依次向头部方向移动蛇各个节点的座标
{
snake.x[i]=snake.x[i-1];
snake.y[i]=snake.y[i-1];
snake.z[i]=snake.z[i-1];
}
snake.x[0]=TailPoint.x; //恢复尾巴座标
snake.y[0]=TailPoint.y;
snake.z[0]=TailPoint.z;
snake.node++; //节点个数加1
//以下程序段为产生食物
do
{
food.yes=1;//实物产生标志置1
GetNewFoodLoc(&food.x,&food.y,&food.z);//随机产生新的食物的座标
for(i=0;i<snake.node-1;i++)
{
if((snake.x[i])==food.x&&((snake.y[i])==food.y)&&(snake.z[i]==food.z)) //判断食物出现的位置是否在蛇身上
{
food.yes=0; //食物产生标志置0
break;
}
}
}while(!food.yes);//直到产生的食物不在蛇身上为止
LED_Set_Bit(food.x,food.y,food.z);//产生新的食物
return 1;
}
return 0;
}
//读取定时器的随机值来获得食物座标,同时不能越界
void GetNewFoodLoc(uchar *x,uchar *y,uchar *z)
{
*x=TH0%4+1;
*y=TL0%4+1;
*z=(TL0+TH0)%4+1;
}
void Change_Direction2()
{
uchar olddir=snake.direction;
do{
snake.direction=rand()%6+1;
}
while(snake.direction == olddir);
}
//表示食物的LED灯闪烁
void Shine_Food()
{
LED_Shine(food.x,food.y,food.z);
}
指定位置灭LED灯Led_Reset_Bit 以及 让LED闪烁的函数LED_Shine 即可。