使用Proteus 8仿真打地鼠,灵敏测试,51单片机做主控(附源代码和仿真图供下载使用)原创不易,望点赞。

效果图

//功能:在限定时间内(20秒),每间隔1秒随机点亮D1-D8,要求在间隔时间1秒内迅速点击对应的按键,
//1秒时间到,则进入下一轮;当20秒时间到时,统计击中的胜率,并给出评价:
//好:胜率>=80%;    中:50%<=胜率<80%;    差:胜率<50%;
#include <reg52.h>
#include<stdlib.h>//随机函数在里面 
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

volatile uchar state=0;//全局状态标识变量
volatile uchar test_state=0;//测试状态标识变量
volatile uint flag=0;
volatile uint interval_time_length=0;


uint time_counter_interval;//2ms定时情况下,0.5秒时间到的判读计数器
uint time_counter_overall; //2ms定时情况下,10秒时间到的判读计数器

sbit led_good=P3^2;  //好评灯控制端口
sbit led_normal=P3^3;//中评灯控制端口
sbit led_bad=P3^4;   //差评灯控制端口

sbit beginning=P0^7; //从开
sbit key_easy=P3^7; //“简单”按键输入端口
sbit key_normol=P3^6; //“一般”按键输入端口
sbit key_difficult=P3^5; //“困难”按键输入端口

uchar grade[3];//成绩
code uint zk[11]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff};
code uchar sm[7]={0xee,0xed,0xf6,0xf5,0xfa,0xf9,0xff};//动态扫描2个灯-差 一般 好
//#define interval_time_length 500 //定义反应间隔时间长度是0.5秒,可改变数值控制测试难度

#define sm_data    P0    //P0定义为“打地鼠”评分显示
#define led_mouse  P1    //P1定义为“地鼠”灯
#define key_mouse  P2    //P2定义为“打地鼠”按键
#define key_LED  P3      //P3定义为LED动态显示

volatile uchar cache_key_mouse;//“打地鼠”按键的缓存数值

volatile uchar random_number;//随机数

volatile uint winning;//胜率

volatile uint k;//记次

void delay(uint n);

uchar i,j,sum;

// 12MHZ Timer 0 方式1  定时中断服务,2ms定时
void time0( ) interrupt 1
{
    TH0=0xf8;//重置TH0和TL0
    TL0=0x30;
	
	 if (++time_counter_interval>=interval_time_length) //0.5秒间隔时间到
	   {						
		 time_counter_interval=0;
		 test_state++;//测试次数加1
		 flag=0;
	   }					
}

void initialization() // 初始化
{ 
    TR0=0;//定时关闭	
    TH0=0xf8; //初始化TH0、TH1,12MHZ下 定时为2ms
    TL0=0x30;	 
	test_state=0;//准备再次进行第一次测试  
	winning=0;//对胜率清零
	sum=0;	 //对总分清零
	sm_data=zk[10];//数码管关闭
	led_mouse=0xff;//“地鼠”没有出现
	key_LED=0xff;//20次时间到
	TR0=1;//定时开始	 
}

void random() // 随机取数
{
     if(flag==0&&k==0)
	 {
		rand();//空取一次随机数函数,使得随机性更强。
		random_number=(((uint)rand())%10);//随机数取个位保存
		if(random_number>7)//将随机数控制在0-7范围,超出7,则强制为7
		 {
		      random_number=7;
		 }

            led_mouse=(~(0x01<<random_number));//地鼠出现
		}
	 if(k==1)led_mouse=0xff;					
}

void Flog() // 保持取一个的数
{ 
	if((++flag)==65535)//保证flag只有一次为1的机会
		{
		flag=0;
		}
}

