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 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 单片机课程设计,基于AT89C51和LCD-12864的贪吃蛇游戏 -> 正文阅读

[嵌入式]单片机课程设计,基于AT89C51和LCD-12864的贪吃蛇游戏

前言

课程设计报告以及keil文件和protues仿真在文末。


一、设计内容及要求

设计一个贪吃蛇游戏,使其具有以下游戏规则:

????????①当没有改变方向时,贪吃蛇沿原来路径一直前进

????????②贪吃蛇无法回头,只能异于当前方向改变行动

????????③蛇头碰到蛇身时死亡,游戏结束

????????④贪吃蛇吃到豆子则蛇身增加

????????⑤蛇头碰到墙壁时死亡,游戏结束

????????⑥当蛇长达到17及以上时出现山洞出口,进入则游戏胜利

二、系统的硬件设计

  • 主控芯片为AT89C51
  • LCD-12864为显示器输出
  • 多个按键作为控制器

2.1? Protues仿真图

2.2? 主控芯片连接

?

?其中P0口连接LCD-12864的DB0~DB7,P2.0~P2.1连接LCD两个片选端,P2.2~P2.4连接LCD的指令线,读写线,以及电源线,P1.0~P1.4连接控制的四个按键。

2.3? LCD-12864连接

?

?分别连接至AT89C51的引脚

2.4? 控制按键连接

?此法连接,当按下按键后,相应端口置零

三、系统的软件设计

3.1? 贪吃蛇算法介绍

贪吃蛇游戏算法的实现,即如何通过液晶屏显示蛇的移动。

????????1、其实蛇看似移动的过程中,实质只有两个点再变,即蛇头前进方向增加一个点,蛇尾减少一个点。

????????2、知道如何显示蛇的移动后,再一个关键问题就是蛇的转折问题,如何控制蛇尾消失的点沿着蛇的路径。通俗的说就是蛇怎么实现曲折移动,这里就用到了循环队列,每次蛇头前进方向发生变化后,队列增加一个结点,结点中包含蛇头方向变化的位置,以及蛇头转变的方向。

????????3、蛇尾每次移动的过程中都会与队列头指针所储存的位置做一次判断,当蛇尾到达这一位置后,从结点中取出保存的蛇头的移动方向赋给蛇尾,结点出队列即删除这一结点。

????????4、由于队列是先进先出,所以每前进一步会先push进蛇头的节点,再pop出蛇尾的节点,即实现了蛇的曲折运动。

3.2? 典型算法实现

3.2.1? 采用循环队列存储蛇头的转向信息

????????存储蛇头转向的信息使用了step记录,即每走一步使step+1,初始化蛇头step>蛇尾step,当按下按键时代表蛇头发生转向,用循环队列记录此时蛇头step坐标入队,同时使队尾指针+1,当不停前进蛇尾到达此step时,代表之前蛇头在此发生转向,则可不用具体xy坐标记录信息,从而节省存储空间。

// 按键扫描
void Key_Scan(void){
	if (KEY0 == 0)
		pause();
	else if (KEY1 == 0) {
		if (direction != 2) { //蛇不能直接掉头
			direction = 1;
			tailtrun_step[rear] = head_step;
			tailtrun_direction[rear] = 1;
			rear = (rear + 1) % 20;
		}
	}
	else if (KEY2 == 0) {
		if (direction != 1) {
			direction = 2;
			tailtrun_step[rear] = head_step;
			tailtrun_direction[rear] = 2;
			rear = (rear + 1) % 20;
		}
	}
	else if (KEY3 == 0) {
		if (direction != 4) {
			direction = 3;
			tailtrun_step[rear] = head_step;
			tailtrun_direction[rear] = 3;
			rear = (rear + 1) % 20;
		}
	}
	else if (KEY4 == 0) {
		if (direction != 3) {
			direction = 4;
			tailtrun_step[rear] = head_step;
			tailtrun_direction[rear] = 4;
			rear = (rear + 1) % 20;
		}
	}
}

3.2.2??根据行列具体点亮或熄灭LCD-12864某一个点

?????????由于LCD-12864的点阵点亮是八位DB0~DB7一次性操作一个page,代表一次只能八位一起操作,无法根据某一点的line,column点亮一个点,这里采用了位与或的思想,即根据某一点的line算出此坐标点对应的page中所在的位,后读取这点所在整列的数据与此位进行位或,即可在不改变原始数据的情况下点亮此点,熄灭相似,先对位信息进行取反,后与所在整列的数据与此位进行位与,即可熄灭某一具体点。

// 点亮一个点,行列
void show_p(uint8 screen, uint8 line, uint8 column) {
	SelectScreen(screen);
	
	dat = read_LCD_data(line / 8, column);
	Set_page(line/8);	
  Set_column(column);
	write_LCD_data(dat | bitTo16(line % 8));
}
// 熄灭一个点,行列
void out_p(uint8 screen, uint8 line, uint8 column) {
	SelectScreen(screen);
	
	dat = read_LCD_data(line / 8, column);
	Set_page(line/8);	
  Set_column(column);
	write_LCD_data(dat & ~(bitTo16(line % 8)));
}

3.2.3 ?碰撞检测

????????同样采取位与的思想,函数传入具体点的line,column坐标,读取此列的信息,后进行位与操作,若结果不为零,则代表此点已被点亮,表示发生碰撞(蛇身,墙壁)。

