本篇博客将介绍利用rand、srand生成随机数来实现五子棋小游戏。
主要从游戏流程和所需要的自定义函数两方面对五子棋小游戏进行讲解,其中所用到的知识都是相对来说比较基础,小白可以上手的!!!废话不多说,下面开始进行讲解。
一、游戏流程
想要写好一个五子棋小游戏,首先就要确定它具体的流程,依次来梳理从哪方面下手去实现这个游戏。
具体游戏流程:
1.创建一个棋盘并初始化,所有位置设为空格;
2.打印棋盘;
3.玩家落子。让玩家输入坐标(row,col);
4.打印棋盘;
5.判定获胜---->从连线、棋盘是否满了两个方面,判断是否继续下棋、人胜、电脑胜、和棋这四种情况;
6.电脑进行落子,随机落子;
7.打印棋盘;
8.判定获胜---->同上述第5条。
二、代码实现----自定义函数
有了具体的需求,我们所能做的就是根据需求去创建不同的函数,每个函数各司其职,最终达到实现游戏的效果!
2.1 头文件及宏定义
在介绍函数之前,我们引入函数中所需的头文件与宏定义。
这里着重介绍一下宏定义的数字,在本程序中会反复出现的
一个数字---5(5行5列),像这种反复出现的数字也被称为
magic number:在写程序中因为太多所以很容易混淆其含义
,所以我们不妨在最开始将其用宏定义---令它代表特定的含
义。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h> //rand、srand函数头文件
#include<time.h> //time函数头文件
#define MAX_ROW 5 //magic number,在一个程序中反复出现的数字,容易让人混淆含义
#define MAX_COL 5 //所以直接define宏定义这个数,相当于全局变量
2.2 自定义函数
接下来我们开始介绍这些自定义函数!
0.菜单函数
作用:优化用户体验
int menu(){
printf("=======================================================\n\n");
printf("=======================================================\n\n");
printf("================= 欢迎来到五子棋游戏! =================\n\n");
printf("===================== 1.开始游戏 ======================\n\n");
printf("===================== 0.退出游戏 ======================\n\n");
printf("=======================================================\n\n");
printf("=======================================================\n\n");
printf("请输入您的选择:");
int choice = 0;
scanf("%d", &choice);
return choice;
}
1.初始化棋盘函数
目标:令棋盘中字符都为‘0’,使得每次开局都能是新的一轮
void init(char chess[MAX_ROW][MAX_COL]){
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
chess[row][col] = ' '; //将字符数组初始化为全空
}
}
}
2.打印棋盘函数
目标:尽量照顾用户体验
void printChess(char chess[MAX_ROW][MAX_COL]){ //注意棋盘数据类型是字符型!!!
printf(" 0 1 2 3 4 \n");
printf(" +---+---+---+---+---+\n");
for (int row = 0; row < MAX_ROW; row++){
printf("%d |",row); //此步为了让棋盘显示行数和列数
for (int col = 0; col < MAX_COL; col++){
printf(" %c |", chess[row][col]);
}
printf("\n");
printf(" +---+---+---+---+---+\n");
}
}
3.玩家落子函数
目标:让玩家输入想要落子的坐标--->判断范围是否超出以
及落子处是否已经有子--->满足条件在此处落棋子‘x’,否
则重新输入落子位置并重新判断。
void playerChoose(char chess[MAX_ROW][MAX_COL]){
while (1){
printf("请输入(row col) (注:其中row、col均属于区间[0,4])\n");
int row = 0;
int col = 0;
scanf("%d %d", &row, &col);
if (row > 4 || row < 0 || col > 4 || col < 0){ //先对范围进行判断
printf("您的输入有误!请重新输入!\n");
continue;
}
if (chess[row][col] != ' '){ //超出区间范围的棋子可能也不为空 所以两者并列if 而非else if
printf("这里已经有子了,请重新输入!\n");
continue;
}
//并非上述两种情况,进行赋值落子
chess[row][col] = 'x';
break;//结束循环
}
}
4.判定棋盘是否满的函数
目标:返回0为未满,返回1为满了
int isChessFull(char chess[MAX_ROW][MAX_COL]){
for (int row = 0; row < MAX_ROW; row++){
for (int col = 0; col < MAX_COL; col++){
if (chess[row][col] == ' ')
return 0;
}
}
return 1;
}
5.判定连线函数
目标:
函数返回类型为char
如果人胜,返回‘x’
如果电脑胜,返回‘o’
如果和棋(棋盘满但未判定胜负’),返回‘q’
如果游戏还没有结束(棋盘未满且未判定胜负),返回‘ ’
char isGameWin(char chess[MAX_ROW][MAX_COL]){
for (int row = 0; row < MAX_ROW; row++){ //比较行
if ((chess[row][0] != ' ') &&
(chess[row][0] == chess[row][1])&&
(chess[row][0] == chess[row][2])&&
(chess[row][0] == chess[row][3])&&
(chess[row][0] == chess[row][4])){
return chess[0][0];
}
}
for (int row = 0; row < MAX_ROW; row++){ //比较行
if ((chess[row][0] != ' ') &&
(chess[row][0] == chess[row][1]) &&
(chess[row][0] == chess[row][2]) &&
(chess[row][0] == chess[row][3]) &&
(chess[row][0] == chess[row][4]) ){
return chess[0][0];
}
}
for (int col = 0; col < MAX_COL; col++){ //比较列
if ((chess[0][col] != ' ') &&
(chess[0][col] == chess[1][col]) &&
(chess[0][col] == chess[2][col]) &&
(chess[0][col] == chess[3][col]) &&
(chess[0][col] == chess[4][col]) ){
return chess[0][0];
}
}
if ((chess[0][0] != ' ') && //比较正对角
(chess[0][0] == chess[1][1]) &&
(chess[0][0] == chess[2][2]) &&
(chess[0][0] == chess[3][3]) &&
(chess[0][0] == chess[4][4]) ) {
return chess[0][0];
}
if ((chess[0][4] != ' ') && //比较反对角
(chess[0][4] == chess[1][3]) &&
(chess[0][4] == chess[2][2]) &&
(chess[0][4] == chess[3][1]) &&
(chess[0][4] == chess[4][0]) ) {
return chess[0][4];
}
if (isChessFull(chess) == 1){ //函数别忘记要传参!!!
return 'q';
}
return ' ';//不符合上述要求则返回空,说明游戏仍需继续
}
6.电脑落子函数
目标:随机生成坐标数--->判断落子地方是否为空--->若空
进行落子,否则继续循环。
注:此处应用随机落子,所以并不智能,应用到了time和sr-
-and和rand函数
void computerChoose(char chess[MAX_ROW][MAX_COL]){
while (1){
int row = rand() % MAX_ROW; //注意细节,函数要有()
int col = rand() % MAX_COL; //rand()
if (chess[row][col] != ' '){
continue;
}
chess[row][col] = 'o';
break; //函数内没有return时,不要忘记break结束循环
}
}
7.判定是否获胜函数
目标:根据‘x’、‘o’、‘q’、‘ ’,这四种情况分类,且前三
种情况返回1,最后一种为空表示应继续下棋返回0(与第5个
函数相呼应)。
int isWin(char winner){
if (winner == 'x'){
printf("恭喜您获胜了!\n");
return 0;
}
if (winner == 'o'){
printf("很遗憾,您未获胜。\n");
return 0;
}
if (winner == 'q'){
printf("您与电脑和棋了!\n");
return 0;
}
if (winner == ' '){
return 1;
}
}
8.创建游戏函数
目标:利用上述0-7这几个函数,对最开始提到的具体游戏流
程进行实现。
int gameGobang(){
char chess[MAX_ROW][MAX_COL];
//1.创建期盼并初始化,所有位置设置为空格
init(chess); //一次游戏只需要初始一次
char winner = ' ';//创建winner变量,为了后续接收函数return值
//2.打印棋盘
printChess(chess);
while (1){
//3.玩家落子。让玩家输入坐标(row,col)
playerChoose(chess);
//4.打印棋盘
printChess(chess);
//5.判定获胜---从连线、棋盘是否满了两个方面,判断是否继续下棋、人胜、电脑胜、和棋这四种情况;
winner = isGameWin(chess);
if (isWin(winner) == 0){
break;
}
//6.电脑进行落子,随机落子
computerChoose(chess);
//7.打印棋盘
printChess(chess);
//8.判定获胜---同上述第5条。
winner = isGameWin(chess);
if (isWin(winner) == 0){
break;
}
}
}
2.3 main函数(主函数)
有了上面的头文件和0-8这9个自定义函数,接下来我们进行main函数的编写。
main函数(主函数)
目标:与menu函数相呼应,根据菜单中指示的开始、结束游
戏,并判断输入形式的正确性。
int main(){
srand((unsigned int)time(0));//与rand函数对应,生成随机数组
while (1){
int choice = menu();
if (choice == 0){
printf("您已退出猜数字游戏\n");
break;
}
else if (choice == 1){
gameGobang();
}
else{
printf("您输入的形式有误!请输入0或1!!\n");
}
}
return 0;
}
2.4 最终呈现效果(部分)
最终呈现的效果的开头如下图所示,因为下一盘五子棋真的太长啦~所以只截取了开头的部分---->选择开始游戏、本人下了一步棋、电脑下了一步棋。
本人也比较小白,所以还有很多实现的不太完善的地方,欢迎大家提点交流呀~
如果想要玩的话,不过不妨自己也去尝试一下,也欢迎来和我沟通想法呀~
三、总结
通过游戏流程和代码实现我们实现了猜数字小游戏,游戏实现的主要思路是先确定五子棋小游戏的流程---->根据流程需求去实现不同的函数---->不断进行调试、优化,最终程序实现!
有了大概的思路就可以去自己编写五子棋小游戏啦!在敲代码的过程中可能会遇到一些大大小小的问题,再参考本文代码的同时,也一定一定不要忘了多调试!多调试!多调试!(重要的事情说三遍!!!)调试的过程中也会让自己掌握的更加深入熟练,加油!
欢迎在评论区进行提问、指正与讨论,感谢各位的观看~