如何用c写井字棋矩阵游戏(Tic-Tac-Toe)

今天继续学c,记录一下如何用c写井字棋矩阵游戏。
在这里插入图片描述

题干

读入一个3x3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为O
程序判断这个矩阵中是否有获胜的一方,输出表示获胜一方的字符X或O,或输出无人胜出。

整体思考

我想的很简单,就是通过遍历矩阵,用检查行列与对角线的函数判断二维数组中元素是否已经连续出现三次,最后在主函数中判断X与O的胜负情况。

思考算法

如何判断一行或一列元素是否连续出现三次呢?
我觉得可以这样写

检查行

下面展示 检查行算法代码片段

//定义矩阵
int arr[3][3] = {
		{1, 1, 1},
		{1, 0, 0},
		{0, 0, 1}
	};
int i,j;
int numofO,numofX;//定义X与O的计数器
const int size=3;//定义一个矩阵大小常量
for(i=0;i<size;i++){
	numofO=numofX=0;
	for(j=0;j<size;j++){
		if(arr[j][i]==1){
			numofX++;
		}else if(arr[j][i]==0){
			numofO++;
		}
	}
	if(numofX==size){
		return 1;//表示一行有三个X
	}else if(numofO==size){
		return 0;//表示一行有三个O
	}else{
		return 2;//表示一行没有三个连续的元素
	}
}

检查列

检查列的算法就很简单了,跟检查行算法大同小异,只需将i与j互换

下面展示 检查列算法代码片段

//定义矩阵
int arr[3][3] = {
		{1, 1, 1},
		{1, 0, 0},
		{0, 0, 1}
	};
int i,j;
int numofO,numofX;//定义X与O的计数器
const int size=3;//定义一个矩阵大小常量
for(i=0;i<size;i++){
	numofO=numofX=0;
	for(j=0;j<size;j++){
		if(arr[j][i]==1){
			numofX++;
		}else if(arr[j][i]==0){
			numofO++;
		}
	}
	if(numofX==size){
		return 1;//表示一列有三个X
	}else if(numofO==size){
		return 0;//表示一列有三个O
	}else{
		return 2;//表示一列没有三个连续的元素
	}
}

同时检查行与列

但是这样显得代码很啰嗦,如何改进呢?
我觉得可以思考这样一个问题:“思考如何利用两重循环来同时检查行列”。
问题核心就是i与j的位置关系
如果我想在一次循环中同时检查两次,那么我自然会想多写一次if判断,所以就有了接下来的代码
下面展示 同时检查行列算法代码片段

//定义矩阵
int arr[3][3] = {
		{1, 1, 1},
		{1, 0, 0},
		{0, 0, 1}
	};
int i,j;
int numofO,numofX;//定义X与O的计数器
const int size=3;//定义一个矩阵大小常量
for(i=0;i<size;i++){
	numofO=numofX=0;
	for (j = 0; j < size; j++) {
		if (arr[i][j] == 1) {
			numofX++;
		} else if (arr[i][j] == 0) {
			numofO++;
		} else if (arr[j][i] == 1) {
			numofX++;
		} else if (arr[j][i] == 0) {
			numofO++;
		}
	}
	if(numofX==size){
		return 1;
	}else if(numofO==size){
		return 0;
	}else{
		return 2;
	}
}

这里我用到的是级联判断的形式来多次判断数组元素是否满足要求,我觉得是个很单纯的笨方法,更好更优的算法估计要在以后的学习中才能领悟了吧。

检查对角线

游戏还有一种规则是对角线上三个元素如果相等也可获胜,那么该如何用算法实现呢?
先思考一下对角线上的数组是什么情况吧:

a[0][0]-a[0][2]
-a[1][1]-
a[2][0]-a[2][2]

通过表格不难发现从a[0][0]开始的那条对角线数组下标完全一样
而从a[0][2]开始的对角线看似没有任何规律,实际上i是从0到2,而j是从2到0
那么我们可以这样来写算法:
下面展示 检查左对角线算法代码片段

//定义矩阵
int arr[3][3] = {
		{0, 2, 2},//2表示空
		{2, 0, 1},
		{1, 1, 0}
	};
int i,j;
int numofO,numofX;//定义X与O的计数器
const int size=3;//定义一个矩阵大小常量
numofO=numofX=0;
for(i=0;i<size;i++){
	if(arr[i][i]==1){
		numofX++;
	}else if(arr[i][i]==0){
		numofO++;
	}
}
	if(numofX==size){
		return 1;//表示对角线上有三个X
	}else if(numofO==size){
		return 0;//表示对角线上有三个O
	}else{
		return 2;//表示对角线上没有三个连续的元素
	}
}

下面展示 检查右对角线算法代码片段

//定义矩阵
int arr[3][3] = {
		{0, 2, 2},
		{2, 0, 1},
		{1, 1, 0}
	};
