IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> C51自动贪吃蛇程序 -> 正文阅读

[嵌入式]C51自动贪吃蛇程序

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

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-09 11:49:55  更:2021-12-09 11:50:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 12:25:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码