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

本文详细介绍了如何使用C语言编写井字棋(Tic-Tac-Toe)游戏的胜利判断算法,包括检查行、列、对角线的方法。作者通过两重循环实现了同时检查行列,并分别给出了检查左对角线和右对角线的代码。最后,给出了完整的源代码以供参考。
摘要由CSDN通过智能技术生成

今天继续学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个

红包金额最低5元

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

抵扣说明:

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

余额充值