C语言实现“井字棋”游戏(三子棋)人机对弈

2023-05-16

井字棋游戏:即三子棋,英文名叫Tic-Tac-Tic,是一种在3*3格子上进行的连珠游戏,和五子棋比较类似,由于棋盘一般不画边线框,格线排成井字故得名。

题目分析 :

要完成该游戏的编写,我们需要先分析出完成整个游戏过程都需要干什么?

1.首先,需要定义出一个3*3的棋盘,根据相关知识,我们可以以二维数组的方式将棋盘表示出来;

2.棋盘定义出来后,需要将棋盘初始化,将3*3二维数组的每一个位置初始化为‘ ’(空格);

3.有了棋盘,我们就可以开始进行下棋了,首先要确定是玩家先下还是电脑先下。在这里我们规定玩家先下且玩家的下棋方式为‘x’,电脑下棋方式为‘o’;

4.每一次下完棋后需要进行检测,判断该下棋位置是否合法、判断是否胜利等等。

根据上述分析,可以大致定义出以下函数窗口:

void InitGame();//初始化游戏(棋盘)
void PrintChess();//输出棋盘
void PlayerMove();//玩家下棋
void ComputerMove();//电脑下棋
char CheckGameOver();//判断游戏是否结束(玩家胜/电脑胜/和棋)

初始化棋盘:将3*3的二维数组棋盘的每个位置初始化为‘ ’

void InitGame()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
			chess_board[i][j] = ' ';
	}
}

输出棋盘: 输出棋盘时,棋盘的风格可以根据自己的喜好来设计

void PrintfChess()//输出棋盘,棋盘的设计可以根据自己的喜好设计
{
	for (int i = 0; i < ROW; i++)
	{
		printf("| %c | %c | %c |\n", chess_board[i][0], chess_board[i][1], chess_board[i][2]);
		if (i < ROW - 1)
			printf("|---|---|---|\n");
	}
}

玩家下棋: 玩家输入下棋位置后,需要判断该位置是否合法、输入位置是否已被占用

void PlayerMove()//玩家下棋
{
	printf("玩家落子.\n");
	int row, col;
	while (1)
	{
		printf("请输入一组坐标(下棋位置):>");
		scanf("%d %d", &row, &col);
		//检查坐标的有效性
		if (row < 0 || row > ROW || col < 0 || col > COL)
		{
			printf("输入非法,请重新输入...");
			continue;
		}
		if (chess_board[row][col] != ' ')
		{
			printf("输入的位置已被占用,请重新输入...");
			continue;
		}
		chess_board[row][col] = 'x';//x代表玩家下的棋
		break;
	}
}

电脑下棋: 电脑下棋时,下棋的位置利用srand函数随机产生

void ComputerMove()//电脑下棋
{
	srand(time(0));
	while (1)
	{
		int row = rand() % ROW;
		int col = rand() % COL;
		if (chess_board[row][col] != ' ')
		{
			continue;
		}
		chess_board[row][col] = 'o';//o代表电脑下的棋
		break;
	}
}

检查棋盘 :在检测棋盘时,分别判断行、列、对角线,在这里我规定:

'x'代表玩家赢   'o'代表电脑赢   'h'代表和棋   'c'代表继续

char CheckGameOver()//检测游戏是否结束
{
	//检查行
	for (int i = 0; i < ROW; i++)
	{
		if (chess_board[i][0] != ' '
			&& chess_board[i][0] == chess_board[i][1]
			&& chess_board[i][0] == chess_board[i][2]
			)
			return chess_board[i][0];
	}
	//检查列
	for (int j = 0; j < COL; j++)
	{
		if (chess_board[0][j] != ' '
			&& chess_board[0][j] == chess_board[1][j]
			&& chess_board[0][j] == chess_board[2][j]
			)
			return chess_board[0][j];
	}
	//检查对角线
	if (chess_board[0][0] != ' '
		&& chess_board[0][0] == chess_board[1][1]
		&& chess_board[0][0] == chess_board[2][2]
		)
		return chess_board[0][0];
	if (chess_board[0][2] != ' '
		&& chess_board[0][2] == chess_board[1][1]
		&& chess_board[0][2] == chess_board[2][0]
		)
		return chess_board[0][2];
	//判断是否和棋
	if (ChessFull())
		return 'h';
	return 'c';
}

