哈喽大家好!今天我来向大家介绍用二维数组和函数来设计的另一个游戏三子棋
当然在介绍代码之前我们先来讲解一下游戏规则这里我们实现的是人机对战(其实是人.
工智障),在如下棋盘中
其中九宫格获胜的方式是任意一个人的三个棋子连在同一条线上就为赢如下图
当然通过图片我们应该有了一个简单的设计思路及需要创建一个3x3的二维数组,在没
俩个格直接用一些线将其隔开下面就向大家展示我的设计思路
目录
一、程序实现的介绍
二、头文件的介绍
下面向大家展示头文件并对其在游戏的思路进行讲解
四、三子棋程序的重点突破
先将game.c的代码展现出来之后进行解析
下面向大家讲述上述函数的实现过程
一、初始化棋盘部分
二、打印棋盘
三、玩家下棋
四、电脑下棋
五、通过棋盘情况判断是否有赢棋的情况
六、平局
一、程序实现的介绍
当然通过上述图片我们可以先确定我们的基本设计思路,第一步、先打印用二维数组布
置一个九宫格的棋盘,第二步、将我们布置的棋盘打印展现给我们的玩家,第三步、玩
家根据棋盘情况进行下棋,第四步、电脑通过生成随机数的情况下棋,第五步、在每次
下棋过后对棋盘的情况进行一定的判断,看是否有赢棋的情况。
二、头文件的介绍
下面我将实现三子棋的代码的头文件test.c呈现给大家,帮大家先捋
清三子棋的实现思路
#include "game.h"
#include<time.h>
#include<stdlib.h>
void menu()
{
printf("*********************************\n");
printf("********1.play 0.exit**********\n");
printf("*********************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
//下棋
char ret;
while (1)
{
//玩家赢返回'*'电脑赢返回'#' 平局返回'Q' 如果继续'c'
PlayerMove(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
ComputerBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
在上图中我们可以看到在实现游戏之前我们需要,在主函数内我们需要
的结构是do —— while类型的因为我们需要在进行判断循环条件之前先
将我们的内容打印一遍,在进入游戏之前我们先打印一下我们的菜单告
诉玩家如何选择,在使用switch语句对玩家的输入进行选择性执行,将
input作为循环条件的判断是因为当选择0,及与我们设计的退出游戏相
匹配也与结束while循环的条件所匹配。上述的游戏简单区块的设置适
合多种游戏的起步执行。
下面向大家展示头文件并对其在游戏的思路进行讲解
#include<stdio.h>
#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 Computerboard(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
通过头文件我们可以较为清楚的了解游戏函数内部的实现,在进行游戏
函数的实现时,我们需要先将棋盘初始化为我们需要的形式——九宫
格。在初始化结束之后,将我们的棋盘进行打印以便于玩家对下棋位置
的选择,在这做好之后,需要写入玩家下棋实现的函数使玩家能够通过
键盘输入的方式进行玩游戏,之后写入电脑通过生成随机数的方式随机
找空白处下棋下棋(当然实现人工智能是需要用算法的),之后需要在每
次玩家或者电脑下棋之后判断输赢,当棋盘上出现赢棋的情况那就结束
游戏
四、三子棋程序的重点突破
先将game.c的代码展现出来之后进行解析
#include"game.h"
//初始化棋盘函数
void InitBoard(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++)
{
//将棋盘的内容全赋值为空格 ' '
board[i][j] = ' ';
}
}
}
//棋盘打印函
//我们需要的打印效果是这样的
// | |
//---|---|---
// | |
//---|---|---
// | |
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]);
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
//这里我们只需要每俩列之间打印一次 | 但是我们只需要在棋盘内打印 | 所以将其打印控制在列数 - 1
if (j < col - 1)
{
printf("|");
}
}
//每次打印问记得换行才能在输入下一行的数据
printf("\n");
//打印分割信息
//打印之后判断是否是最后一行打印,如果不是那么需要在下一次打印之前先打印 ---|---|---
if (i < row - 1)
{
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");
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
//对玩家输入的坐标进行判断是否在棋盘内部以及对是否被占用的判断
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
}
else
{
printf("坐标被占用请重新选择\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
//电脑下棋函数
void ComputerBoard(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("电脑下棋\n");
//电脑下棋用while循环主要是可能下棋的位置以及被下所以多次生成随机数进行下棋
while (1)
{
x = rand() % row;
y = rand() % col;
if (board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
}
//如果满了返回1 没满返回0
int IsFull(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++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
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][1] != ' ')
{
return board[i][1];
}
}
//判断列是否存在三子连在一起的情况
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j] == board[1][j]&&board[2][j] == board[1][j]&&board[1][j] != ' ')
{
return board[1][j];
}
}
//判断对角线是否存在连在一起的情况
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
return board[1][1];
}
if(board[0][2]==board[1][1]&&board[1][1]==board[2][0]&&board[1][1]&&board[1][1]!=' ')
{
return board[1][1];
}
//判断是否平局
if (IsFull(board, ROW, COL))
{
return 'Q';
}
//游戏继续
return 'C';
}
下面向大家讲述上述函数的实现过程
一、初始化棋盘部分
//初始化棋盘函数
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
将棋盘3x3的内容初始化为我们的空格以便能后续打印能显示我们想要
的结果
二、打印棋盘
//棋盘打印函数
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]);
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
//打印分割信息
if (i < row - 1)
{
for (j = 0; j < col; j++)
{
printf("---");
if ( j < col - 1)
printf("|");
}
printf("\n");
}
}
}
当然这里我们只向大家展示这种适合打印设置不仅仅是适合打印3x3的
九宫格,n x n 的棋盘也能打印,所以向大家只介绍这一种棋盘打印的
方式。比如我们第一行想打印的是 | | ,那么就需要数组的内
容和 | 分次打印,且数组内容的打印次数比 | 打印的次数多一次,
那么我们在设置打印的时候就需要判断打印的 | 是否少于 我们的列数 (也就是col - 1)
在打印完第一行之后进行换行打印,换行打印需要确定的是,是否打印
到最后一行的信息,如果没有打印到最后一行那么需要在下一组数据打
印之前先在他们上面打印 ---|---|---以做分割之后就是循环打印。
三、玩家下棋
//玩家下棋函数
void PlayerMove(char board[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
printf("玩家请输入\n");
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
}
else
{
printf("坐标被占用请重新选择\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
玩家下棋的主要过程是获取玩家从键盘上输入的内容,将数组中对应的
位置转化为我们下棋的标识符,当然为了防止重复下棋,在每次下棋之
后需要判断该坐标是否为我们输入的标识符,如果不是则可以进行下
棋,否则打印不能重复下棋。当然我们输入的坐标也需要进行判断看是
否超出棋盘范围,当然为了玩家的游戏体验更好我们需要对玩家输入的
数据进行一定的处理,因为他可能并不知道数组的下标是从0开始的所
以我们允许的输入是1 —— 3 而不是0 —— 2
四、电脑下棋
//电脑下棋函数
void ComputerBoard(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;
}
}
}
//当然我们将使用rand()的函数先向大家介绍一下,
//rand()的使用需要用srand((unsigned int)time(NULL));去调用,
//其中srand的头文件需要 #include<stdlib.h> 和 include<time.h>俩个头文件
我们想让电脑进行下棋就需要生成一个随机数去 % 我们的行和列,看
最后剩下结果X与Y是否在棋盘范围内,电脑生成随机数的方式以及需要
的内容在代码块中有介绍,这里因为我们不知道电脑在第一次的随机数
可以找到合适的坐标所以我们进行while循环的方式去找一个合适的坐
标,当然电脑下棋就不需要对其坐标进行修改。
五、通过棋盘情况判断是否有赢棋的情况
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][1] != ' ')
{
return board[i][1];
}
}
//列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j]==board[1][j]&&board[2][j]==board[1][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
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';
}
当然在判断赢棋情况之前我们先规定IsWin返回的不同值表示的不同含
义(例如我规定的是Q平局,C游戏未结束,如果玩家赢了返回玩家的
字符,电脑赢返回电脑的字符),当然判断输赢就是看每一行,每一
列,和对角线的情况有三颗相同的棋连在一起就为赢,这里我们也需要
注意,因为棋盘的起初就为全部相同,那么我们在判断输赢的时候就要
排除数组内容为空格的情况。
六、平局
//如果满了返回1 没满返回0
int IsFull(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++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
当我们进行判断的时候只需要判断棋盘上是否还有空格的存在,如果没
有那么就返回0,判断平局为加,否则返回1,说明出现平局的情况。
最后向大家展示完整代码
#include<stdio.h>
#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 Computerboard(char board[ROW][COL], int row, int col);
//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
#include"game.h"
//初始化棋盘函数
void InitBoard(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++)
{
board[i][j] = ' ';
}
}
}
//棋盘打印函数
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]);
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
{
printf("|");
}
}
printf("\n");
//打印分割信息
if (i < row - 1)
{
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");
printf("请输入坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 3 && y >= 1 && y <= 3)
{
if (board[x - 1][y - 1] == ' ')
{
board[x - 1][y - 1] = '*';
}
else
{
printf("坐标被占用请重新选择\n");
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
//电脑下棋函数
void ComputerBoard(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;
}
}
}
//如果满了返回1 没满返回0
int IsFull(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++)
{
if (board[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
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][1] != ' ')
{
return board[i][1];
}
}
//列
int j = 0;
for (j = 0; j < col; j++)
{
if (board[0][j]==board[1][j] && board[2][j] == board[1][j] && board[1][j] != ' ')
{
return board[1][j];
}
}
//对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
{
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';
}
#include "game.h"
#include<time.h>
#include<stdlib.h>
void menu()
{
printf("*********************************\n");
printf("********1.play 0.exit**********\n");
printf("*********************************\n");
}
void game()
{
char board[ROW][COL] = { 0 };
//初始化棋盘的函数
InitBoard(board,ROW,COL);
//打印棋盘
DisplayBoard(board,ROW,COL);
//下棋
char ret;
while(1)
{
//玩家赢返回'*'电脑赢返回'#' 平局返回'Q' 如果继续'c'
PlayerMove(board,ROW,COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
ComputerBoard(board, ROW, COL);
//判断输赢
ret = IsWin(board, ROW, COL);
if (ret != 'C')
{
break;
}
DisplayBoard(board, ROW, COL);
}
if (ret == '*')
{
printf("玩家赢\n");
}
else if (ret == '#')
{
printf("电脑赢\n");
}
else
{
printf("平局\n");
}
DisplayBoard(board, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
default:
printf("选择错误,请重新选择\n");
break;
}
}
while (input);
return 0;
}