返回

三子棋小游戏

发布时间:2023-01-31 06:00:45 120

今天实现一个三子棋小游戏,虽然小,但是“麻雀虽小,五脏俱全”,通过三子棋游戏,我们来学习如何模块化地写代码。

首先,我们创建一个game.h头文件,再创建一个game.c和test.c源文件。

//头文件用来放各种函数的声明,以及引用库里的头文件;game.h用来写各个函数的内容;test.c用来将各个函数模块连接起来

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include


#define ROW 3
#define COL 3
//函数的声明
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

 //头文件(上图)

然后,开始在test.c中写代码。我们希望玩家在一开始的时候可以看到游戏的一个界面,并且决定自己玩还是不玩游戏,所以这里我们用一个do while循环,先让玩家看到界面,再选择自己玩不玩,并且如果想,可以一直玩下去:

void menu()
{
printf("***************************\n");
printf("*********三 子 棋**********\n");
printf("*********1.开始游戏********\n");
printf("*********0.退出游戏********\n");
printf("***************************\n");
}

//menu

int main()
{
int input = 0;
srand((unsigned int)time(NULL));//后面电脑随机生成坐标要用到rand函数
do
{
menu();
printf("请输入>: ");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}

这里我们把input作为while的条件,输入1开始游戏,0退出游戏。

接下来,我们就要开始写游戏的内容了也就是game函数。

下棋嘛,肯定要有棋盘,所以创建一个3*3的二维数组,元素全部是空格,就定义为board函数吧,在头文件里面声明一下,再在game.c里面写:

void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';//空格不仅占位了,而且又看不见;0虽然看不见,但是不能占位
}
}
//memset(&board[0][0], ' ', row* col * sizeof(board[0][0]));
}

//也可以用memset函数

创建好了数组,但是什么都看不到,我们要加上一些条条框框,所以定义DisplayBoard函数:

void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j printf("|");
}
printf("\n");
if (i < row - 1)
{
j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}

接下来就可以看到棋盘了:

三子棋小游戏_#include

棋盘做好了,就可以下棋了,你下一步,打印一下棋盘,电脑下一步,再打印一下棋盘,你再下一步,打印一下棋盘,电脑下一步......我们发现这里要用到循环,并且,下完之后,我们最好都去判断一下输赢:

