在前面的文章中已经讲过几个小游戏了,而且在其中也讲解了一些之前未涉及的知识点,比如随机数的生成、多文件程序等等。今天,我们把这些知识点结合起来,并着重凸显这些知识点来实现一个大家耳熟能详的小游戏——剪刀、石头、布,希望大家能够从这个小游戏中加深对于这些知识的了解,同时收获快乐!
目录
3.各部分功能的具体实现(全面贯彻多文件程序,其实倒也不用搞这么多文件😀)
3.1游戏指南(特别建立一个文件guide.c存放该部分功能)
3.2进行游戏 (特别建立一个文件game.c存放该部分功能)
3.3查看战况(特别建立一个文件check.c存放该部分功能)
3.4随机数的生成(特别建立一个文件random.c存放该部分功能)
剪刀、石头、布的游戏规则是:用手表示剪刀、石头、布,握紧拳头表示石头,伸出食指和中指表示剪刀,伸出五指表示布。石头会硌坏剪刀、剪刀能剪断布、布能包住石头。设计程序实现游戏者和计算机之间的剪刀、石头、布游戏,要求能够重复游戏,直到游戏者选择结束。除此之外,还能够阅读游戏指南,查看当前战况等。
还记得我在猜数字游戏的实现中说过的一句话吗?没错,我们在写编程题或者小游戏代码时,最重要的就是理清实现思路——主体是什么?为了实现目的要创建哪些函数?函数的功能都是什么?只有当我们心中有了一个大体的框架,知道该做些什么时,我们才能更高效地编写代码,完成程序设计。
剪刀、石头、布小游戏的大致思路如下:
1.menu(提供游戏菜单,由玩家选择是否进行游戏);
2.game( )(进行游戏);
3.本轮游戏结束,打印游戏菜单并再次询问玩家选择。
一次游戏的过程是:计算机随机生成剪刀、石头或布,游戏者从键盘输入石头、剪刀或布,然后进行比较并给出游戏结果。由于需要满足查看战况。因此,需要保存游戏次数和每次的结果。
我们在思考大体框架时不用过多在意具体函数的实现方法,可以先起个能表达其功能的函数名并把它放在需要的位置。(说白了就是先搞一个空壳函数占位置,等到大体框架调试完毕不再有问题后,再去实现这些空壳函数)大体框架代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
int select;
do
{
printf("1.游戏指南 2.开始游戏 3.查看战况 0.退出游戏\n");
printf("请输入你的选择:->");
scanf("%d", &select);
switch (select)
{
case 1:Guide(); break;
case 2:Game(); break;
case 3:Check(); break;
default:printf("游戏结束!\n"); break;
}
} while (select);
return 0;
}
在多文件程序中,头文件毋庸置疑是最为关键的,相当于整个程序的目录,记载着各个源文件中可能用的库函数、自定义函数、数据类型、全局变量、符号常量等等内容。
因为我们这里建立了多个源文件,而大部分源文件用不到头文件中大部分功能),所以,这里就把头文件命名为game.h。
game.h的代码如下:
#pragma once
#define N 10
#include<stdio.h>
typedef enum HandType
{
stone = 1,
scissor,
paper
}HandType;
typedef enum ResultType
{
lose,
tie,
win
}ResultType;
typedef struct StateType
{
HandType computer;
HandType player;
ResultType result;
}StateType;
void Guide(void); //函数声明,游戏指南
void Check(void); //函数声明,查看战况
void Game(void); //函数声明,一次游戏
int Secret(int low, int high);//函数声明,产生随机数
上面三个结构体类型的建立,分别用于表示手势、胜负关系和保存战绩。?
我们在大致流程中提过要能够浏览游戏指南,从而对于新手(即不了解规则的朋友)更加友好,使其能够无障碍进行游戏,这个函数倒是没有太多的细节,只需要进行简单的规则打印。
游戏指南函数Guide的代码实现如下:
void Guide(void)
{
printf("************************************************************\n");
printf("1.握紧拳头表示石头,伸出食指和中指表示剪刀,伸出五指表示布。\n");
printf("2.石头会硌坏剪刀、剪刀能剪断布、布能包住石头。\n");
printf("3.能够重复游戏、阅读游戏指南、查看当前战况等。\n");
printf("************************************************************\n");
printf("\n");
}
这里为了一定程度上的美观,又打印了两行*号,大家也可以根据自己的需求自行调整。
设函数Game实现一次游戏,Game函数的算法实现如下:
设枚举类型HandType{stone = 1,scissor,paper}表示石头、剪刀和布,设枚举类型ResultType
{lose,tie,win}表示负、平和胜,设全局数组gameResult[N]保存游戏结果,设全局变量count保存游戏次数。1.handComputer=随机生成剪刀、石头、布;
2.handPlayer=从键盘输入剪刀、石头、布;
3.比较handComputer和handPlayer,根据不同情况给出游戏结果;
4.gameResult[count] =游戏结果;
5.count++;
函数Game的代码如下所示:
void Game(void)
{
enum HandType handComputer, handPlayer;
enum ResultType result;
int temp, select;
temp = Secret(1, 3);
handComputer = (HandType)temp;
printf("请输入您的选择:1.石头 2.剪子 3.布:");
scanf("%d", &select);
handPlayer = (HandType)select;
if (handComputer == handPlayer)
result = tie;
else
{
switch (handPlayer)
{
case stone:
if (handComputer == scissor) result = win;
else result = lose;
break;
case scissor:
if (handComputer == paper) result = win;
else result = lose;
break;
case paper:
if (handComputer == stone) result = win;
else result = lose;
break;
}
}
if (result == win)
printf("你赢了!\n");
else if (result == lose)
printf("你输了!\n");
else
printf("平局!\n");
gameResult[count].computer = handComputer; //保存游戏结果
gameResult[count].player = handPlayer;
gameResult[count].result = result;
count++;
}
上面有一个函数Secret的功能暂时还没介绍,实际上是随机数生成函数,不过由于我们要把该知识点单列出来以加深大家的理解,所以,在本项目中,它也是一个单独的源文件。
我们前面讲到建立了结构体类型StateType来展示一句游戏的战况,而想展示所有战况,肯定要建立一个该数据类型数组来保存数据,具体查看战况,也就是把该数组中数据都按要求打印出来即可。
查看战况函数Check的代码如下:
void Check(void)
{
int i;
printf("计算机\t玩家\t结果\n");
for (i = 0; i < count; i++)
{
OutResult1(gameResult[i].computer);
OutResult1(gameResult[i].player);
OutResult2(gameResult[i].result);
}
}
里面又有两个函数OutResult1、OutResult2,因为枚举类型中的元素是该枚举类型变量的值,而枚举元素都是整型符号常量,换句话说该枚举类型的变量实际上都是整型数据,无法打印出我们想要的结果(枚举元素的字面含义),所以在这里就通过再自定义两个函数,来进行打印。
打印手势函数OutResult1的代码如下:
void OutResult1(enum HandType hand)
{
switch (hand)
{
case stone:printf("石头\t"); break;
case scissor:printf("剪刀\t"); break;
case paper:printf("布\t"); break;
}
}
打印胜负关系函数OutResult2的代码如下:
void OutResult2(enum ResultType result)//函数定义,输出枚举类型ResultType的枚举元素
{
switch (result)
{
case lose:printf("负\n"); break;
case tie:printf("平\n"); break;
case win:printf("胜\n"); break;
}
}
上面的打印都是灵活的,大家想打印成啥都可以,根据个人喜欢吧!
随机数生成这里单独放置,大家加深一下记忆就行。至于具体的知识点讲解,大家可以看下面这篇文章??????有趣的代码——猜数字游戏的实现-CSDN博客
随机数生成函数Secret代码如下:
int Secret(int low, int high)
{
srand((unsigned int)time(NULL));
return (low + rand() % (high - low + 1));
}
?当然这里要用到一些库函数哦,只是上面仅仅是Secret函数的代码,大家不要迷哦!
#pragma once
#define N 10
#include<stdio.h>
typedef enum HandType
{
stone = 1,
scissor,
paper
}HandType;
typedef enum ResultType
{
lose,
tie,
win
}ResultType;
typedef struct StateType
{
HandType computer;
HandType player;
ResultType result;
}StateType;
void Guide(void); //函数声明,游戏指南
void Check(void); //函数声明,查看战况
void Game(void); //函数声明,一次游戏
int Secret(int low, int high);//函数声明,产生随机数
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
int select;
do
{
printf("1.游戏指南 2.开始游戏 3.查看战况 0.退出游戏\n");
printf("请输入你的选择:->");
scanf("%d", &select);
switch (select)
{
case 1:Guide(); break;
case 2:Game(); break;
case 3:Check(); break;
default:printf("游戏结束!\n"); break;
}
} while (select);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void Guide(void)
{
printf("************************************************************\n");
printf("1.握紧拳头表示石头,伸出食指和中指表示剪刀,伸出五指表示布。\n");
printf("2.石头会硌坏剪刀、剪刀能剪断布、布能包住石头。\n");
printf("3.能够重复游戏、阅读游戏指南、查看当前战况等。\n");
printf("************************************************************\n");
printf("\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int count = 0;
struct StateType gameResult[N];
void Game(void)
{
enum HandType handComputer, handPlayer;
enum ResultType result;
int temp, select;
temp = Secret(1, 3);
handComputer = (HandType)temp;
printf("请输入您的选择:1.石头 2.剪子 3.布:");
scanf("%d", &select);
handPlayer = (HandType)select;
if (handComputer == handPlayer)
result = tie;
else
{
switch (handPlayer)
{
case stone:
if (handComputer == scissor) result = win;
else result = lose;
break;
case scissor:
if (handComputer == paper) result = win;
else result = lose;
break;
case paper:
if (handComputer == stone) result = win;
else result = lose;
break;
}
}
if (result == win)
printf("你赢了!\n");
else if (result == lose)
printf("你输了!\n");
else
printf("平局!\n");
gameResult[count].computer = handComputer; //保存游戏结果
gameResult[count].player = handPlayer;
gameResult[count].result = result;
count++;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void OutResult1(enum HandType hand); //只在该程序中使用
void OutResult2(enum ResultType result);//只在该程序中使用
extern StateType gameResult[];//引用外部变量
extern int count;
void Check(void)
{
int i;
printf("计算机\t玩家\t结果\n");
for (i = 0; i < count; i++)
{
OutResult1(gameResult[i].computer);
OutResult1(gameResult[i].player);
OutResult2(gameResult[i].result);
}
}
void OutResult1(enum HandType hand)
{
switch (hand)
{
case stone:printf("石头\t"); break;
case scissor:printf("剪刀\t"); break;
case paper:printf("布\t"); break;
}
}
void OutResult2(enum ResultType result)//函数定义,输出枚举类型ResultType的枚举元素
{
switch (result)
{
case lose:printf("负\n"); break;
case tie:printf("平\n"); break;
case win:printf("胜\n"); break;
}
}
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int Secret(int low, int high)
{
srand((unsigned int)time(NULL));
return (low + rand() % (high - low + 1));
}