还有这事?——一小时学会三子棋(优化版)

前情提要

在学习了数组之后,我们了解了数组的创建,掌握了数组在内存中的存放,也认识到了一维数组和二维数组的结构,因此,下面就让我们用二维数组来实战一下,利用所学,实现一个简易的三子棋游戏,Let’s go。

一.代码展示部分

三子棋.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void game()
{
	int tmp;
	char board[ROW][COL];
	initialboard(board);//棋盘初始化
	printboard(board, ROW, COL);//打印棋盘
	while (1)//下多次
	{
		printf("玩家下棋:\n");
		playermove(board, ROW, COL);
		printboard(board, ROW, COL);
		tmp = judgefull(board, ROW, COL);
		if (tmp == 0)
		{
			printf("棋盘已满\n");
			break;
		}
		tmp = judgewin(board, ROW, COL);
		if (tmp == 0)
		{
			printf("玩家胜!\n");
			break;
		}
		printf("电脑下棋:\n");
		computermove(board, ROW, COL);
		printboard(board, ROW, COL);
		tmp = judgefull(board, ROW, COL);
		if (tmp == 0)
		{
			printf("棋盘已满\n");
			break;
		}
		tmp = judgewin(board, ROW, COL);
		if (tmp == 0)
		{
			printf("电脑胜!\n");
			break;
		}
	}

}

void menu()
{
	printf("************************\n");
	printf("*******  1.play  *******\n");
	printf("*******  0.exit  *******\n");
	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");
		}
		}
	} while (input);
	return 0;
}

game.c

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"//引头文件

void initialboard(char board[ROW][COL])
{
	int i, j;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			board[i][j] = ' ';
		}
	}
}
//棋盘初始化

void printboard(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		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 i, j;
	printf("请输入您要下的位置坐标>:");
	scanf("%d%d", &i, &j);
	if (i >= 1 && i <= row&&j >= 1 && j <= col)
	{
		if (board[i - 1][j - 1] == ' ')
		{
			board[i - 1][j - 1] = '*';
		}
		else
		{
			printf("此坐标对应位置已被下过,请重下!\n");
		}
	}
	else
	{
		printf("坐标非法,请重新输入!\n");
	}
}
//玩家下棋

void computermove(char board[ROW][COL], int row, int col)
{
	int i, j;
	while (1)
	{
		i = rand() % row;//生成随机坐标
		j = rand() % col;
		if (board[i][j] == ' ')
		{
			board[i][j] = '!';
			break;
		}
	}
}
//电脑下棋

int judgefull(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		for (j = 0; j < col; j++)
		{
			if (board[i][j] == ' ')
				return 1;
		}
	}
	return 0;
}
//判断棋盘是否下满

