打地鼠游戏设计毕业论文(设计)

发布时间:2017-06-16

打地鼠游戏机
公布论文和全部源码,仅供学习
摘要:本作品采用STC12C5A60S22单片机作为主控芯片,选取1602液晶作为显示屏,通过红外接收器用遥控控制游戏机的开机和关机。游戏程序应用C语言编译,主要使用函数为随机函数和键盘扫描函数。通过随机函数产生一个随机数,该随机数使显示屏对应位置出现O同时对应的LED被点亮以代表地鼠的随机出现。通过键盘扫描函数,使每个按键各对应一个LED灯,通过按下该键使相应LED灯熄灭。本系统配有开场音乐和游戏音效。
关键词:单片机、随机函数、键盘扫描函数、音乐 Abstract: this work using STC12C5A60S2 microcontroller as the main control chip select LCD as a display,1602, through the infrared receiver remote control game startup and shutdown. This game program using C language editing, the main function used are the random function and keyboard scan function. Use random functions to generate a random number, at the same time the random number to display the corresponding position"0" and the corresponding LED is illuminated to represent the random hamster. Through the keyboard scan function, make each key corresponds to a LED lamp, by pressing this key to the corresponding LED lights.
The whole process has background music and game sound. Key words: SCM, random function, keyboard scan function, music
游戏说明:
本游戏由8LED灯分别代表8只地鼠,当地鼠跳出来时显示屏对应位置出现“O,同时该地鼠对应的LED灯被点亮,在限定时间内按下相应按键后,对应LED灯熄灭,同时“O”闪烁一下,表示打中该地鼠。游戏规则为,打中18号地鼠,每只得一分,在每局限定的时间30秒内得满当前关所需分即可进入一下关。游戏分四关:第一关,地鼠跳出时间长,得10分后,游戏进入第二关;第二关,地鼠跳出时间较短,得15分后,游戏进入第三关;第三关,地鼠跳出时间更快,得20分后,游戏进入第四关。第四关,得25分可过,但超越人类反应极限,不作阐述。
方案比较、设计:
方案一:STC89C52作主控芯片,灯光表示地鼠,用红外遥控系统,用两层板完成整个电路。
方案二:用STC12C5A60S2作主控芯片,用灯光和液晶“0表示地鼠,加入音乐,用红外遥控系统,用一层板完成整个电路。
显然,方案二更加适合,因为方案二中采用的主控芯片运算的速度要比方案一所用芯片快得多(达8倍)ram足够,而且
游戏系统使用了定时中断函数,用STC12C5A60S2芯片会得到更快的响应。而且方案二加入了液晶显示和音乐,使游戏不那么单调,使玩家更好体现游戏的过程。最后,用一层板可以减少很多飞线,而且布局美观。 电路原理:
本系统包含六个子电路模块,分别为单片机系统电路、流水灯电路、蜂鸣器电路、2*4矩阵键盘、遥控红外接收电路、1602LCD显示屏模块。

单片机系统电路



流水灯电路

蜂鸣器电路



2*4矩阵键盘


遥控红外接收电路



1602液晶显示模块电路


各模块整合并接上电源后,通过遥控打开游戏系统。随后,单片机系统驱动游戏系统进入初始化模式,同时蜂鸣器系统被驱动开始播放背景音乐。游戏开始后,背景音乐停止,单片机系统开始随机驱动8LED灯点亮,同时液晶上对应位置出现O蜂鸣器系统同时被驱动,发出“嘀”一声。此过程中,系统不断计时,不断刷新分数。 游戏实现代码: //begin_display// #ifndef BeginDisplay_H #define BeginDisplay_H
//#include
#include
#define uchar unsigned char #define uint unsigned int
sbit lcden=P3^4; sbit lcdrs=P3^5; sbit dula=P2^6; sbit wela=P2^7; //sbit bemp=P2^3;
int runlight[9]={0xff,0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f} ;
uchar run_light_num,kkk; //流水灯亮到哪一盏,kkk定时0计数

