光立方實現3D貪吃蛇

這段代碼是貪吃蛇的核心代碼,一般貪吃蛇只有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 即可。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章