int judgewin(char board[ROW][COL], int row, int col)
{
	int i, j, k;
	for (i = 0; i < row; i++)//行
	{
		for (j = 0; j < col - 2; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 0; i < col; i++)//列
	{
		for (j = 0; j < row - 2; j++)
		{
			if (board[j][i] == board[j + 1][i] && board[j][i] == board[j + 2][i] && board[j][i] != ' ')
				return 0;
		}
	}
	for (i = 0; i < row - 2; i++)//主对角线
	{
		for (j = i; j < col - 2; j++)
		{
			if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 0; i < row - 2; i++)//副对角线
	{
		for (j = col - i; j > 1; j--)
		{
			if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 1; i < row - 2; i++)//主对角线下部分
	{
		for (j = 0, k = i; j < col - 2; j++)
		{
			if (i - j == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (j = 1; j < col - 2; j++)//主对角线上部分
	{
		for (i = 0, k = j; i < row - 2; i++)
		{
			if (j - i == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (i = 0; i < row - 2; i++)//副对角线上部分
	{
		for (j = col - 2, k = j; j > 1; j--)
		{
			if (i + j == k)
			{
				if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (i = row - 1, k = 1; i > 1; i--, k++)//副对角线下部分
	{
		for (j = k; j < col - 2; j++)
		{
			if (board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
}
//判断输赢

game.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h>
#include<time.h>

#define ROW 5
#define COL 5

void game();
//游戏声明

void initialboard(char board[ROW][COL]);
//棋盘初始化声明

void printboard(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);
//电脑下棋声明

int judgefull(char board[ROW][COL], int row, int col);
//判断棋盘是否满了

int judgewin(char board[ROW][COL], int row, int col);
//判断输赢

在这里插入图片描述

当看到这一堆的代码时,想必大家脑袋瓜子嗡嗡的吧!
没关系,下面我带大家逐句理解。

二.分析代码部分

由于实现三子棋较为复杂,代码量相对比较多,所以我们分模块来写。三子棋总的有三个模块——三子棋.c、game.c、game.h

模块功能
三子棋.c主要实现三子棋游戏的逻辑和结构
game.c主要实现三子棋游戏的具体实现
game.h定义声明三子棋的所用到函数

[1]三子棋.c部分

既然在三子棋.c模块下我们要实现三子棋游戏的逻辑和结构,所以游戏执行的流程我们一定要清楚。

试想一下,我们在玩游戏的时候,最先看到的是一个游戏的界面,界面上有一个选项卡供我们选择,我们可选择开始游戏或是退出游戏。并且,一旦开始游戏,我们可以玩好几把,也可以选择退出游戏。

在这里插入图片描述

想到这,我们大概就知道这里要用到循环语句分支语句。那么下面让我们来实现一下:

void menu()//选项卡
{
	printf("************************\n");
	printf("*******  1.play  *******\n");
	printf("*******  0.exit  *******\n");
	printf("************************\n");
}

int main()
{
	int input = 0;
	do//玩很多把
	{
		menu();
		printf("请选择>: ");
		scanf("%d", &input);
		switch (input)
		{
		case 1://进入游戏
		{
				  game();
				  break;
		}
		case 0://退出游戏
		{
				  printf("退出成功\n");
				  break;
		}
		default:
		{
				   printf("选择错误,请重新选择!\n");
		}
		}
	} while (input);//若input=0,判断为假,终止循环,退出游戏
	return 0;
}

由上面代码,我们实现了三子棋游戏的基本结构
从代码中我们可以看到,正如我们所想的,用到了循环和分支语句。
循环这里用到的是do···while语句,因为我们至少要进行一次选择是否要开始游戏。
分支这里用到的是switch语句,因为这里有三种情况,用switch语句结构会更加清晰。

完成了三子棋.c的基本结构后,我们还要实现它的游戏逻辑
试想一下,在我们玩三子棋时,首先得要有棋盘吧,所以我们要创建一个棋盘,并且要有一个函数将棋盘打印出来让我们看到,这样我们才知道将棋下在哪儿。
还有,最初的棋盘不能有别的东西,也不能有棋子,所以我们还得初始一下棋盘。
接着,有了棋盘,我们开始下棋,下了棋后,我们要知道棋下在哪了,并且我们也要知道电脑下哪了,所以在双方落子后要将棋子的位置存起来,并将棋盘再次打印出来,让玩家看到。
再来,游戏总得有输赢,所以在双方落子后要判断有没有获胜,如果有一方获胜,则本轮游戏结束(注意不是退出游戏);否则游戏继续。还有一个特殊情况,就是棋盘下满了也没有决出胜负,所以还要判断棋盘是否满了,若满了,则双方平局,本轮游戏结束。

在这里插入图片描述

通过上述的分析,我们知道了我们要做什么了,所以我们用到一些函数来帮我们完成我们要完成的事情。


#define ROW 5
#define COL 5
//棋盘大小

void game();
//实现游戏

void initialboard(char board[ROW][COL]);
//实现棋盘初始化

void printboard(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);
//实现电脑下棋

int judgefull(char board[ROW][COL], int row, int col);
//判断棋盘是否满了

int judgewin(char board[ROW][COL], int row, int col);
//判断输赢

定义好这些个函数后,我们就可以干大事了

#include"game.h"//引头文件

void game()
{
	int tmp;
	char board[ROW][COL];
	initialboard(board);//棋盘初始化
	printboard(board, ROW, COL);//打印棋盘
	while (1)//下多次,直到决出胜负(或下满)
	{
		printf("玩家下棋:\n");
		playermove(board, ROW, COL);//玩家下
		printboard(board, ROW, COL);//打印下的结果
		tmp = judgefull(board, ROW, COL);//判断满没
		if (tmp == 0)
		{
			printf("棋盘已满\n");
			break;
		}
		tmp = judgewin(board, ROW, COL);//判断赢没
		if (tmp == 0)
		{
			printf("玩家胜!\n");
			break;
		}
		printf("电脑下棋:\n");
		computermove(board, ROW, COL);//电脑下
		printboard(board, ROW, COL);//打印下的结果
		tmp = judgefull(board, ROW, COL);//判断满没
		if (tmp == 0)
		{
			printf("棋盘已满\n");
			break;
		}
		tmp = judgewin(board, ROW, COL);//判断赢没
		if (tmp == 0)
		{
			printf("电脑胜!\n");
			break;
		}
	}
}

[2]game.c部分

game.c部分是整个项目最核心的部分,也是最难的部分,但只要掌握了二维数组行列下标的几个关系,也就迎刃而解了。
下面,我们来逐一分析:

(1)棋盘初始化——initialboard(board)

先亮代码

void initialboard(char board[ROW][COL])
{
	int i, j;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			board[i][j] = ' ';
		}
	}
}
//棋盘初始化

因为最开始棋盘什么也没有,但棋盘上要有下棋的空间,所以我们最开始给棋盘赋空格(‘ ’),并将棋盘的内容存到board[ROW][COL]数组中,这样我们之后就方便对棋盘进行操作了(也就是下棋)。

(2)棋盘打印——printboard(board, ROW, COL)

先亮代码

void printboard(char board[ROW][COL], int row, int col)
{
	int i, j;
	for (i = 0; i < row; i++)
	{
		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");
	}
}

首先,我们打印棋盘,要知道棋盘的样子。在这,我设计的棋盘是由竖杠减号构成的:

棋盘

可以看到,棋盘中的空格是用来落子的,棋子的两侧各有一个空格
我们还可知,要打印棋盘一定要用到循环,且为二重循环。
所以我们可以将“ %c ”(%c为下的内容),“|”,""看做小的循环单位,将每两行看做一个大的循环单位。

(3)玩家下棋——playermove(board, ROW, COL)

先亮代码

void playermove(char board[ROW][COL], int row, int col)
{
	int i, j;
	printf("请输入您要下的位置坐标>:");
	scanf("%d%d", &i, &j);
	if (i >= 1 && i <= row&&j >= 1 && j <= col)
	{
		if (board[i - 1][j - 1] == ' ')
		{
			board[i - 1][j - 1] = '*';
		}
		else
		{
			printf("此坐标对应位置已被下过,请重下!\n");
		}
	}
	else
	{
		printf("坐标非法,请重新输入!\n");
	}
}

玩家是通过输入棋盘坐标来实现下棋的,并且只能下在没有下过的地方,所以需要判断下的位置之前有没有落子(若是空格,则之前没有落子)。
这里还要注意棋盘坐标和数组下标的区别。

(4)电脑下棋——computermove(board, ROW, COL)

先亮代码

void computermove(char board[ROW][COL], int row, int col)
{
	int i, j;
	while (1)
	{
		i = rand() % row;//生成随机坐标
		j = rand() % col;
		if (board[i][j] == ' ')
		{
			board[i][j] = '!';
			break;
		}
	}
}

因为实现的是简易的三子棋,所以在这电脑下棋是随机的,所以这里用到了rand()来生成随机数,同样需要判断所下位置是否有被下过。

(5)判断棋盘是否满了——judgefull(board, ROW, COL)

先亮代码

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

判断棋盘是否满了很简单,就是遍历一遍数组,看看有没有空格。若没有,则棋盘满了,返回0;否则没满,返回1;

(6)判断输赢——judgewin(board, ROW, COL)(重头戏)

在这里插入图片描述

先亮代码

int judgewin(char board[ROW][COL], int row, int col)
{
	int i, j, k;
	for (i = 0; i < row; i++)//行
	{
		for (j = 0; j < col - 2; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 0; i < col; i++)//列
	{
		for (j = 0; j < row - 2; j++)
		{
			if (board[j][i] == board[j + 1][i] && board[j][i] == board[j + 2][i] && board[j][i] != ' ')
				return 0;
		}
	}
	for (i = 0; i < row - 2; i++)//主对角线
	{
		for (j = i; j < col - 2; j++)
		{
			if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 0; i < row - 2; i++)//副对角线
	{
		for (j = col - i; j > 1; j--)
		{
			if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
				return 0;
		}
	}
	for (i = 1; i < row - 2; i++)//主对角线下部分
	{
		for (j = 0, k = i; j < col - 2; j++)
		{
			if (i - j == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (j = 1; j < col - 2; j++)//主对角线上部分
	{
		for (i = 0, k = j; i < row - 2; i++)
		{
			if (j - i == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (i = 0; i < row - 2; i++)//副对角线上部分
	{
		for (j = col - 2, k = j; j > 1; j--)
		{
			if (i + j == k)
			{
				if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}
	for (i = row - 1, k = 1; i > 1; i--, k++)//副对角线下部分
	{
		for (j = k; j < col - 2; j++)
		{
			if (board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}
}

(判断输赢是最难的一个小模块,但只要理清楚行列(i,j)之间的关系,从而找到相应的位置,就简单很多了。)

要判断输赢,首先我们要了解游戏规则,即只要连续的方格内的棋子相同,并且不是空格,则获胜。连续的方格可以是横的,竖的,斜的都行。所以下面我们就考虑这三种情况是否满足条件。(以5*5的棋盘为例,并且棋盘为正方形

1.考虑每列(竖向)

在这里插入图片描述

需要注意,如果用 i 表示行, j 表示列,则在写循环的控制条件是要写
i<row-2;j<col (row表示棋盘有多少行,col表示棋盘有多少列) ,因为每一列的判断是连续判断三个数,若是惯性思维写i<row,j<col的话会有越界的问题,包括下面所有情况的越界问题都相同,只需注意 i , j 的取值范围即可,在下面的内容中不在赘述。( i , j 的初值为0,因为在这里,遍历从[0][0]开始)。

for (i = 0; i < col; i++)//列
	{
		for (j = 0; j < row - 2; j++)
		{
			if (board[j][i] == board[j + 1][i] && board[j][i] == board[j + 2][i] && board[j][i] != ' ')
				return 0;
		}

2.考虑每行
在这里插入图片描述

与考虑每列的情况同理,此情况也需要考虑越界问题。此处比较简单,读者自己写一写。

for (i = 0; i < row; i++)//行
	{
		for (j = 0; j < col - 2; j++)
		{
			if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}

3.考虑斜的情况(较为复杂,需耐心)
由于这种情况较为复杂,所以在这里进行了分类讨论:
【1】主对角线
【2】副对角线
【3】主对角线上侧
【4】主对角线下侧
【5】副对角线上侧
【6】副对角线下侧

【1】主对角线情况
在这里插入图片描述
由上图所示,如果在主对角线上若有连续三个棋子相同且不是空格则获胜。
通过观察,主对角线上的下标 i = j 恒成立,根据 i , j的关系可找到主对角线上的所有位置
(此处同样要考虑越界问题)

for (i = 0; i < row - 2; i++)//主对角线
	{
		for (j = i; j < col - 2; j++)
		{
			if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}

【2】副对角线情况
在这里插入图片描述
由上图所示,如果在副对角线上若有连线三个棋子相同且不是空格则获胜。
通过分析,我们发现 i + j 是一个定值,这个定值为row(或col)。根据这个条件即可找到副对角线上所有位置。与判断主对角线不同的是,此处是从
[0][4]开始遍历(准确来说是从[0][col]开始,只是在这里以5*5的棋盘为例)。(考虑越界问题)

for (i = 0; i < row - 2; i++)//副对角线
	{
		for (j = col - i; j > 1; j--)
		{
			if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
				return 0;
		}
	}

【3】主对角线上侧情况
如果获胜出现在主对角线上侧该如何来判断呢?
i , j 有什么关系呢?
因为此获胜情况三个的斜的方向要与主对角线一致,所以棋子就不可能出现在[0][3]、[0][4]、[1][4]这三个位置,因为在此情况下这三个位置不能形成三子棋,所以棋子能下的位置为下图红色框区域里所包含的位置:
在这里插入图片描述
所以下面我们要做的就是找到红色框中的位置,只有找到了这些位置,才能对位置上的棋子进行判断。通过对二维数组下标的观察,不难发现,如果遍历从[0][1]开始,蓝色杠上的位置 j - i = 1,绿色杠上的位置 j - i = 2。所以我们可以创建一个变量k,赋它初值为1时,就找到了蓝色杠上所对应的位置,因为 j 的初值也为1,并且循环一次要加1,所以让k = j,判断 j - i 是否等于 k 就能把红色框中的所有位置都找到。(注意越界问题)

for (j = 1; j < col - 2; j++)//主对角线上部分
	{
		for (i = 0, k = j; i < row - 2; i++)
		{
			if (j - i == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}

【4】主对角线下侧情况
此情况与【3】大致相同,要找到 i 和 j 的关系,再通过k找到所有符合条件的位置。只不过遍历的起点变了。(注意越界问题)
在这里插入图片描述

for (i = 1; i < row - 2; i++)//主对角线下部分
	{
		for (j = 0, k = i; j < col - 2; j++)
		{
			if (i - j == k)
			{
				if (board[i][j] == board[i + 1][j + 1] && board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}

【5】副对角线上侧
考虑了主对角线的上下侧,那副对角线上下侧 i , j 又有什么规律呢?

在这里插入图片描述
不难看出,如要满足与副对角线斜的方向一致,并且要形成三子棋,则棋子只能落在橘框中的空格中。同样的,我们要找到橘框里的位置,通过分析橘框中数组下标,若从[0][3]开始遍历,绿色杠上的位置 i + j = 3(或col - 2),蓝色杠上的位置 i + j = 2(或col - 3)(注意越界问题)。同样,i + j 的值与col 有关,而col与 j 有关,所以创建 k = j ,判断 j + i 是否等于 k 就能把橘色框中的所有位置都找到。(注意越界问题)

for (i = 0; i < row - 2; i++)//副对角线上部分
	{
		for (j = col - 2, k = j; j > 1; j--)
		{
			if (i + j == k)
			{
				if (board[i][j] == board[i + 1][j - 1] && board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ')
					return 0;
			}
		}
	}

【6】副对角线下侧
在这里插入图片描述
首先指出,我们从 [4][1]开始遍历。通过观察,不难发现每一行中,j 不断加1,并且随着行标的变小,j 的初值也再加1,所以我们可以创建变量 k,让 j = k ,并赋 k 初值为1,之后再通过循环改变 k 的值即可找到橘色框中的所有位置。(注意越界问题)

for (i = row - 1, k = 1; i > 1; i--, k++)//副对角线下部分
	{
		for (j = k; j < col - 2; j++)
		{
			if (board[i][j] == board[i - 1][j + 1] && board[i][j] == board[i - 2][j + 2] && board[i][j] != ' ')
				return 0;
		}
	}

[3]game.h部分

这一部分主要用来声明一下我们所用到的函数,并且棋盘的大小也在此处定义。

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h>
#include<time.h>

#define ROW 5
#define COL 5

void game();
//游戏声明

void initialboard(char board[ROW][COL]);
//棋盘初始化声明

void printboard(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);
//电脑下棋声明

int judgefull(char board[ROW][COL], int row, int col);
//判断棋盘是否满了

int judgewin(char board[ROW][COL], int row, int col);
//判断输赢

三.代码运行部分

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
笔者水平有限,若有错误或不足,还望指出,深表感谢!

  • 13
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲代码的小邢~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值