uchar begin_flag,time_counter,mouse_hit;

void delay(uint z //延时1ms {
uint x,y; for(x=z;x>0;x-- for(y=110;y>0;y--; }
void delayus(unsigned char x //最新12c5a延时1us { while(x--
{ _nop_(; _nop_(; _nop_(; } }
void delayms(unsigned char x //最新12c5a延时1
{ unsigned char i,j,k;
for(k = x; k > 0; k-- for(i = 22; i > 0; i--
for(j = 250; j > 0; j--;
}

void write_com(uchar com { lcdrs=0; P0=com; delay(5; lcden=1; delay(5; lcden=0; }
void write_data(uchar date { lcdrs=1; P0=date; delay(5; lcden=1; delay(5; lcden=0; }
void init( { dula=0; wela=0;
lcden=0; write_com(0x38; //显示模式设置 write_com(0x0f; //开显示、光标、闪烁
write_com(0x06; //读写一个后地址加一,不移屏 write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80+0x01; //起始指针位置
} void begin_display( {
int i; uchar code table[]="##Whack a Mole##"; uchar code table1[]=" By CoolCat ";
init(;
write_com(0x80+0x10 ; for(i=0;i<16;i++ //写入第一行字
{ write_data(table[i] ;
delayms(5;

} write_com(0x80+0x50 ; //坐标变至下一行 for(i=0;i<16;i++
{ write_data(table1[i] ; delayms(5;
} for(i=0;i<16;i++
{ write_com(0x18; //整屏左移一位 delayms(100;
} for(i=0;i<5;i++ //整屏闪烁
{ write_com(0x08; delayms(50; write_com(0x0f; delayms(50;
} while(begin_flag;


}
/*void light_run( { int i;
TH0=(65536-5000/256; TL0=(65536-5000%256;
EA=1;//开中断
ET0=1; TR0=1; //开定时0
for(j=0;j<4;j++ for(i=1;i<9;i++
{ P0=runlight[i]; if(i==8 i==0; } */

void ready_go(
{
int i; //bemp=1; //初始化不响 uchar code table3[]="Ready "; uchar code table4[]="Go" ;
uchar code table5[]="5 4 3 2 1"; write_com(0x01; //清屏,显示清0,数据指针清0
write_com(0x80+0x01 ; for(i=0;i<9;i++ //写入第一行字
{ write_data(table5[i] ; bemp=~bemp; delayms(500; }
bemp=1; write_com(0x80+0x40 ; //坐标变至下一行

for(i=0;i<6;i++ //display "ready "再停顿一下
{ write_data(table3[i]
;
delayms(50;
} delayms(500;
for(i=0;i<2;i++
{ write_data(table4[i] ; delayms(50;
} write_data(0x7e ;
delayms(50; write_data(0x7e ; //向右方向头 delayms(50;

/*for(i=0;i<16;i++
{ write_com(0x18; //整屏左移一位 delay(300; }
*/ for(i=0;i<2;i++ //整屏闪烁
{
write_com(0x08; delayms(50; write_com(0x0f; delayms(50; } }
/*void Timer00( interrupt 1 //该中断为 流水灯转
{ TH0=(65536-5000/256; TL0=(65536-5000%256;
run_light_num++; P0=runlight[run_light_num] ; //流水灯亮 if (run_light_num==8 run_light_num=1;
} */ #endif
//GamingDisplay_h// #ifndef GamingDisplay_h #define GamingDisplay_h //有静止的time_score( , 动态
score_display( , //定时器2
uchar iii; //定时器2i uchar numm_temp=0x82;
uchar hole[]={ 0x80,0x82,0x83,0x84,
0x85,0x86,0x87, 0x88,0x8b } ; //8b王牌鼠

void first_line_mouse1602( {
int i; uchar code table8[]=" #_______#^_^# " ; //8个地鼠 8是王牌地鼠 打中加2 write_com(0x80; for(i=0;i<16;i++
{ write_data(table8[i] ; delay(1; }


}

void time_score( //显示时间和分数的单词 静态 加上显示地鼠
{ //尼码 还是得按5才有显示
int i; //不要全部用i uchar code table6[]="Time "; uchar code table7[]="Score ";

//dula=0; //wela=0;
//lcden=0; //write_com(0x38; //显示模式设置 write_com(0x0c; //不要光标,闪烁
//write_com(0x06; //读写一个后地址加一,不移屏 write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80+0x01; //起始指针位置 //write_com(0x0c; delay(5;

first_line_mouse1602(;
delayms(5;

write_com(0x80+0x40 ; for(i=0;i<5;i++ //第二行写时间 这个不用动
{ write_data(table6[i] ; delayms(5; }
write_com(0x80+0x48 ; //第二行后 分数 for(i=0;i<6;i++
{ write_data(table7[i] ; delayms(5; } }
void level_1_display( { uchar code table8[]="####Level 1#### ";
int i;
write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80; //起始指针位置 for(i=0;i<16;i++
{ write_data(table8[i]; delayms(50; } delayms(500; } void level_2_display( { uchar code table8[]="####Level 2#### ";
int i; write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80; //起始指针位置 for(i=0;i<16;i++
{ write_data(table8[i]; delayms(50; } delayms(500; }
void level_3_display( { uchar code table8[]="####Level 3#### ";
int i; write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80; //起始指针位置 for(i=0;i<16;i++
{ write_data(table8[i]; delayms(50; } delayms(500; } void level_4_display( {

uchar code table8[]="##BT##Level 4## "; int i; write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80; //起始指针位置 for(i=0;i<16;i++ {
write_data(table8[i];

} delayms(50;
}
delayms(500; void congratulation( //过关后的庆贺 {
int i; uchar code table9[]="congratulation!!";
uchar code table10[]="Your score" ; write_com(0x01; //清屏,显示清0,数据指针清0 write_com(0x80; //起始指针位置 for(i=0;i<16;i++
{ write_data(table9[i]; delayms(50;
} write_com(0x80+0x41; for(i=0;i<10;i++
{ write_data(table10[i]; delayms(50;
}
write_com(0x80+0x4c
; write_data(mouse_hit/10+0x30 ; //显示分数十位
//delay(5; write_data(mouse_hit%10+0x30 ; //显示分数个位 write_com(0x50; }
void game_over( // 失败 {
int i; uchar code table9[]=" Gmae Over
uchar code table10[]="Your score" ; write_com(0x01; //清屏,显示清0,数据指针清 write_com(0x80; //起始指针位置 for(i=0;i<16;i++
{ write_data(table9[i]; delayms(50;
} write_com(0x80+0x41;
for(i=0;i<10;i++ "; 0

{ write_data(table10[i]; delayms(50;
} write_com(0x80+0x4c
; write_data(mouse_hit/10+0x30 ; //显示分数十位
//delay(5; write_data(mouse_hit%10+0x30 ; //显示分数个位 write_com(0x50; }
void mouse_1602display(uchar numm { //first_line_mouse1602(;
write_com(hole[numm_temp] ; write_data(0x5f ; //0x5f="_"

write_com(hole[numm] ; write_data(0x4f ; // 0x4f=O

numm_temp=numm;
write_com(0x50; }

void init_timer2( { RCAP2H=(65536-50000/256; //重装载计数器赋初值
RCAP2L=(65536-50000%256; ET2=1; //开定时器2中断 EA=1; //开总中断 }
void gaming_display( {
init_timer2(; TR2=1; //开启定时器,并设置为 自动重装载模式 }


/*void timer2( interrupt 5 //调用定时器2,自动重装载模式
{ TF2=0; //定时器2的中断标志要软件清0 iii++; //计数标志自加1 if(iii==8
{ iii=0; //将静态变量清0 score_display(;
} } */ #endif

//mouse_level// #ifndef MouseLevel_H #define MouseLevel_H //time_counter, mouse_hit ,random , key_scan , // mouse_out , 两个定时中断01

#define level_1 50
#define level_2 70 #define level_3 80 //不同等级对应不同的地鼠数 #define level_4 100
uchar seed,keyscan_num, temp_num,random_num; //声明时间种子,键盘数,临时数,计时数
//击中地鼠数 int iiii;

int deng[9]={0xff,0xfe,0xfd,0xfb,0xf7, 0x7f,0xbf,0xdf,0xef} ;

int random( { uchar j,k; srand(seed; k=(rand(%8+1; j=1+(int(16.0*rand(/65535; //jk是两种实现随机机算法,j算法优 return(k
;
}
uchar keyscan(;
void mouse_out(uchar mouse_num,uchar speed //第一个变量是老鼠数,第二个是速度
{ uchar i,kk, random_temp ,keyscan_temp; keyscan_num=0; random_num=1;

mouse_hit=0; time_counter=30; //初始化时间和分数


TMOD=0X11; TH0=(65536-61440/256; //定时中断初始化 开了2个中断 TL0=(65536-61440%256; //0是给随机函数用的,1是进行定时扫描键盘的
TH1=(65536-10000/256;
TL1=(65536-10000%256;
EA=1;//开中断
ET0=1; TR0=1; //开定时0 ET1=1; TR1=1;

for(kk=0;kk
{ random_temp=random(; //使random(变化
if(random_num!=random_temp //random_num不变 keyscan num 保持一段时间
//产生不重合的随机数 random_num=random_temp; else if (random_temp>=7 random_num=random_temp-1; else random_num=random_temp+1;

P1=deng[random_num]; bemp=0; delayms(50;
bemp=1;
//for(i=0;i<100;i++ delay(99;
for(i=0;i //此处的i用于调节速度
{ if(random_num==keyscan_num
{
P1=0xff ; //i++; //此处的加是击中后出鼠速度会加快
if(keyscan_num!=keyscan_temp ////要解决不断刷分的问题
{
mouse_hit++; if(random_num==8 mouse_hit++; //神鼠加2
first_line_mouse1602(;
}
//keyscan_num=9; keyscan_temp=keyscan_num;
} delayms(1000;



} if(time_counter==0 break;

//delay(2000; }
} /********************************************************* **************************************************** *********************************************************/ void game_start( {
int i; level_1_display(; //第一关 10分过关
time_score(; mouse_out(level_1,4; if(mouse_hit>=10
{
congratulation(;

for(i=0;i<3;i++ delayms(500; mouse_hit=0; } else
{ game_over(; while(1; }

level_2_display(;
time_score(; mouse_out(level_2,3; 时间
if(mouse_hit>=15
{ congratulation(; for(i=0;i<3;i++ delayms(500;
mouse_hit=0; //第二关 15分过关 //这个函数里面有开定时 设置
} else
{ game_over(; while(1; }

level_3_display(;
time_score(; mouse_out(level_3,2; 时间
if(mouse_hit>=20
{ congratulation(; for(i=0;i<3;i++ delayms(500; mouse_hit=0; } else
{ //第三关 20分过关 //这个函数里面有开定时 设置
game_over(; while(1; }
while(1; //gaming_display(; }
/********************************************************* ********************************************************** *********************************************************/

void Timer0( interrupt 1//该中断是为random(提供时间种子服务,并计时 {
if(music_flag==1
{

bemp = !bemp; TH0 = Sound_Temp_TH0; TL0 = Sound_Temp_TL0; kkk++; if(kkk==100
{
run_light_num++; P1=runlight[run_light_num] ; //流水灯亮 if (run_light_num==8 run_light_num=0; kkk=1; } }
else {TH0=(65536-61440/256; TL0=(65536-61440%256;
seed=seed+iiii; //产生更混乱的时间种子,去重复的bug if(seed>100 seed=0; //时间种子服务 iiii++;


if(iiii%3==1

{ mouse_1602display(random_num; //1602液晶显示地鼠 write_com(0x80+0x4e
; write_data(mouse_hit/10+0x30 ; //显示分数十位
//delay(5; write_data(mouse_hit%10+0x30 ; //显示分数个位 write_com(0x50; }
if(iiii==1 //经过计算15次恰为1 time_counter用以显示剩余时间
{ time_counter-- ;
if(time_counter==0
{ TR0=0; //关中断
TR1=0; P1=deng[0]; //灯全灭 first_line_mouse1602(;
}


write_com(0x80+0x45 ; write_data(time_counter/10+0x30 ; //显示时间十位
//delay(5; write_data(time_counter%10+0x30 ; //显示时间个位 //delay(5; write_com(0x50;
} if(iiii==19 iiii=0; } }

void Timer1( interrupt 3//该中断时定时进行键盘扫描服务 {

TH1=(65536-5000/256;
TL1=(65536-5000%256; temp_num=keyscan(; //这个判断语句防止不断收到0 if(temp_num keyscan_num=temp_num;


}

uchar keyscan( { uchar num,temp; P3=0xfe; temp=P3; temp=temp&0xf0; num=0;
if(temp!=0xf0
{ delay(5; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ temp=P3; switch(temp
{ //按下去
case 0xee:num=1; break; case 0xde:num=5; break; /* case 0xbe:num=4; break; case 0x7e:num=8; break;
} /* while(temp!=0xf0
{ temp=P3; temp=temp&0xf0; } */ } } P3=0xfd; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ */ //松手才有效


delay(5; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ temp=P3; switch(temp
{ case 0xed:num=2; break; case 0xdd:num=6; break; /* case 0xbd:num=3;
break; case 0x7d:num=7; break;
} /* while(temp!=0xf0
{ temp=P3; temp=temp&0xf0; } */ */
} }

P3=0xfb; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ delay(5; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ temp=P3; switch(temp
{ case 0xeb:num=3; break; case 0xdb:num=7; break; /*
case 0xbb:num=2;
break; case 0x7b:num=6; break; */
} /* while(temp!=0xf0
{ temp=P3; temp=temp&0xf0; } } } P3=0xf7; temp=P3; temp=temp&0xf0; if(temp!=0xf0
{ delay(5; temp=P3; temp=temp&0xf0;
if(temp!=0xf0 */



{ temp=P3; switch(temp
{ case 0xe7:num=4; /* return num;
break; case 0xd7:num=8; break; /* case 0xb7:num=1; break; case 0x77:num=5; break;
} while(temp!=0xf0
{ temp=P3;
temp=temp&0xf0; } } } */ */
} #endif
//music// #ifndef __SOUNDPLAY_H_REVISION_FIRST__ #define __SOUNDPLAY_H_REVISION_FIRST__
#include
//**************************************************************************
#define SYSTEM_OSC 11059200//12000000 //定义晶振频率12000000HZ #define SOUND_SPACE 4/5 //定义普通音符演奏的长度分率,//4分音符间隔
sbit bemp = P2^3; //定义输出管脚

int music_flag;

idata
unsigned
int


FreTab[12]

= { 262,277,294,311,330,349,369,392,415,440,466,494 }; //原始频率
idata unsigned char SignTab[7] = { 0,2,4,5,7,9,11 }; //1~7在频率表中的位置
idata unsigned char
LengthTab[7]= { 1,2,4,8,16,32,64 }; idata unsigned char Sound_Temp_TH0,Sound_Temp_TL0; //音符定时器初值暂存
idata unsigned char Sound_Temp_TH1,Sound_Temp_TL1; //音长定时器初值暂存
//************************************************************************** void InitialSound(void {
bemp = 1; Sound_Temp_TH1 = (65535-(1/1200*SYSTEM_OSC/256; // 计算TL1应装入的初值 (10ms的初装值
Sound_Temp_TL1 = (65535-(1/1200*SYSTEM_OSC%256; // 计算TH1应装入的初值 TH1 = Sound_Temp_TH1;
TL1 = Sound_Temp_TL1;
TMOD |= 0x11; ET0 = 1; ET1 = 0; TR0 = 0; TR1 = 0; EA = 1; }
/*void BeepTimer0(void interrupt 1 //音符发生中断
{ if(music_flag==1
{
bemp = !bemp; TH0 = Sound_Temp_TH0; TL0 = Sound_Temp_TL0; } /*
else {TH0=(65536-61440/256; TL0=(65536-61440%256;
seed=seed+iiii; //产生更混乱的时间种子,去重复的bug if(seed>100 seed=0; //时间种子服务

iiii++;
if(iiii%3==1
{ mouse_1602display(random_num; //1602液晶显示地鼠 write_com(0x80+0x4e
; write_data(mouse_hit/10+0x30 ; //显示分数十位
//delay(5; write_data(mouse_hit%10+0x30 ; //显示分数个位 write_com(0x50; }
if(iiii==1 //经过计算15次恰为1 time_counter用以显示剩余时间
{ time_counter-- ;
if(time_counter==0
{ TR0=0; //关中断
TR1=0;
P1=deng[0]; //灯全灭 first_line_mouse1602(; }

write_com(0x80+0x45 ; write_data(time_counter/10+0x30 ; //显示时间十位
//delay(5; write_data(time_counter%10+0x30 ; //显示时间个位 //delay(5; write_com(0x50;
} if(iiii==19 iiii=0; } */ /*
bemp = !bemp; TH0 = Sound_Temp_TH0; TL0 = Sound_Temp_TL0; */ //} //************************************************************************** void Play(unsigned char *Sound,unsigned char Signature,unsigned Octachord,unsigned int Speed {
idata unsigned int NewFreTab[12]; //新的频率表 idata unsigned char i,j;
idata
unsigned int
Point,LDiv,LDiv0,LDiv1,LDiv2,LDiv4,CurrentFre,Temp_T,SoundLength; idata unsigned char Tone,Length,SL,SH,SM,SLen,XG,FD; for(i=0;i<12;i++ // 根据调号及升降八度来生成新的频率表
{ j = i + Signature; if(j > 11
{
j = j-12; NewFreTab[i] = FreTab[j]*2; }
else NewFreTab[i] = FreTab[j];
if(Octachord == 1 NewFreTab[i]>>=2; else if(Octachord == 3
NewFreTab[i]<<=2;
}


SoundLength = 0; while(Sound[SoundLength] != 0x00 //计算歌曲长度
{ SoundLength+=2; }

Point = 0; Tone = Sound[Point];

Length = Sound[Point+1]; // 读出第一个音符和它时时值

LDiv0 = 12000/Speed; // 算出1分音符的长度(10ms LDiv4 = LDiv0/4; // 算出4分音符的长度 LDiv4 = LDiv4-LDiv4*SOUND_SPACE; // 普通音最长间隔标准 TR0 = 0; TR1
= 1; while(Point < SoundLength
{
SL=Tone%10; //计算出音符 SM=Tone/10%10; //计算出高低音

SH=Tone/100; //计算出是否升半

CurrentFre = NewFreTab[SignTab[SL-1]+SH]; //查出对应音符的频率 if(SL!=0
{ if (SM==1 CurrentFre >>= 2; //低音 if (SM==3 CurrentFre <<= 2; //高音
Temp_T
= 65536-(50000/CurrentFre*10/(12000000/SYSTEM_OSC;//计算计数器初值
Sound_Temp_TH0 = Temp_T/256; Sound_Temp_TL0 = Temp_T%256; TH0 = Sound_Temp_TH0;

TL0 = Sound_Temp_TL0 + 12; //12是对中断延时的补偿
} SLen=LengthTab[Length%10]; //算出是几分音符 XG=Length/10%10; //算出音符类型(0普通1

打地鼠游戏设计毕业论文(设计)

相关推荐