void game()
{
//创建一个3*3的二维数组
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board,ROW,COL);
//显示棋盘
DisplayBoard(board,ROW,COL);
while (1)
{
//玩家下棋
PlayerMove(board,ROW,COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判读输赢
ret = IsWin(board, ROW, COL);
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
}

这就是大概的流程,以及各自的函数;

首先,玩家下棋:

void PlayerMove(char board[ROW][COL], int row, int  col)
{
int x = 0;
int y = 0;
printf("玩家下棋>:\n");
while (1)
{
printf("请输入要下棋的坐标>:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}

在玩家的眼中,大多是认为第一行第一列就是1 1,而不是0 0,所以我们就要按照玩家的习惯去写,下完了打印一下棋盘,

接着电脑下棋,这里就是个小游戏,不是什么人机大战,所以不会写的电脑很厉害,当然现在我也写不出来那种类似于人工智能的代码,所以就rand取随机数就好了(srand函数写外面,一次游戏调用一次就行了):

void ComputerMove(char board[ROW][COL], int row, int  col)
{
int x = 0;
int y = 0;
printf("电脑下棋>:\n");

while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}

三子棋小游戏_#define_02

电脑的话坐标就直接从0开始到2结束就好了,省的麻烦,接着打印棋盘;

现在还有最后一个模块:判断输赢,也就是IsWin函数:

//判断输赢
//玩家赢 —— '*'
//电脑赢 —— '#'
//平局 —— 'Q'
//继续 —— 'C'
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断是否是平局
if (IsFull(board, row, col))
return 'Q';
//游戏继续
return 'C';
}
int IsFull(char board[ROW][COL], int row, int  col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (i = 0; i < col; i++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}

我们一开始在头文件里面用define定义了常量ROW和COL,是为了以后可以快速的改变棋盘的大小,但是在判断输赢中又把我们的棋盘限制住了,但是呢,无论如何还是满足了作为“三”子棋的条件,以后学的更多了之后可以再改进改进。

这里IsWin函数中玩家和电脑赢返回的‘*’ ‘#‘正好是玩家和电脑输入的’*’ ‘#’,灵活地运用了函数的返回值:

void game()
{
//创建一个3*3的二维数组
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board,ROW,COL);
//显示棋盘
DisplayBoard(board,ROW,COL);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board,ROW,COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判读输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("你赢了,恭喜你!\n");
else if (ret == '#')
printf("电脑赢了呢\n");
else if (ret == 'Q')
printf("平局!\n");
}

而且把判断输赢放在循环外面,平局的判断放在里面,也减少了代码的重复;三子棋小游戏_#define_03

三子棋小游戏_i++_04

这样,我们的三子棋小游戏就写好了,思路不算复杂,主要还是认识并了解代码的模块化,毕竟这么写下来也有个300多行代码,如果还像以前做题目一样全部写在一个源文件里面,就太麻烦了。



最后,源码附上:

game.h :

#define _CRT_SECURE_NO_WARNINGS 1
#include
#include
#include
#include


#define ROW 3
#define COL 3
//函数的声明
//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);
//打印棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);
//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);

game.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
board[i][j] = ' ';//空格不仅占位了,而且又看不见;0虽然看不见,但是不能占位
}
}
//memset(&board[0][0], ' ', row* col * sizeof(board[0][0]));
}

//void DisplayBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// int j = 0;
// for (i = 0; i < row; i++)
// {
// for (j = 0; j < col; j++)
// {
// printf("%c ", board[i][j]);
// }
// printf("\n");
// }
//}//什么都看不到

//void DisplayBoard(char board[ROW][COL], int row, int col)
//{
// int i = 0;
// int j = 0;
// for (i = 0; i < row; i++)
// {
// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
// if (i < row - 1)
// printf("---|---|---\n");
// }
//}//列数卡死了

void DisplayBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if(j printf("|");
}
printf("\n");
if (i < row - 1)
{
j = 0;
for (j = 0; j < col; j++)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}

void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家下棋>:\n");
while (1)
{
printf("请输入要下棋的坐标>:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标被占用,请重新输入\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
}

//电脑随机下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋>:\n");

while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}

int IsFull(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (i = 0; i < col; i++)
{
if (board[i][j] == ' ')
return 0;
}
}
return 1;
}

//判断输赢
//玩家赢 —— '*'
//电脑赢 —— '#'
//平局 —— 'Q'
//继续 —— 'C'
char IsWin(char board[ROW][COL], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
}
for (i = 0; i < col; i++)
{
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
}
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != ' ')
{
return board[1][1];
}
if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
{
return board[1][1];
}
//判断是否是平局
if (IsFull(board, row, col))
return 'Q';
//游戏继续
return 'C';
}

test.c :

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

void menu()
{
printf("***************************\n");
printf("*********三 子 棋**********\n");
printf("*********1.开始游戏********\n");
printf("*********0.退出游戏********\n");
printf("***************************\n");
}

void game()
{
//创建一个3*3的二维数组
char board[ROW][COL] = { 0 };
//初始化棋盘
InitBoard(board,ROW,COL);
//显示棋盘
DisplayBoard(board,ROW,COL);
char ret = 0;
while (1)
{
//玩家下棋
PlayerMove(board,ROW,COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判读输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋
ComputerMove(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
printf("你赢了,恭喜你!\n");
else if (ret == '#')
printf("电脑赢了呢\n");
else if (ret == 'Q')
printf("平局!\n");
}

int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请输入>: ");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
字符串左旋 2023-01-31 05:49:40