51单片机系列(三)51 单片机游戏设计 —— 双人对战小游戏(石头剪刀布)

本博客51单片机实训系列,旨在记录本人在大学上单片机技术这门课时所做的课程实训内容,并与大家分享基于51单片的课程作业,如果作业中的某些细节和代码能给大家一点启发那就更好了,希望大家能用51单片机做出多姿多彩的东西。最后不要忘记,我们的目标是星辰大海!

51单片机系列(三)51 单片机游戏设计 —— 双人对战小游戏(石头剪刀布)

    • 实验游戏规则介绍
    • 实验游戏详细介绍
    • 实验游戏计算推导过程
    • 实验项目所用到的模块
    • 表格展示
    • 算法流程图
    • 程序清单

51单片机系列(三)51 单片机游戏设计 —— 双人对战小游戏(石头剪刀布)_第1张图片

实验游戏规则介绍

本游戏(石头剪刀布)玩法如下:
1、本游戏分为甲乙双方,采用 8*8 点整显示出拳结果
①(“石头”-用圆角矩形表示)
②(“剪刀”-用大写字母 X 表示)
③(“布” -用矩形表示)
④通过 Led1-4 显示甲方的积分,Led5-8 显示乙方的积分
2、本游戏采用 5 局 3 胜制。
①甲方通过控制独立按键的 key1(石头)、key3(剪刀)、key4(布)。
②乙方通过控制矩阵键盘 S1(石头)、S2(剪刀)、S3(布)。
③当甲方胜利,甲方积分加 1,甲方的 Led 灯区域点亮一盏灯(表示获得 1 积分),乙方同理。
④当其中一方率先到达 3 分时,这一方的四栈 led 全亮,蜂鸣器发出游戏结 束的声音(提示其中一方获胜)。
3、打开单片机电源,显示游戏未开始的界面。该界面由石头剪刀布以及一个向 右的箭头组成,玩家可以按下 S15 键开始游戏,然后游戏进入到等待输入界面。
4、当一局游戏结束时,玩家可以按下 S16 键来重置游戏(重新开一局)

实验游戏详细介绍

首先打开 51 板子电源后,我们能看到 88 点阵显示的游戏等待界面。界面 上有四个图形分别是:圆角矩形(代表石头)、大写字母 X(代表剪刀)、矩形 (代表布)、向右的箭头(意味着游戏马上开始)。当我们按下矩阵键盘区的 S15 时,游戏开始 88 点阵变黑等待玩家的输入。游戏的甲玩家操控独立按键区 的 Key1(代表石头)、Key3(代表剪刀)、Key4(代表布),乙玩家操控矩阵 按键区的 S1(代表石头)、S2(代表剪刀)、S3(代表布)。双方的出拳结果会显示 到 8*8 点阵,并且本游戏设计 Led1-4 显示玩家甲的积分,led5-8 显示玩家乙的 积分。当其中一方胜利一局时,对应的 led 区域点亮一盏灯。当其中一个玩家的 积分到达三分时,4 栈 led 灯全亮,蜂鸣器响起,代表玩家获胜。此时玩家可以 通过矩阵键盘的 S16 重新开始一局游戏。

实验游戏计算推导过程

实验项目所用到的模块

LED 模块,74HC138 译码器,8*8 点阵模块,独立按键模块,矩阵按键模块,蜂 鸣器模块。

表格展示

51单片机系列(三)51 单片机游戏设计 —— 双人对战小游戏(石头剪刀布)_第2张图片

算法流程图

51单片机系列(三)51 单片机游戏设计 —— 双人对战小游戏(石头剪刀布)_第3张图片

程序清单

//
// Created by BeLoved91 on 2020-12-14.
//
#include "reg51.h"
#include "intrins.h"

typedef	unsigned char u8;
typedef	unsigned int u16;

#define led P2	   //将P2口定义为led 后面就可以使用led代替P2口
#define GPIO_KEY P1		   //矩阵按键
u8 KeyValue;	//用来存放读取到的键值			  
//--定义使用的IO口--//
sbit SRCLK=P3^6;
sbit RCLK=P3^5;
sbit SER=P3^4;