至此,主要的功能函数均已编写完毕,整个程序的流程如下所示:

1.初始化棋盘;

2.输出棋盘;

3.玩家下棋;

4.检测棋盘;

5.电脑下棋;

6.检测棋盘

代码如下: 

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>

#define START 1
#define QUIT  0
#define ROW   3
#define COL   3

static char chess_board[ROW][COL];//定义棋盘

void StartGame();
void InitGame();
void PrintfChess();
void PlayerMove();
void ComputerMove();
char CheckGameOver();
bool ChessFull();

int main(int argc, char* argv[])
{
	int select = 1;
	while (select)
	{
		printf("*********************\n");
		printf("* [1] Start Game    *\n");
		printf("* [2] Over  Game    *\n");
		printf("*********************\n");
		printf("请选择:>");
		scanf_s("%d", &select);

		if (select == QUIT)
			break;
		if (select != START)
		{
			printf("输入有错,请重新输入.....\n");
			continue;
		}
		StartGame();
	}
	printf("GoodBye.....");
	return 0;
}

void StartGame()
{
	char winner;
	//1 初始化游戏(棋盘)
	InitGame();
	//2 进入游戏
	while (1)
	{
		//3 输出棋盘
		PrintfChess();
		//4玩家下棋
		PlayerMove();
		//5检查结果
		winner = CheckGameOver();
		if (winner != 'c')
			break;
		
		//6电脑下棋
		ComputerMove();
		//7检查结果
		CheckGameOver();
		winner = CheckGameOver();
		if (winner != 'c')
			break;
	}
	if (winner == 'x')
		printf("玩家赢.\n");
	if (winner == 'o')
		printf("电脑赢.\n");
	if (winner == 'h')
		printf("和棋.\n");
}

void InitGame()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
			chess_board[i][j] = ' ';
	}
}

void PrintfChess()//输出棋盘,棋盘的设计可以根据自己的喜好设计
{
	for (int i = 0; i < ROW; i++)
	{
		printf("| %c | %c | %c |\n", chess_board[i][0], chess_board[i][1], chess_board[i][2]);
		if (i < ROW - 1)
			printf("|---|---|---|\n");
	}
}

void PlayerMove()//玩家下棋
{
	printf("玩家落子.\n");
	int row, col;
	while (1)
	{
		printf("请输入一组坐标(下棋位置):>");
		scanf("%d %d", &row, &col);
		//检查坐标的有效性
		if (row < 0 || row > ROW || col < 0 || col > COL)
		{
			printf("输入非法,请重新输入...");
			continue;
		}
		if (chess_board[row][col] != ' ')
		{
			printf("输入的位置已被占用,请重新输入...");
			continue;
		}
		chess_board[row][col] = 'x';//x代表玩家下的棋
		break;
	}
}

void ComputerMove()//电脑下棋
{
	srand(time(0));
	while (1)
	{
		int row = rand() % ROW;
		int col = rand() % COL;
		if (chess_board[row][col] != ' ')
		{
			continue;
		}
		chess_board[row][col] = 'o';//o代表电脑下的棋
		break;
	}
}
/*
* 'x'代表玩家赢
* 'o'代表电脑赢
* 'h'代表和棋
* 'c'代表继续
*/
char CheckGameOver()//检测游戏是否结束
{
	//检查行
	for (int i = 0; i < ROW; i++)
	{
		if (chess_board[i][0] != ' '
			&& chess_board[i][0] == chess_board[i][1]
			&& chess_board[i][0] == chess_board[i][2]
			)
			return chess_board[i][0];
	}
	//检查列
	for (int j = 0; j < COL; j++)
	{
		if (chess_board[0][j] != ' '
			&& chess_board[0][j] == chess_board[1][j]
			&& chess_board[0][j] == chess_board[2][j]
			)
			return chess_board[0][j];
	}
	//检查对角线
	if (chess_board[0][0] != ' '
		&& chess_board[0][0] == chess_board[1][1]
		&& chess_board[0][0] == chess_board[2][2]
		)
		return chess_board[0][0];
	if (chess_board[0][2] != ' '
		&& chess_board[0][2] == chess_board[1][1]
		&& chess_board[0][2] == chess_board[2][0]
		)
		return chess_board[0][2];
	//判断是否和棋
	if (ChessFull())
		return 'h';
	return 'c';
}
bool ChessFull()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			if (chess_board[i][j] == ' ')
				return false;
		}
	}
	return true;
}