// 碰撞检测
void hit_block(uint8 line, uint8 column) {
	dat = read_LCD_data(line * 2 / 8, column * 2);
	
	Set_page(line * 2 /8);	
	Set_column(column * 2);
	if ((dat & bitTo16(line * 2 % 8)) != 0)
		over();
}

3.2.4 ?2×2点扩大

??????由于一次只亮一个点,导致贪吃蛇和豆子会很小,对视觉和操作是一个很大的考验,于是可以使用比例扩大到一个点为2×2,使得游戏界面变得更加亲和。对于原先的1点扩大到2个点,我使用了每个点对应一个坐标,使得4个点是一体的,为后续的函数书写提供极大便利。

?

?

// 2×2合并为一个点
void show_bp(uint8 screen,uint8 line,uint8 column){
	SelectScreen(screen);
	
	start_line = line * 2;start_column = column * 2;
	for(j=0;j<2;j++){
		dat = read_LCD_data(start_line / 8, start_column + j);
		write_LCD_data(dat | bitTo16(start_line % 8));
		dat = read_LCD_data(start_line / 8, start_column + j);
		write_LCD_data(dat | bitTo16(start_line % 8 + 1));
	}
	Set_page(start_line / 8);	//前面设置完会自动+1,需重新设置回来
	Set_column(start_column + 1);
}
void out_bp(uint8 screen,uint8 line,uint8 column){
	SelectScreen(screen);
	
	start_line = line * 2;start_column = column * 2;
	for(j=0;j<2;j++){
		dat = read_LCD_data(start_line / 8, start_column + j);
		write_LCD_data(dat & ~( bitTo16(start_line % 8)));
		dat = read_LCD_data(start_line / 8, start_column + j);
		write_LCD_data(dat & ~( bitTo16(start_line % 8 + 1)));
	}
	Set_page(start_line / 8);	//前面设置完会自动+1,需重新设置回来
	Set_column(start_column + 1);
}

3.2.5 ?字模算法

????????由于LCD-12864采用的是点阵点亮,若想显示具体汉字信息,则需使用16×16的字模运算。可使用“PCtoLCD2002”软件进行字模提取。?

?在具体调用时,应设计相应算法,适应具体字模,例如16×16,由于一次只能书写8位,16则需分两次书写,先写上面的8×16,再写下方的8×16。

// 16×16字模
void show_ch(uint8 screen,uint8 page,uint8 column,uint8 *p)
{
	uint8 i;
	SelectScreen(screen);
	Set_page(page);
	Set_column(column);
	
	for(i=0;i<16;i++)	//采用16*16的字模
	{
		write_LCD_data(p[i]);
	}
	
	Set_page(page+1);
	Set_column(column);
	for(i=0;i<16;i++)	//采用16*16的字模,"小四号字"
	{
		write_LCD_data(p[i+16]);
	}
}
//游戏开始结束字模
uint8 code ch[]=
{
0x10,0x60,0x02,0x8C,0x00,0x08,0xF9,0x4E,0xC8,0x20,0x58,0x4F,0x48,0xC8,0x08,0x00,
0x04,0x04,0x7E,0x81,0x40,0x30,0x0F,0x40,0x7F,0x00,0x44,0x84,0x7F,0x04,0x04,0x00,/*"游",0*/

0x00,0x08,0x48,0x88,0x08,0xC8,0x38,0x40,0x40,0x40,0xFF,0x20,0x22,0xAC,0x20,0x00,
0x00,0x20,0x10,0x0C,0x03,0x04,0x18,0x80,0x40,0x20,0x17,0x18,0x26,0x41,0xF0,0x00,/*"戏",1*/

0x80,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x82,0x82,0xFE,0x82,0x82,0x82,0x80,0x00,
0x00,0x80,0x40,0x30,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,/*"开",2*/

0x10,0x10,0xF0,0x1F,0x10,0xF0,0x00,0x40,0xE0,0x58,0x47,0x40,0x50,0x60,0xC0,0x00,
0x40,0x22,0x15,0x08,0x16,0x21,0x00,0x00,0xFE,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,/*"始",3*/

0x20,0x30,0xAC,0x63,0x20,0x18,0x08,0x48,0x48,0x48,0x7F,0x48,0x48,0x48,0x08,0x00,
0x22,0x67,0x22,0x12,0x12,0x12,0x00,0xFE,0x42,0x42,0x42,0x42,0x42,0xFE,0x00,0x00,/*"结",4*/

0x04,0x04,0xE4,0x24,0x24,0x24,0x24,0xFF,0x24,0x24,0x24,0x24,0xE4,0x04,0x04,0x00,
0x40,0x40,0x27,0x22,0x12,0x0A,0x06,0xFF,0x06,0x0A,0x12,0x22,0x27,0x40,0x40,0x00,/*"束",5*/

0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,/*"!",6*/
};
// 游戏开始界面
void start(){
	show_im(1, 2, 0 * 16, image1);
	show_ch(1, 4, 2 * 16, ch + 32 * 0);
	show_ch(1, 4, 3 * 16, ch + 32 * 1);
	show_ch(2, 4, 0 * 16, ch + 32 * 2);
	show_ch(2, 4, 1 * 16, ch + 32 * 3);
	show_ch(2, 4, 2 * 16, ch + 32 * 6);
	show_ch(2, 4, 3 * 16, ch + 32 * 6);
	pause();
	ClearScreen(0);
}

附录

百度网盘,提取码:r70l

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-10-08 11:56:38  更:2021-10-08 11:57:25 
 
开发: 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 5:25:02-

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