int i,j;
int numofO,numofX;//定义X与O的计数器
const int size=3;//定义一个矩阵大小常量
numofO=numofX=0;
for(i=0;i<size;i++){
	if(arr[i][size-1-i]==1){//从arr[0][2]开始至arr[2][0]
		numofX++;
	}else if(arr[i][i]==0){
		numofO++;
	}
}
	if(numofX==size){
		return 1;//表示对角线上有三个X
	}else if(numofO==size){
		return 0;//表示对角线上有三个O
	}else{
		return 2;//表示对角线上没有三个连续的元素
	}
}

同理检查左右对角线算法也可以进行合并,留给大家思考了。

源代码

最后附上源代码供参考:

#include <stdio.h>
int check_row_and_column(int arr[][3]);
int check_diagonal(int arr[][3]);

int main() {
	int arr[3][3] = {
		{0, 2, 2},
		{2, 0, 1},
		{1, 1, 0}
	};
//	printf("ret=%d", check_row_and_column(arr));
//	printf("ret=%d", check_diagonal(arr));
	int ret = check_row_and_column(arr);
	int ret1 = check_diagonal(arr);
	if (ret == 1) {
		printf("X");
	} else if (ret == 0) {
		printf("O");
	} else if (ret1 == 1) {
		printf("X");
	} else if (ret1 == 0) {
		printf("O");
	} else {
		printf("out");
	}


	return 0;
}

int check_row_and_column(int arr [][3]) {
	int i, j;
	int numofO, numofX; //定义X与O的计数器
	const int size = 3; //定义一个矩阵大小常量
	for (i = 0; i < size; i++) {
		numofO = numofX = 0;
		for (j = 0; j < size; j++) {
			if (arr[i][j] == 1) {
				numofX++;
			} else if (arr[i][j] == 0) {
				numofO++;
			} else if (arr[j][i] == 1) {
				numofX++;
			} else if (arr[j][i] == 0) {
				numofO++;
			}
		}
		if (numofX == size) {
			return 1;//表示一列有三个X
		} else if (numofO == size) {
			return 0;//表示一列有三个O
		} else {
			return 2;//表示一列没有三个连续的元素
		}
	}
}

int check_diagonal(int arr[][3]) {
	int i, j;
	int numofO, numofX; //定义X与O的计数器
	const int size = 3; //定义一个矩阵大小常量
	numofO = numofX = 0;
	for (i = 0; i < size; i++) {
		if (arr[i][i] == 1) {
			numofX++;
		} else if (arr[i][i] == 0) {
			numofO++;
		} else if (arr[i][size - 1 - i] == 1) {
			numofX++;
		} else if (arr[i][size - 1 - i] == 0) {
			numofO++;
		}
	}
	if (numofX == size) {
		return 1;//表示对角线上有三个X
	} else if (numofO == size) {
		return 0;//表示对角线上有三个O
	} else {
		return 2;//表示对角线上没有三个连续的元素
	}
}


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
tic-tac-toe是一种井字棋游戏,在一个3×3的棋盘上,两名玩家轮流在空白格中放置自己的棋子,先将3颗自己的棋子连成一条直线的一方获胜。 首先,我们需要定义一个tictactoe类。这个类应该具备以下功能:初始化游戏、显示棋盘、玩家行动和判断游戏是否结束。 我们可以在类的构造函数中初始化游戏。初始化时,我们可以使用一个二维字符数组来表示棋盘,将所有的格子都赋值为空白。另外,我们需要一个变量来表示当前玩家,初始值为玩家1。我们还可以定义一个变量来表示游戏是否结束,初始值为false。 接下来,我们可以编一个方法来显示棋盘。该方法会遍历棋盘数组,并打印每个格子的状态,例如打印空白格为"-",玩家1的棋子为"X",玩家2的棋子为"O"。 然后,我们需要编一个方法来实现玩家的行动。该方法需要接收玩家的坐标作为参数,在指定坐标上放置当前玩家的棋子。我们需要检查这个位置是否为空,如果为空则可以放置棋子并切换当前玩家。 接下来,我们需要编一个方法来判断游戏是否结束。我们需要检查是否有任意一方已经获胜,也就是是否有一行、一列或一条对角线上存在连成一条直线的三个相同棋子。如果有,那么游戏结束,我们将结束变量置为true。另外,如果棋盘已经满了,即所有格子都被填满,且没有任何一方获胜,那么游戏也结束。 最后,我们可以在主函数中创建一个tictactoe对象,并循环执行游戏,直到游戏结束。每次轮到一个玩家行动时,我们可以要求玩家输入一个坐标,并调用行动方法。然后显示棋盘。如果游戏结束,我们可以显示获胜方或平局的消息。 这样,我们就完成了一个简单的tic-tac-toe游戏的Java编程。通过这个例子,我们了解了如何使用类和方法来设计和实现一个游戏

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值