sbit k1 = P3^1;
sbit k2 = P3^0;
sbit k3 = P3^2;
sbit k4 = P3^3;
//蜂鸣器
sbit beep =  P1^5; 
u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
u8 ledduan[10][8]=
{0x60,0x90,0x90,0x60,0x06,0x09,0x09,0x06, //石头-石头
 0x60,0x90,0x90,0x60,0x09,0x06,0x06,0x09, //石头-剪刀
 0x60,0x90,0x90,0x60,0x0f,0x09,0x09,0x0f, //石头-布
 0x90,0x60,0x60,0x90,0x06,0x09,0x09,0x06, //剪刀-石头
 0x90,0x60,0x60,0x90,0x09,0x06,0x06,0x09, //剪刀-剪刀
 0x90,0x60,0x60,0x90,0x0f,0x09,0x09,0x0f, //剪刀-布
 0xf0,0x90,0x90,0xf0,0x06,0x09,0x09,0x06, //布-石头
 0xf0,0x90,0x90,0xf0,0x09,0x06,0x06,0x09, //布-剪刀
 0xf0,0x90,0x90,0xf0,0x0f,0x09,0x09,0x0f, //布-布
 0x6f,0x99,0x99,0x6f,0x94,0x64,0x6e,0x94  //开局画面									
};

//甲的分数,乙的分数。
u8 jiaScore =0,yiScore=0;
//重置游戏标志位
u8 flag = 0;
//获胜者标识   0代表甲赢,1代表乙赢。
u8 vy = -1;

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
 
void delayfordig(u16 time){		//延时函数
 	
	u16 i,j;
	for(i=0;i<time;i++){
		 for(j=0;j<121;j++){
		 }
	}
	
}
void delay(u16 i){
 	while(i--);
}
void Hc595SendByte(u8 dat)	  //发送段选信号
{
	u8 a;
	SRCLK=0;
	RCLK=0;
	for(a=0;a<8;a++)
	{
		SER=dat>>7;
		dat<<=1;
		SRCLK=1;
		_nop_();
		_nop_();
		SRCLK=0;	
	}

	RCLK=1;
	_nop_();
	_nop_();
	RCLK=0;
}

void showresult(u8 j){
	u8 tab,count=16;
	u16 i;
	while(count--){
	for(i=0;i<6;i++)
	{
		for(tab=0;tab<8;tab++)
		{
			    Hc595SendByte(0x00); //消隐
			    P0=ledwei[tab];
				Hc595SendByte(ledduan[j][tab]);
				delayfordig(2);
		}
	}
   }
    Hc595SendByte(0x00); //消隐
}