运行测试图: 

 

 程序的运行界面我们还可以利用system("cls")对界面进行优化,这样可以使界面更加美观。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言实现“井字棋”游戏(三子棋)人机对弈 的相关文章

  • C语言实现strcmp()函数

    span class token macro property span class token directive keyword define span CRT SECURE NO WARNINGS span span class to
  • 辗转相除法详解(C语言实现)

    辗转相除法 定义基本原理原理证明 算法实现思想C语言实现 定义 辗转相除法 xff0c 被称为欧几里得 xff08 Euclidean xff09 算法 xff0c 是求最大公约数的算法 基本原理 原理 两个正整数a和b a gt b xf
  • 使用汇编语言与C语言实现LED1/LED2/LED3三盏灯点亮

    汇编语言代码段 text global start start LED13 INIT LED1 3点灯 RCC章节 64 1 设置GPIO始终使能 通过RCC AHB4ENSRTR寄存器设置0x50000A28 4 61 1 ldr r0
  • 用c语言实现 将src指向的字符串追加到dest指向字符串的后面

    实现char my strcat char dest char src 函数 返回 xff1a dest字符串的地址 功能 xff1a 将src指向的字符串追加到dest指向字符串的后面 例如 xff1a char dest 10 61 3
  • C语言实现 Josegh()函数

    问题 设有n个人围坐一圈并按顺时针方向从1到n编号 xff0c 从第s个人开始进行1到m的报数 xff0c 报数到第m个人 xff0c 此人出圈 xff0c 再从他的下一个人重新开始1到m的报数 xff0c 如此下去直到所有的人都出圈为止
  • 使用汇编语言与C语言实现LED1/LED2/LED3三盏灯点亮

    汇编语言代码段 text global start start LED1点灯LED1 gt PE10 64 1 对LED1进行初始化 RCC AHB4 ENSETR MODER OTYPER OSPEEDR PUPDR 64 2 实现LED
  • 一篇文章带你搞懂扫雷小游戏(c语言实现)

    目录 前言 1 游戏设计逻辑 2 游戏思考及实现过程 2 1符号与棋盘的建立 2 2棋盘的初始化与打印 2 3布置雷 2 4 排查雷并设置结束标志 3 代码展示 test c game c game h 前言 扫雷是一款经典的小游戏 xff
  • 无名的ADRC的C语言实现

    分为ADRC h和ADRC c 确实看头文件有用 xff0c 有哪些变量都一目了然 和ACfly一样的是比如都有beta这个参数 ADRC c 本程序只供购买者学习使用 xff0c 版权著作权属于无名科创团队 xff0c 无名科创团队将飞控
  • 记录:在ubuntu中以C语言实现json文件读取遇到的问题(1)(说不定会有2)

    4 12 记录在ubuntu中以C语言实现json文件读取遇到的问题 xff08 1 xff09 xff08 说不定会有2 xff09 暂记录遇到的问题及解决 xff0c 其中还有些原因没有搞明白 xff09 1 首先过程参考自一位大佬的博
  • PID连续控制算法的表达式以及C语言实现

    1 数字 xff08 离散 xff09 PID控制算法的表达式 xff1a 将PID调节器离散化 xff0c 用差分方程来代替连续系统的微分方程 xff0c 分为位置式和增量式两类 重点理解概念如下 xff1a a xff09 基本偏差e
  • ubuntu下串口发送或者接收(c语言实现)minicom调试

    关于串口的知识这里就不累赘了 xff0c 看着多又烦 xff0c 搞这个的都懂串口 xff0c 不多废话了 xff01 xff01 进入正题 xff01 xff01 1 选择合适的usb串口模块 某宝很多这种模块 xff0c 有各种型号的
  • C语言实现http请求器

    C语言实现http请求器 项目介绍 本项目完成一个http客户端请求器 xff0c 该请求器往服务器发送请求 xff0c 并接受服务器发来的响应数据 程序执行流程 建立TCP连接在TCP连接获得的socket的基础上 xff0c 发送htt
  • C语言实现UDP通信

    UDP通信 UDP是一种无连接的尽最大努力交付的不可靠连接 xff0c 通信之前无需先建立连接 xff0c 自然而然 xff0c 通信之后也就无需再释放连接 通信的套接字 UDP所采用的通信接口与前面讲过的TCP通信接口相同 xff0c 只
  • PID控制算法的C语言实现

    PID控制算法的C语言实现一 PID算法原理 最近两天在考虑一般控制算法的C语言实现问题 xff0c 发现网络上尚没有一套完整的比较体系的讲解 于是总结了几天 xff0c 整理一套思路分享给大家 在工业应用中PID及其衍生算法是应用最广泛的
  • windows下C语言实现TCP通信

    编译器 xff1a vs2017 语言 xff1a c语言 具体的原理可以在其他博客看到 在我学习winsock编程时 xff0c 发现那些博客代码居然在我机器上没一个能运行 xff0c 可能是我水平有限 于是我根据winsock相关知识
  • C语言实现1/1-1/2+1/3-...-1/100求和

    观察题目要求可以看出 xff0c 底数为奇数是前面符号为正 xff0c 偶数是则为负 那么我们可以考虑使用一下方式完成求解 解法一 xff1a span class token macro property span class token
  • c 语言udp方式连接代码,C语言实现UDP连接的参考代码

    C语言实现UDP连接的参考代码 xff0c Client连接上Server后将自己所在目录下的 34 liu 34 文件中的前三行文字发送到Server端去 xff0c 然后Server负责接收和显示 server c include in
  • c语言实现strcat函数

    char strcat char strDestination const char strSource 一 函数介绍 作用 xff1a 连接字符串的函数 xff0c 函数返回指针 xff0c 两个参数都是指针 xff0c 第一个参数所指向
  • UDP通信 (C语言实现)

    直接看代码吧 v乛 乛 udp server c 文件信息 文 件 名 udp server c 创 建 人 文件创建日期 年 月 日 描 述 UDP 回射服务器程序
  • 二叉树递归遍历(C语言实现)

    span class token macro property span class token directive hash span span class token directive keyword include span spa

