单片机俄罗斯方块游戏设计大全(设计思路大全,程序大全)
- 格式:doc
- 大小:6.28 MB
- 文档页数:95
本科课程设计题目:基于单片机的8*8LED 俄罗斯方块设计姓名孙俊学号2008130346院(系)物理与信息科学学院电子系专业、年级电子信息科学与技术2008级指导教师刘美容二○一一年十月基于单片机的8x8 俄罗斯方块设计一、设计任务《俄罗斯方块》是一款世人皆知,看似简单实则变化无穷的小游戏。
本次设计以51单片机为基础,设计一款功能简单的8*8点阵俄罗斯方块游戏,我们将以汇编语言编程实现以下操作:图形的显示合成,通过按键控制图形的移动和旋转,满格消行,手动复位等。
本次设计俄罗斯方块功能简单,用单片机的最小系统就能得以实现。
而单片机的最小系统设计中实际上最重要的就是对键盘/显示器接口电路的设计,由于系统功能不同所以要求就不同,接口设计也就不同。
对一个键盘/显示器接口设计应从整个系统出发,综合考虑软、硬件特点。
其中,硬件设计包括初始的设计原理和原理图介绍,到最终的电路图实际焊接以及布局,软件设计我们会给出具体的设计方案,比如图形的显示合成,通过按键控制图形的移动和旋转,满格消行等的设计流程图,以及具体的汇编程序。
二、设计方案本次设计初期是在keil和proteus联合仿真中进行,编程语言为51汇编语言,后期是进行实物焊接。
本次我们采用单片机STC89C52控制模块提供电源,以点阵式LED 显示,采用独立按键,直接在I/O口线上接上按键开关。
因为设计时精简和优化了电路,所以剩余的口资源还比较多,我们使用四个按键,分别是旋转键,下键,左键,右键。
这种方案实现可行,既满足系统功能要求,又减少了系统实现的复杂度。
而由于STC89C52是一种带8K 字节闪烁可编程可檫除只读存储器的低电压,高性能COMOS8的微处理器,该器件采用ATMEL 搞密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
89C52内置8位中央处理单元、256字节内部数据存储器RAM 、8k 片内程序存储器(ROM )32个双向输入/输出(I/O)口、3个16位定时/计数器和5个两级中断结构,一个全双工串行通信口,片内时钟振荡电路。
游戏机的制作:俄罗斯方块目录摘要 (1)1 方案论证……………………………………………………………………….1.1 开发意义…………………………………………………………………1.2 功能介绍………………………………………………………………….2 设计思路………………………………………………………………………….3 硬件电路………………………………………………………………………2.1 74HC573驱动芯片电路…………………………………………………….2.2 8*8LED点阵的接口电路…………………………………………………..2.3单片机最小系统电路………………………………………………………..2.4整体电路图………………………………………………………………….4 系统调试………………………………………………………………………..3.1硬件调试………………………………………………………………………3.2软件调试……………………………………………………………………..5 作品展示………………………………………………………………………….6 元器件清单……………………………………………………………………..7 结束语……………………………………………………………………………..致谢……………………………………………………………………………参考文献………………………………………………………………………….游戏机的制作:俄罗斯方块摘要:近年来随着计算机在社会领域的渗透, 单片机的应用正在不断地走向深入,应用到各个领域。
在实时检测和自动控制的单片机应用系统中,单片机往往是作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构,以及针对具体应用对象特点的软件结合,以作完善。
我做的题目是一个用51单片机制作的游戏机,大致分位软件和硬件2大部分,硬件主要通过5按键、1个8*8LED点阵屏、一个单片机系统,实现积木的左、右、下、变化、复位五个模式,完全达到俄罗斯方块所实现的功能。
************说明******************************此程序包含一个俄罗斯方块.c 文件和一个12864.h 文件********************俄罗斯方块.c文件**************************#include "reg51.h"#include "12864.h"#define uchar unsigned char#define uint unsigned intstatic unsigned long Seed = 1;#define A 48271L#define M 2147483647L#define Q (M / A)#define R (M % A)sbit K1=P3^4;sbit K2=P3^5;sbit K3=P3^6;sbit K4=P3^7;unsigned int idata num[19+2]={0xfff,//第1行,最下面0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行0xfff//第21行,最上面};//定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列unsigned char code Block[28][2]={/** 口口口口口口* 口口口口* 口口口口口口*/{0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},/** 口口口口口口* 口口口口* 口口口口口口*/{0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},/** 口* 口口口口* 口口口*/{0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},/** 口口口* 口口口口* 口*/{0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},/** 口口* 口口口口口口口口* 口口口口口口*/{0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},/*口* 口* 口口口口口* 口*/{0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},/** 口口* 口口*/{0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}};#define PASSSCORE 20struct Jimu{unsigned int dat;char x;unsigned char y;unsigned char type;unsigned char change;}Sign[3];//积木结构体unsigned char SysFlag=0;#define NEWSIGNFLAG 0#define DEADFLAG 1#define PAUSEFLAG 2unsigned char Score=0;unsigned char Level=1;unsigned char DelayCnt=5;/*********************************************************/#define N 25/************************************伪随机数发生器*************************************/ double Random(void){long TmpSeed;TmpSeed=A*(Seed%Q)-R*(Seed/Q);if(TmpSeed>=0)Seed=TmpSeed;elseSeed=TmpSeed+M;return (double)Seed/M;}/************************************** 为伪随机数发生器播种***************************************/ void InitRandom(unsigned long InitVal){Seed=InitVal;}//延时子程序void Delay(unsigned int t){unsigned int i,j;for(i=0;i<t;i++)for(j=0;j<10;j++);}/*********************************初始化MPU**********************************/void InitCpu(void){TMOD=0x0;TH0=0;TL0=0;TR0=1;ET0=1;EX1=1;EA=1;TCON|=0x04;}/**************************** welcome 游戏选择界面/**********************/void welcome(){Lcd_WriteStr(0,0,"欢迎来玩");Lcd_WriteStr(0,1,"俄罗斯方块");Lcd_WriteStr(0,2,"设置按K1");Lcd_WriteStr(0,2,"开玩按K2");}/*************俄罗斯方块部分/******************************画墙壁,初始化界面*******************************/void DrawBoard(void){unsigned char n;for(n=0;n<12;n++){Lcd_Rectangle(3*n,0,3*n+2,2,1);Lcd_Rectangle(3*n,60,3*n+2,62,1);}for(n=0;n<20;n++){Lcd_Rectangle(0,3*n,2,3*n+2,1);Lcd_Rectangle(33,3*n,35,3*n+2,1);}Lcd_WriteStr(4,0,"经典游戏");Lcd_WriteStr(3,2,"Score:");Lcd_WriteStr(3,3,"Level:");}/*********************************** 游戏结束处理************************************/ void GameOver(void){if((SysFlag&(1<<DEADFLAG))!=0)Lcd_WriteStr(3,1,"You Fail");elseLcd_WriteStr(3,1,"You Pass");}unsigned int code MaskTab[16]={0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000};/**********************************根据积木图标左下坐标X,Y来画出积木图标***********************************/void DrawSign(struct Jimu Temp,unsigned char DrawMode){unsigned char m,n;for(m=0;m<4;m++)for(n=0;n<4;n++){if((Temp.dat&MaskTab[4*m+n])!=0)Lcd_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode);}}/********************************将积木图标值融入num数据中也即把积木图标固定,无法再下降*********************************/FixSign(void){unsigned char m,n;for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[4*m+n])!=0){num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n];}}}/********************************判断积木图标中方块是否与障碍方块重合*********************************/unsigned char CheckIf(void){unsigned char m,n;for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[1].dat&MaskTab[4*m+n])!=0){if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])!=0)return 0;}}return 1;}/********************************判断积木图标是否可以继续下降一格********************************/unsigned char CheckIfDown(void){Sign[1]=Sign[0];//Sign[1].y+=3;//假设下降一格return CheckIf();}/********************************判断积木图标是否可以向左移动*********************************/unsigned char CheckIfLeft(void){Sign[1]=Sign[0];Sign[1].x-=3;return CheckIf();}/********************************判断积木图标是否可以向右移动*********************************/unsigned char CheckIfRight(void){Sign[1]=Sign[0];Sign[1].x+=3;return CheckIf();}/********************************判断是否可以旋转*********************************/unsigned char CheckIfRoll(void){unsigned char i;unsigned int Temp;Sign[1]=Sign[0];if(++Sign[1].change>3)Sign[1].change=0;i=Sign[1].type*4+Sign[1].change;Temp=(unsigned int)Block[i][0]<<8;Temp=Temp|Block[i][1];Sign[1].dat=Temp;return CheckIf();}/********************************寻找满格的行并做消除处理最多寻找4个满行并做消除*********************************/void DelFull(void){unsigned char m,n;unsigned char Temp;unsigned char Flag=0;Temp=(Sign[0].y-2)/3;if(Temp>=20)//防止越过了下边界Temp=1;elseTemp=20-Temp;for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算{if(num[n]==0xfff){Flag=1;for(m=n+1;m<=19;m++){num[m-1]=num[m];}num[m]=0x801;Score++;//每找到一个满行,则分数加1}}if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面{for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画for(n=1;n<=10;n++){if((num[m]&MaskTab[n])==0){if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)!=0)//为加速而做的读象素操作{Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0);}}else{if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作{Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1);}}}}}/*******************************随机产生一个积木图标放到预产生区域并显示出来********************************/void CreatSign(void){unsigned char n;unsigned int Temp;DrawSign(Sign[2],0);//先清除n=Random()*28;Temp=(unsigned int)Block[n][0]<<8;Temp=Temp|Block[n][1];Sign[2].dat=Temp;Sign[2].x=45;Sign[2].y=4*3+2;Sign[2].type=n/4;Sign[2].change=n%4;DrawSign(Sign[2],1);//后画出}void PrintScore(void){unsigned char Str[3];Str[0]=(Score/10)|0x30;Str[1]=(Score%10)|0x30;Str[2]=0;Lcd_WriteStr(6,2,Str);}void PrintLevel(void){unsigned char Str[3];Str[0]=(Level/10)|0x30;Str[1]=(Level%10)|0x30;Str[2]=0;Lcd_WriteStr(6,3,Str);}/********************************游戏的具体过程,也是俄罗斯方块算法的关键部分*********************************/void GamePlay(void){unsigned char m,n;unsigned int Temp;SysFlag|=1<<NEWSIGNFLAG;//刚开始初始化为需要产生新的积木图标InitRandom(TL0);Lcd_WriteStr(3,1,"Playing");PrintScore();PrintLevel();CreatSign();while(1){if((SysFlag&(1<<NEWSIGNFLAG))==1)//判是否需要产生新的积木图标{SysFlag&=~(1<<NEWSIGNFLAG);Sign[0]=Sign[2];CreatSign();Sign[0].x=12;Sign[0].y=14;for(m=0;m<4;m++)//行循环{for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[15-m*4-n])==0)break;}if(n==4)Sign[0].y-=3;}//将积木图标出现置顶for(m=0;m<4;m++)//行循环for(n=0;n<4;n++)//列循环{if((Sign[0].dat&MaskTab[4*m+n])!=0){if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])!=0)SysFlag|=1<<DEADFLAG;}}if((SysFlag&(1<<DEADFLAG))!=0)break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。
基于51单片机的俄罗斯方块游戏代码实现主要包括以下几个方面:
1. 数据结构:使用数据结构来表示游戏中的各种元素,如方块、矩阵等。
2. 导航键控制:通过键盘扫描代码,获取用户输入的导航键(上下左右)信息,以便控制方块的移动。
3. 方块生成:随机生成新的方块,或者根据游戏规则生成特定的方块。
4. 方块移动:根据用户输入的导航键信息,移动当前方块的位置。
5. 方块旋转:根据用户输入的导航键信息,旋转当前方块的角度。
6. 碰撞检测:检测方块与游戏区域边界、其他方块之间的碰撞,以及方块自身的碰撞。
7. 游戏规则:实现游戏的基本规则,如方块消除、得分、游戏结束等。
8. 用户界面:显示游戏界面,包括方块、游戏区域边界、得分等信息。
9. 延时与中断:通过延时函数和中断函数,实现游戏的实时性,如方块自动下落、响应用户输入等。
10. 代码优化:对代码进行优化,提高游戏运行效率和用户体验。
总之,基于51单片机的俄罗斯方块游戏代码实现涉及到数据结构、键盘扫描、方块生成与移动、碰撞检测、游戏规则、用户界面、延时与中断等多个方面。
在2KB内存的单片机上实现的的俄罗斯方块一. 综述相对于五子棋,俄罗斯方块算法更是满天飞。
我的代码还是相对好移植的,看起来也更清晰,方便学弟学妹们做编程小学期时移植。
不过要做就要做的有特色:它运行在软硬件由我们独立开发的平台上。
以下是截图:有如下特点:∙跑在独立开发的平台上,平台为MSP430F149,内存2KB,频率8MHz∙支持体感:可以通过左右倾斜来左右移动方块,还可以上下抖动改变方块形状∙代码精简,方便移植∙内存占用率极低∙支持横屏和竖屏操作∙支持等级:用户在达到一定分数后,等级会上升,从而方块下落速度变得更快二. 系统设计我们将问题细化为以下几个方面:1. 方块的形状如何存储俄罗斯方块总共有19种形状,每种形状都由四个小方块组成。
如何高效存储这些方块的形状是个值得思考的问题。
上图介绍了存储方法:我们用以下数组保存形状:const unsigned char BoxShape[19][9]={{ 1,0,0,1,1,1,2,1,1 },{ 1,0,1,1,2,1,1,2,2 },{ 0,0,1,0,2,0,1,1,3 },{ 1,0,0,1,1,1,1,2,0 },{ 1,0,2,0,1,1,1,2,5 },{ 0,0,1,0,2,0,2,1,6 },{ 2,0,2,1,2,2,1,2,7 },{ 0,0,0,1,1,1,2,1,4 },{ 1,0,2,0,2,1,2,2,9 },{ 2,0,0,1,1,1,2,1,10 },{ 1,0,1,1,1,2,2,2,11 },{ 0,0,1,0,2,0,0,1,8 },{ 0,0,0,1,1,1,1,2,13 },{ 1,0,2,0,0,1,1,1,12 },{ 2,0,1,1,2,1,1,2,15 },{ 0,0,1,0,1,1,2,1,14 },{ 1,0,1,1,1,2,1,3,17 },{ 0,1,1,1,2,1,3,1,16 },{ 1,0,2,0,1,1,2,1,18 }};2. 如何解决各个方块的互相转换的顺序:以上的数组已经解决了这一问题,多维数组的最后一位即该形状发生改变后的下一个形状。
基于51单片机俄罗斯方块游戏设计作者:左厚臣前言闲得无事,想用单片机和LCD12864写一个俄罗斯方块游戏,培养培养兴趣,丰富一下业余生活,同时也熟练熟练单片机应用。
然后整理一下过程,本文没有什么专业的流程图,系统框图,随手画的。
希望各位大神勿喷,本菜鸟就献丑了。
关键字:51单片机LCD12864 俄罗斯方块游戏设计一、实物写真1、先展示一下实物效果呗,看能不能吸引到各位大神的眼球!!!!2、单片机选型IO口占用:7个程序存储器占用:6459Byte内部RAM:117.0Byte内部扩展RAM:1016ByteFosc = 24Mhz(也可选择12Mhz)中断使用状况:16位定时器溢出中断1个手头有一块STC12C5A60S2 51系列单片机,本实验也采用的此款单片机,或许有大神能用很节省资源的方法写出这款游戏,本菜鸟甘拜下风。
二、游戏算法整个游戏的算法也就是这样子的吧!下面就对每个步骤进说明吧!三、算法说明算法就捡重点的说吧,省得各位大神都闲啰嗦。
1、当前随机方块获取和下一回合游戏方块生成并显示此步骤拆解成如下流程图所示:(1)随机数生成51单片机需要调用库函数来产生随机数,如下:#include <stdlib.h>//调用库函数的头文件函数rand ()会生成一个int型的随机数,int型变量范围为-32768~32767占用2 字节。
我们使用时其实是可以把它当做一个unsigned int型变量的,取值范围0-65535 这个应该是很好理解的。
但是如果我们需要一个0-7的随机数怎么处理呢,没关系有办法,程序如下:u8 Random(u8 max){u16 temp;u8 a;max = max +1;temp=rand();//获取随机种子a = temp%max;return a;}其实也就是把得到随机数与想要得到数范围的最大数求余运算就可以了,即:a = temp%max;我们的游戏方块可以描述成2个要素:A、形状比如说形状有:■■■■■■■■■等,可用0-n来表示B、姿态比如说形状■■■姿态有4种如下:■■■■■■■■■■■■它们从左往右看可以看出规律分别旋转了0°,90°,180°,270°,也分别相对旋转了90°,可以用0-3来表示。