void evaluate() //评价
{ 
    if(test_state<20)//20次时间到
	{
					 /*******************分值评价********************/
		 sum=winning*5;grade[0]=sum%10;grade[1]=sum/=10;
		//if(test_state==19){sum=99;grade[0]=sum%10;grade[1]=sum/=10;}//避免超过两位数码管的读取范围

		if((((winning*100)/20)>80)||(((winning*100)/20)==80))//好:胜率>=80%
				     {if(sum<100){				  
				         for(i=0;i<2;i++)
				           {
				              key_LED=sm[i+4];
					          sm_data=zk[grade[i]];//显示数据
					         delay(10);  	  
				           }}
	
	                   if(sum==100){sum=99;grade[0]=sum%10;grade[1]=sum/=10;}//避免超过两位数码管的读取范围
				     {					  
				         for(i=0;i<2;i++)
				           {
				              key_LED=sm[i+4];
					          sm_data=zk[grade[i]];//显示数据
					         delay(10);  	  
				           }
					 }
					 }
					   	 
		else if(((((winning*100)/20)>50)||(((winning*100)/20)==50))&&(((winning*100)/20)<80))// 中:50%<=胜率<80%
				     {					  
				         for(i=0;i<2;i++)
				           {
				              key_LED=sm[i+2];
					          sm_data=zk[grade[i]];//显示数据
					         delay(10);  	  
				           }
					 }					 					 

		else if(((winning*100)/20)<50)//  差:胜率<50%
				     {					  
				        
				         for(i=0;i<2;i++)
				           {
				              key_LED=sm[i];
					          sm_data=zk[grade[i]];//显示数据
					         delay(10);  	  
				           }
					 }
	 }
	if(test_state==20)//20次时间到
	{ 
	TR0=0;//定时关闭	
    TH0=0xf8; //初始化TH0、TH1,12MHZ下 定时为2ms
    TL0=0x30;
	k=1;//已达到20次,“地鼠”不能出现
	test_state=0;
	}
}

void judgment() // 判定是否击中目标
{ 
if(key_mouse!=0xff)
{
delay(20);
if(key_mouse!=0xff)
{
cache_key_mouse=key_mouse;
	switch(cache_key_mouse) 
		{ 
		case 0xfe:		  
		if(random_number==0)//击中0号地鼠
		winning++;//胜率加1
		random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
        case 0xfd:		  
		if(random_number==1) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0xfb:		  
		if(random_number==2) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0xf7:		  
		if(random_number==3) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0xef:		  
		if(random_number==4) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0xdf:		  
		if(random_number==5) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0xbf:		  
		if(random_number==6) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		case 0x7f:		  
		if(random_number==7) winning++;random_number=8;//避免在间隔时间内,多次击中,使胜率多次加1
		break;
		}
		}
		}	
}


/********************************************************************/
/******************************主函数********************************/
/********************************************************************/
void main(void)
{
	//中断初始化
    TMOD=0x01;//选定T0作为定时器,工作方式1(2的16次方)
    TH0=0xf8; //初始化TH0、TH1,12MHZ下 定时为2ms
    TL0=0x30;
    ET0=1;
	EA=1;			// 开放全局中断

    led_mouse=0xff;//“地鼠”没有出现
    led_good=1;  //好评灯灭
    led_normal=1;//中评灯灭
    led_bad=1;   //差评灯灭
	initialization();//初始化
	while(1)
	{
	  switch(state)
	   		{
	          case 0://初始状态,等待按下“开始”建,触发进入测试状态
				  initialization();//初始化	
				  if(!key_easy||!key_normol||!key_difficult)
	          	    {
				      delay(100);
				      if(!key_easy)	 //简单
					  {  
					      initialization();//初始化
						  k=0;  //“地鼠”出现
					      state=1;//触发进入简单状态 
						}
					   if(!key_normol) //一般
					    {
						  k=0;
						  initialization();//初始化
						  state=2;//触发一般状态
						}

						if(!key_difficult) //困难
					    {
						  initialization();//初始化
						  k=0;
						  state=3;//触发困难状态
						}
			  	    } 
			  break;
			 
			  case 1://简单测试状态
			     interval_time_length=500; //定义反应间隔时间长度是0.5秒,可改变数值控制测试难度
				 random();	//随机取数
			 	 Flog();	//保持数值
				 judgment();//判断是否击中“地鼠”
				 evaluate();//显示分值并评价
				 if(!key_easy||!key_normol||!key_difficult)
	          	    { delay(100);
				     if(!key_easy||!key_normol||!key_difficult)
					 state=0;}	   
			  break; 

			  case 2://一般测试状态
			     interval_time_length=350; //定义反应间隔时间长度是0.75秒
				 random();	
			 	 Flog();
				 judgment();
				 evaluate();
				 if(!key_easy||!key_normol||!key_difficult)
	          	    { delay(100);
				     if(!key_easy||!key_normol||!key_difficult)
					 state=0;}	   
			  break;

			  case 3://困难测试状态
			     interval_time_length=250; //定义反应间隔时间长度是0.5秒
				 random();	
			 	 Flog();
				 judgment();
				 evaluate();
				 if(!key_easy||!key_normol||!key_difficult)
	          	    { delay(100);
				     if(!key_easy||!key_normol||!key_difficult)
					 state=0;}	   
			  break;
			}  
	}
}

void delay(uint n)
{
   uchar i;
   while(n--)
      for(i=0;i<125;i++);
}

  • 12
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liang_Xia_Strive

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值