C语言数组实现三子棋

文章介绍了如何使用C语言实现一个简单的三子棋游戏,包括创建二维数组表示棋盘,初始化棋盘,玩家和电脑轮流下棋的逻辑,以及判断输赢和平局的函数。代码分为游戏菜单设置、游戏过程实现、棋盘操作和游戏状态判断等部分,电脑的走棋是随机的,游戏结束条件是玩家、电脑获胜或平局。
摘要由CSDN通过智能技术生成

目录

三子棋的介绍

三子棋代码实现

设置游戏菜单

游戏过程

创建二维数组

初始化棋盘

打印棋盘

玩家下棋

电脑下棋

判断输赢

游戏整个过程实现

全部代码

总结


三子棋的介绍

三子棋,想必大家都一定玩过,就是一个3*3的表格,两个玩家交替落子,谁先使棋盘中的某一行,或者某一列,又或者某一对角线全部落成字节的子,则谁就获胜。如果棋盘下满了还没有获胜,就表示平局。上面便是三子棋的整个游戏过程,那么我们究竟如何把三子棋用代码实现呢?这便是我们这一期要探讨的内容。

三子棋代码实现

设置游戏菜单


//设置游戏菜单
void menu() 
{
	printf("*************************\n");
	printf("********  1.play  *******\n");
	printf("********  0.exit  *******\n");
}

游戏过程

创建二维数组

char board[ROW][COL];

整个棋盘可以看做是一个3行3列的二维数组,这里用了宏定义,因为如果创建二维直接给定行数和列数为3的话,后续维护代码时所有3的地方都应该修改,较为繁琐,这也是我们后续编码时的一个小技巧。

初始化棋盘

//初始化棋盘
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] = ' ';
		}
	}
}

刚开始棋盘上没有落子,可以理解为二维数组的每个元素的值都为空,所以我们可以遍历整个二维数组,让每个元素的值为空。

打印棋盘

//打印棋盘
void DisplayBoard(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++) {
			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) {
	printf("玩家走\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入坐标>\n");
		scanf("%d%d", &x, &y);//传给的x,y值是要放入的坐标,如果是2,1;那么对应数组元素的下标就是1,0;
		if (x >= 0 && x <= row && y >= 0 && y <= col) 
		{
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			else 
			{
				printf("坐标被占用,请重新输入\n");
			}
		}
		else {
		
			printf("坐标违法,超出范围\n");
		}
		
		
	}
}

玩家输入一个坐标,但是坐标一般是从1开始的,而数组的元素的下标是从0开始的,所以得给坐标减去1(x-1,y-1);在落子之前得判断要落子的位置的元素是否为空,只有为空,才可以落子

电脑下棋

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
	int x = 0;
	int y = 0;
	printf("电脑走\n");
	while (1) {
		x = rand() % row; //随机数函数,模行数之后的范围就是0—row-1.刚好是行标的范围
		y = rand() % col;
		if (board[x][y] == ' ') {
			board[x][y] = '#';
			break;
		}
	}
}

电脑落子是随机的,所以我们用到了库中的rand()函数,返回的整型模row后,范围为(0—row-1),而数组的行标的范围就是(0—row-1),所以可以直接(x,y)表示数组元素的下标。

判断输赢

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 (IsFull(board, ROW, COL)) {
		return 'Q';
	}
	//游戏继续
	else {
		
		return 'C';
		
	}

}
	

有四种返回值,

//返回 '*', 玩家胜
//返回 '#',电脑胜
//返回 'C',游戏继续
//返回 'Q',平局
//分析:以上四种状态,只有返回'C'这种状态,游戏继续进行,其它三种状态都是游戏结束

游戏整个过程实现

//游戏过程
void game()
{
		//三子棋的过程,本质上就是一个二维数组
		char board[ROW][COL];
		//初始化棋盘,每个元素全部初始化为空格
		InitBoard(board, ROW, COL);
		//打印棋盘
		DisplayBoard(board,ROW,COL);
		//开始下棋,创建一个变量ret,用来表示游戏的状态
		char ret = 0;
		//游戏进行的整个过程
		while (1)
		{
			//玩家下棋
			PlayerMove(board,ROW,COL);
			//打印棋盘
			DisplayBoard(board, ROW, COL);
			//判断游戏状态
			ret = IsWin(board,ROW,COL);
			if (ret != 'C') {		//游戏既然能够进行,证明ret的值肯定是'c',若果不是'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 {
			printf("平局\n");
		}
}

 注意:不管玩家还是电脑,每落完一次子,就得打印一次棋盘,因为只有打印了棋盘,玩家才能知道往哪里落子。而且,每落子一次就得判断游戏的状态,游戏的状态就是IsWin函数的四种返回值。

全部代码

总共分为了三个文件:

game.h(相关函数的声明)

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.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 ComputerMove(char board[ROW][COL], int row, int col);
//判断游戏状态
//要返回四种不同的状态
//返回'*', 玩家胜
//返回'#',电脑胜
//返回'C',游戏继续
//返回'Q',平局
//分析:以上四种状态,只有返回'C'这种状态,游戏继续进行,其它三种状态都是游戏结束
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] = ' ';
		}
	}
}
//打印棋盘
void DisplayBoard(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++) {
			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) {
	printf("玩家走\n");
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入坐标>\n");
		scanf("%d%d", &x, &y);//传给的x,y值是要放入的坐标,如果是2,1;那么对应数组元素的下标就是1,0;
		if (x >= 0 && x <= row && y >= 0 && 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; //随机数函数,模行数之后的范围就是0—row-1.刚好是行标的范围
		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 (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][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 (IsFull(board, ROW, COL)) {
		return 'Q';
	}
	//游戏继续
	else {
		
		return 'C';
		
	}

}
	
	
	
	

test.c(测试文件,实现整个游戏的功能)

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//设置游戏菜单
void menu() 
{
	printf("*************************\n");
	printf("********  1.play  *******\n");
	printf("********  0.exit  *******\n");
}
//游戏过程
void game()
{
		//三子棋的过程,本质上就是一个二维数组
		char board[ROW][COL];
		//初始化棋盘,每个元素全部初始化为空格
		InitBoard(board, ROW, COL);
		//打印棋盘
		DisplayBoard(board,ROW,COL);
		//开始下棋,创建一个变量ret,用来表示游戏的状态
		char ret = 0;
		//游戏进行的整个过程
		while (1)
		{
			//玩家下棋
			PlayerMove(board,ROW,COL);
			//打印棋盘
			DisplayBoard(board, ROW, COL);
			//判断游戏状态
			ret = IsWin(board,ROW,COL);
			if (ret != 'C') {		//游戏既然能够进行,证明ret的值肯定是'c',若果不是'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 {
			printf("平局\n");
		}
}
int main() 
{
	int input = 0;
	srand((unsigned int )time(NULL));
	do 
	{
		menu();
		printf("请选择> \n");
		scanf("%d",&input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误\n");
			break;
		}
	} while (input);
	return 0;
}

	













以上便是三子棋的所有代码, 需要的小伙伴自行提取。

总结

总的来说,以上的代码基本上实现了三子棋的基本功能,但是需要注意的是,以上的电脑玩家是很笨的,因为是随机的函数,也就是说,电脑玩家下的每一步都是随机的,与此前游戏进行的每一步都是没有关联的,这就导致了,你可能想让电脑玩家赢,电脑玩家都不会去赢,这只是一个基本的三子棋案例,电脑玩家的聪明程度可完全取决于各位。

本期内容到此结束^_^

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

棠~

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

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

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

打赏作者

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

抵扣说明:

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

余额充值