本博客51单片机实训系列,旨在记录本人在大学上单片机技术这门课时所做的课程实训内容,并与大家分享基于51单片的课程作业,如果作业中的某些细节和代码能给大家一点启发那就更好了,希望大家能用51单片机做出多姿多彩的东西。最后不要忘记,我们的目标是星辰大海!
本游戏(石头剪刀布)玩法如下:
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 点阵模块,独立按键模块,矩阵按键模块,蜂 鸣器模块。
//
// 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);
}
}
代码有点长,这是一次课后作业,大概花了一个星期完成。