//矩阵键盘
void KeyDown(void)
{
	char a=0;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f)//读取按键是否按下
	{
		delay(1000);//延时10ms进行消抖
		if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
		{	
			//测试列
			GPIO_KEY=0X0F;
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=1;break;
				case(0X0b):	KeyValue=2;break;
				case(0X0d): KeyValue=3;break;
				case(0X0e):	KeyValue=4;break;
			}
			//测试行
			GPIO_KEY=0XF0;
			switch(GPIO_KEY)
			{
				case(0X70):	KeyValue=KeyValue;break;
				case(0Xb0):	KeyValue=KeyValue+4;break;
				case(0Xd0): KeyValue=KeyValue+8;break;
				case(0Xe0):	KeyValue=KeyValue+12;break;
			}
			
		}
		}
	while((a<50)&&(GPIO_KEY!=0xf0))	 //检测按键松手检测
	{
		delay(100);
		a++;
	}
}
void bmp()    //游戏结束时,蜂鸣器发出声音函数
{
	u8 t=500;
	while(t--)
	{
		beep=~beep;
		delay(500);	
	}
}
//游戏逻辑处理
void handler();
//结果处理
void resultJudge(); 
void main()
{
u8 count = 20;
  //熄灭所有灯
  led=0xff;
  while(count--)
  {	
  		//熄灭所有灯
  		led=0xff;
  		//初始化得分
  		jiaScore =0,yiScore=0;
  		//开场画面
		showresult(9);
  		while(flag){
  		KeyValue=0;//复位
 		KeyDown();		   //按键判断函数
		handler();		   //游戏逻辑处理
		resultJudge();     //结果处理
		}
		if(vy == 0){
		  led = 0xf0;      //led0-led3,一直亮表示甲赢
		  bmp();		   //提示游戏结束
		    delay(5000);
		  delay(5000);
		  vy = -1;
		}
		if(vy == 1){
		  led = 0x0f;	   //led4-led7,一直亮表示乙赢
		  bmp();           //提示游戏结束
		  delay(5000);
		  delay(5000);
		  vy = -1;
		}
		KeyDown();		   //按键判断函数
		if(KeyValue == 15){//当按下s15时,开始游戏
		  flag = 1;
		  KeyValue = 0;
		}
		if(KeyValue == 16){//当按下s16时,重置比赛
		  flag = 1;
		  KeyValue = 0;
		  //熄灭所有灯
  	      led=0xff;
		}
  }
}
//结果处理
void resultJudge(){
	if(jiaScore == 0 && yiScore == 1){
		   led = 0xef;
		   delay(50000);
	}
	if(jiaScore == 0 && yiScore == 2){
		   led = 0xcf;
		   delay(50000);
	}
	if(jiaScore == 0 && yiScore == 3){	//0-3乙胜利
		   led = 0x8f;
		   delay(20000);  
		   flag = 0;
		   vy = 1;
		   return ;
	}


	if(jiaScore == 1 && yiScore == 0){
		   led = 0xfe;
		   delay(50000);
	}
	if(jiaScore == 1 && yiScore == 1){
		   led = 0xee;
		   delay(50000);
	}
	if(jiaScore == 1 && yiScore == 2){
		   led = 0xce;
		   delay(50000);
	}
	if(jiaScore == 1 && yiScore == 3){   //1-3乙胜利
	       led = 0x8e;
		   delay(20000);  
		   flag = 0;
		   vy = 1;
		   return ;
	}


	if(jiaScore == 2 && yiScore == 0){
		   led = 0xfc;
		   delay(50000);
	}
	if(jiaScore == 2 && yiScore == 1){
		   led = 0xec;
		   delay(50000);
	}
	if(jiaScore == 2 && yiScore == 2){
		   led = 0xcc;
		   delay(50000);
	}
	if(jiaScore == 2 && yiScore == 3){   //2-3乙胜利
	       led = 0x8c;
		   delay(20000);  
		   flag = 0;
		   vy = 1;
		   return ;
	}


	if(jiaScore == 3 && yiScore == 0){	 //3-0甲胜利
		   led = 0xf8;
	       delay(20000);
		   flag = 0;
		   vy = 0;
	}
	if(jiaScore == 3 && yiScore == 1){	 //3-1甲胜利
		   led = 0xe8;
	       delay(20000);
		   flag = 0;
		   vy = 0;
	}
	if(jiaScore == 3 && yiScore == 2){	 //3-2甲胜利
		   led = 0xd8;
		   delay(20000);  
		   flag = 0;
		   vy = 0;
		   return ;
	}
}
//游戏逻辑处理
void handler(){
		//情况二	 //石头-石头  //石头-剪刀   //石头-布
	 	if(k1 == 0 &&  KeyValue==1)
  		{
			delay(1000);
			if(k1 == 0){
			   showresult(0);   //石头-石头
			   KeyValue=0;//复位
			}
			while(!k1);
		}
		if(k1 == 0 &&  KeyValue==2)
  		{
			delay(1000);
			if(k1 == 0){
			   showresult(1);   //石头-剪刀
			   jiaScore++;		//甲赢了,加一分
			   KeyValue=0;//复位
			}
			while(!k1);
		}			
		if(k1 == 0 &&  KeyValue==3)
  		{
			delay(1000);
			if(k1 == 0){
			   showresult(2);   //石头-布
			   yiScore++;		//乙赢了,加一分
			   KeyValue=0;//复位
			}
			while(!k1);
		}


		//情况二	 //剪刀-石头  //剪刀-剪刀   //剪刀-布
		if(k3 == 0 &&  KeyValue==1)
  		{
			delay(1000);
			if(k3 == 0){
			   showresult(3);   //剪刀-石头
			   yiScore++;		//乙赢了,加一分
			   KeyValue=0;//复位
			}
			while(!k1);
		}
		if(k3 == 0 &&  KeyValue==2)
  		{
			delay(1000);
			if(k3 == 0){
			   showresult(4);    //剪刀-剪刀
			   KeyValue=0;//复位
			}
			while(!k1);
		}			
		if(k3 == 0 &&  KeyValue==3)
  		{
			delay(1000);
			if(k3 == 0){
			   showresult(5);    //剪刀-布	 
			   jiaScore++;       //甲赢了,加一分
			   KeyValue=0;//复位
			}
			while(!k1);
		}

			//情况三	 //布-石头  //布-剪刀   //布-布
		if(k4 == 0 &&  KeyValue==1)
  		{
			delay(1000);
			if(k4 == 0){
			   showresult(6);    //布-石头
			   jiaScore++;       //甲赢了,加一分 
			   KeyValue=0;//复位
			}
			while(!k1);
		}
		if(k4 == 0 &&  KeyValue==2)
  		{
			delay(1000);
			if(k4 == 0){
			   showresult(7);     //布-剪刀 
			   yiScore++;		  //乙赢了,加一分
			   KeyValue=0;//复位
			}
			while(!k1);
		}			
		if(k4 == 0 &&  KeyValue==3)
  		{
			delay(1000);
			if(k4 == 0){
			   showresult(8);     //布-布
			   KeyValue=0;//复位
			}
			while(!k1);
		}
}

代码有点长,这是一次课后作业,大概花了一个星期完成。

你可能感兴趣的:(51单片机系列,单片机)