随机推荐

  • Qt项目实战:愤怒的小鸟(联机版)

    前言 本文章会详细介绍难点的内容 xff0c 不附带全部源码 xff0c 会将关键代码进行展示 因为只有截图 xff0c 这里在每一个动作和界面都添加了音效与BGM 同时附加了CG展示 素材和音效全部放在下面了 xff0c 需要可自行提取
  • Ubuntu中安装openCV时Cmake问题解决

    1 执行Cmake的语句指令 sudo cmake D CMAKE BUILD TYPE 61 Release D CMAKE INSTALL PREFIX 61 usr local 2 当执行完上述指令后遇见以下问题解决策略 问题1 xf
  • 使用 RGB-D 相机(Astra)实现 YOLO v3 实时目标检测

    设备和环境 xff1a 奥比中光RGB D相机 xff08 Astra xff09 xff1b Ubuntu16 04 首先 xff0c 先将自己的RGB D相机的环境与依赖构建好 xff0c 然后进行以下步骤构建darknet ros 1
  • Arduion应用U8g2库实现字符滚动效果

    由于U8g2库中没有可以位移的函数 xff0c 所以简单编写了一个可以实现字符滚动的代码 主要是为了记录一下自己学习Arduion的过程 算是一个记事本吧 xff01 当然如果你对于这方面有所需求 xff0c 可以拿去使用 主要是利用显示器
  • C语言老鼠走迷宫(单路径)算法详细讲解

    最近在学习C语言的一些经典算法 xff0c 其中遇到了一点困难 xff0c 导致卡进度了 琢磨了很久 xff0c 在绘制流程图时 xff0c 突然灵感大开理解了 xff0c 老鼠走迷宫算法的奇妙 所以写了这个 xff0c 一来是方便以后右和
  • 关于二分搜索法条件判断的研究

    最近在写二分搜索法时 xff0c 发现了几个现象 xff0c 在不同的条件设定之下 xff0c 系统会出现几种bug xff1a 1 当搜索的值 lt 最小值 时系统都会一直在循环内执行 2 当搜索的值 gt 最大值 时系统都会一直在循环内
  • C++ 库函数<string>示例

    最近在学C 43 43 自己整理了一部分C 43 43 库函数 lt string gt 的一些 函数 主要都是C 43 43 的 想到以后可能会用到 所以打算记录一下 方便自己也方便了大家 在啃这些函数的时候有很多借鉴之处 xff0c 在
  • 两台电脑间的串口通信

    目录 一 准备工作 二 实验过程 三 实验结果 一 准备工作 1 两台笔记本电脑 2 2个usb转串口模块 3 杜邦线若干 4 秒表 二 实验过程 两个串口线分别连接两台电脑 连线方式 xff1a 3V3 3V3 xff0c GND GND
  • c++ primer plus学习笔记(1)——基础知识

    本人还有一星期要开始期末考试了 xff0c 复习c 43 43 时顺便挖个坑 xff0c 之后会详细更新 目录 1 初识源代码 1 1 c 43 43 程序的产生 1 2 代码例 1 3 标记 空白 2 简单数据类型 2 1 变量名 2 2
  • C语言:sizeof和strlen计算字符串大小

    大家清楚 sizeof 和 strlen 的区别吗 xff1f sizeof是运算符 xff0c 确定的是字符所占空间大小 xff0c 参数可以有数组 指针 类型 对象 函数等 strlen是C语言的标准库函数 xff0c 确定是字符串的大
  • Python--爬虫--requests进阶,cookie/session模拟登录

    目录 一 原理 二 实际操作 三 结果 四 问题与总结 一 原理 以下内容为使用requests库发送请求 xff0c 使用cookie session模拟登录 xff08 并且登录时只需输入账号与密码 xff09 我们在使用搜索引擎访问网
  • linux系统移植U-boot与kernel的搭载流程(交互模式下)

    Linux系统移植四大部分 xff1a 搭建交叉开发环境 bootloader的选择和移植 本文选用bootloader下的U boot uImage的配置 编译与移植 根文件系统的制作 全部已完成 xff0c 本文只讲解 如何搭载这些东西
  • FreeRTOS任务创建、删除| FreeRTOS三

    目录 一 FreeRTOS任务创建与删除有关函数 1 1 创建 删除任务的API函数 1 1 1 动态创建任务 1 1 2 静态创建任务 1 1 3 删除任务 二 FreeRTOS任务创建与删除 xff08 动态方法 xff09 2 1 实
  • (学习)基于STM32的串口通信打印数据(HAL库+CubeMX)

    当我们在进行开发的时候 xff0c 通常需要将一些参数进行调整来达到效果 xff0c 这个时候就需要将单片机上的信息通过串口通信传送到PC机上来直观显示 一 基本的专有名词和原理介绍 USART xff1a 只能异步通信 USART xff
  • ROS通信——C++实现

    一 普通话题通信 创建功能包 xff1a catkin create pkg package roscpp rospy std msgs 创建发布者 xff1a include 34 ros ros h 34 include 34 std
  • ROS使用Python编写的步骤

    第一步 xff1a 和C 43 43 编写一样 xff0c 配置好工作空间 第二步 xff1a 在功能包下面建立一个scripts文件夹 第三步 xff1a 在scripts文件里面建立一个 py文件 第四步 编写python文件 注意 x
  • window的QT作为TCP客户端,ubuntu的python作为TCP服务端

    客户端 pro文件加入 QT 43 61 network mainwindow h ifndef MAINWINDOW H define MAINWINDOW H include lt QMainWindow gt include lt Q
  • RoboCom机器人大赛使用yolov5抽取20个随机图片进行人群识别

    目录 1 原理 2 思维流程 2 1 进行yolov5的环境搭建 2 1 1 在Linux的ubuntu环境anaconda的安装 2 1 2 Vscode的安装和配置 2 1 3 Github上面yolov5文件的下载 2 1 4 使用A
  • C语言实现字符串逆序、倒置字符串(字符串逆序问题的升级)

    一 字符串逆序 问题描述 xff1a 输入一个字符串str xff0c 将其内容颠倒过来 xff0c 并输出 数据范围0 lt len str lt 10000 输入描述 xff1a 输入一个字符串 xff0c 可以有空格 输出描述 xff
  • C语言实现“井字棋”游戏(三子棋)人机对弈

    井字棋游戏 xff1a 即三子棋 xff0c 英文名叫Tic Tac Tic xff0c 是一种在3 3格子上进行的连珠游戏 xff0c 和五子棋比较类似 xff0c 由于棋盘一般不画边线框 xff0c 格线排成井字故得名 题目分析 xff