《如何使用C语言去下三子棋?》

news2024/10/6 12:19:19

目录

一、环境配置

二、功能模块

        1.打印菜单

2.初始化并打印棋盘

3、行棋 

        3.1玩家行棋

        3.2电脑行棋

4、判断是否和棋 

5.判赢

三、代码实现

        1、test.c文件

        2、game.c文件

        3、game.h文件


一、环境配置

        本游戏用到三个文件,分别是两个源文件test.c  game.c 和一个头文件game.h。

        主函数main()在test.c文件中,游戏实现所需要的函数在test.c中被引用,而函数的实现主要是在game.c文件中完成。game.h文件中包含了程序所需的所有头文件并且包括对实现游戏功能的所有函数的声明。

        之所以使用3个文件是因为,三子棋的实现需要多个模块的相互串联,多个文件各司其职,这样可以更好的处理各个模块间的逻辑,这样也增加了代码的可读性,而且还利于调试。

二、功能模块

1.打印菜单

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

  运行结果: 

 玩家选择(1/0)决定是否进入游戏。

 2.初始化并打印棋盘

InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
			
		}
		
	}
}
/* 通过创建一个char类型的二维数组对其进行初始化 */
char board[ ][ ] = { 0 };       
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j;
	for (i = 0; i < row; i++)
	{
		j = 0; 
		for ( j; j < col; j++) //打印   |   |   
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		
		printf("\n");
		j = 0;
		for ( j; j < col; j++)//打印---|---|---
		{
			if (i < row - 1)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

 运行结果:

 其中,上述棋盘的大小可以根据用户需求自行调整。

 棋盘大小调整方式:在game.h文件中,对宏的定义进行更改即可完成棋盘大小的修改。

#define ROW 3
#define COL 3

3、行棋 

3.1玩家行棋

void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家走:>\n");
	while (1)
	{
		printf("请输入下棋的坐标:>");
		scanf("%d %d", &x, &y);
		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//下棋
			//首先判断坐标是否被占用
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';//玩家使用*下棋
				
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入!");
		}
		
	}
}

3.2电脑行棋

void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑走:>");
	while (1)
	{
		//生成随机坐标
		int x = rand() % row;
		int y = rand() % col;
		
		//下棋
		//判断坐标是否被占用
		if (board[x][y] == ' ')
		{
			printf("%d %d\n", x + 1, y + 1);//输出电脑下棋的坐标
			board[x][y] = '#';//电脑使用#下棋

			break;
		}
			
	}
}

         电脑和玩家每走一步棋,都会打印出新的棋盘,以便于玩家观察空子的位置。

4、判断是否和棋 

int IfFull(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;//棋盘满了
}

        在game.c文件中通过IfFull函数实现对棋盘上空位的判断,防止一个位置多次下棋。

        如果棋盘所有格子都下完之前,还没有分出胜负 ,则代表和棋,以上代码为判断棋盘上面是否有空格子。

5.判赢

char IfWin(char board[ROW][COL], int row, int col)
{
	//判断行
	for (int i = 0; i < row; i++)
	{
		for (int j = 2; j < col; j++)
		{
			if (board[i][j - 2] == board[i][j - 1] && board[i][j - 1] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断列
	for (int j = 0; j < col; j++)
	{
		for (int i = 2; i < row; i++)
		{
			if (board[i - 2][j] == board[i - 1][j] && board[i - 1][j] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断右交叉
	for (int i = 2; i < row; i++)
	{
		for (int j = 2; j < col; j++)
		{
			if (board[i - 2][j - 2] == board[i - 1][j - 1] && board[i - 1][j - 1] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断左交叉
	for (int i = 1; i < row - 1; i++)
	{
		for (int j = 1; j < col - 1; j++)
		{
			if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断平局
	int full = IfFull(board, row, col);
	if (full == 1)
	{
		return 'Q';
		
	}
	//游戏继续
	return 'C';
}

        每下一步棋,都会对棋盘的每行、每列、左交叉、右交叉做出判断,看是否有三个一样的旗子相连,如果有代表下棋者获胜,否则继续下棋,直至下满棋盘。

        return board[ i ][ j ] ;的奥妙之处就在于,无论是玩家获胜还是电脑获胜都会返回与其相同的棋子,不需要再重新进行判断取胜的棋子是哪一方,如果返回'*',证明玩家获胜,game()函数得到'*',判定玩家获胜,输出:“玩家获胜!”;如果返回'#',证明电脑获胜,game()函数得到'#',判定电脑获胜,输出:“电脑获胜!”

        如果通过IfFull()函数判断棋盘已经下满,就会给test.c文件中的game()函数中返回'Q’,game()函数得到'Q'便知道二者微分胜负,输出:和局。

        否则,return ’C',game()函数得到‘C’,游戏继续。

三、代码实现

1、test.c文件

#include"game.h"
char ret = 0;//ret用来存放比赛结果
void menu()
{
	
	printf("********************************\n");
	printf("*****        1.play        *****\n");
	printf("*****        0.exit        *****\n");
	printf("********************************\n");
}

void game()
{
	//存储数据 - 二维数组
	char board[ROW][COL];
	//初始化棋盘 - 初始化空格
	InitBoard(board,ROW,COL);
	//打印棋盘 - 本质是打印数组的内容
	DisplayBoard(board, ROW, COL);
	//玩家 电脑 走旗
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL); //打印玩家的每一步走棋
		//判断玩家是否赢得游戏
		ret = IfWin(board, ROW, COL);//玩家赢了*  电脑赢了#  平局Q  游戏继续C
		if (ret != 'C')
			break;
			
		//电脑下棋
		ComputerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL); //打印电脑的每一步走棋
		//判断电脑是否赢得游戏
		ret = IfWin(board, ROW, COL);
		if (ret != 'C')
			break;
		
	}

	if (ret == '*')
	{
		printf("%c玩家获胜!\n", ret);

	}
	else if (ret == '#')
	{
		printf("%c电脑获胜!\n", ret);

	}
	else 
	{
		printf("%c     平局!\n", ret);
	}
	
	DisplayBoard(board, ROW, COL);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));//配合rand()函数生成随机值,因为只需要调用一次所以放到main()函数中
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("三子棋游戏\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}

	} while (input);
	return 0;
}

2、game.c文件

#include"game.h"

//初始化棋盘的函数
InitBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = ' ';
			
		}
		
	}
}

//打印棋盘的函数
void DisplayBoard(char board[ROW][COL], int row, int col)
{
	int i = 0;
	int j;
	for (i = 0; i < row; i++)
	{
		j = 0; 
		for ( j; j < col; j++) //打印   |   |   
		{
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		
		printf("\n");
		j = 0;
		for ( j; j < col; j++)//打印---|---|---
		{
			if (i < row - 1)
			{
				printf("---");
				if (j < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}

//玩家下棋的函数
void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	printf("玩家走:>\n");
	while (1)
	{
		printf("请输入下棋的坐标:>");
		scanf("%d %d", &x, &y);
		//判断坐标的合法性
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//下棋
			//首先判断坐标是否被占用
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';//玩家使用*下棋
				
				break;
			}
			else
			{
				printf("坐标被占用,请重新输入\n");
			}
		}
		else
		{
			printf("坐标非法,请重新输入!");
		}
		
	}
}

//电脑下棋的函数
void ComputerMove(char board[ROW][COL], int row, int col)
{
	printf("电脑走:>");
	while (1)
	{
		//生成随机坐标
		int x = rand() % row;
		int y = rand() % col;
		
		//下棋
		//判断坐标是否被占用
		if (board[x][y] == ' ')
		{
			printf("%d %d\n", x + 1, y + 1);//输出电脑下棋的坐标
			board[x][y] = '#';//电脑使用#下棋

			break;
		}
			
	}
}

//判断棋盘是否已经满了的函数
int IfFull(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 IfWin(char board[ROW][COL], int row, int col)
{
	//判断行
	for (int i = 0; i < row; i++)
	{
		for (int j = 2; j < col; j++)
		{
			if (board[i][j - 2] == board[i][j - 1] && board[i][j - 1] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断列
	for (int j = 0; j < col; j++)
	{
		for (int i = 2; i < row; i++)
		{
			if (board[i - 2][j] == board[i - 1][j] && board[i - 1][j] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断右交叉
	for (int i = 2; i < row; i++)
	{
		for (int j = 2; j < col; j++)
		{
			if (board[i - 2][j - 2] == board[i - 1][j - 1] && board[i - 1][j - 1] == board[i][j] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断左交叉
	for (int i = 1; i < row - 1; i++)
	{
		for (int j = 1; j < col - 1; j++)
		{
			if (board[i - 1][j + 1] == board[i][j] && board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
			{
				return board[i][j];
			}
		}
	}
	//判断平局
	int full = IfFull(board, row, col);
	if (full == 1)
	{
		return 'Q';
		
	}
	//游戏继续
	return 'C';
}

3、game.h文件

//头文件的包含
#include<stdio.h>
#include<stdlib.h>
#include<time.h>


//符号的定义
#define ROW 3
#define COL 3

//函数的声明

//初始化棋盘函数
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);
//判断游戏结果  玩家赢了*  电脑赢了#  平局Q  游戏继续C
char IfWin(char board[ROW][COL], int row, int col);
//判断棋盘是否已经下满
int IfFull(char board[ROW][COL], int row, int col);


感谢你的阅读,希望对你有所帮助~

欢迎批评指正,共同进步!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1514652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STL】stack栈容器与list链表容器

1.栈stack 栈具有先进后出的特性&#xff0c;最先进入的数据压在最底下&#xff0c;最后出来 2.list链表容器 list链表容器是一种双向链表&#xff0c;两端都可插入与删除&#xff0c;是双向访问迭代器&#xff0c;与vertor随机访问迭代器有不同的区别 reverse&#xff08;&…

设计模式 — — 单例模式

一、是什么 单例模式只会在全局作用域下创建一次实例对象&#xff0c;让所有需要调用的地方都共享这一单例对象 二、实现 // 单例构造函数 function CreateSingleton (name) {this.name name;this.getName(); };// 获取实例的名字 CreateSingleton.prototype.getName func…

torch.backends.cudnn.benchmark 作用

相关参数 torch.backends.cudnn.enabled torch.backends.cudnn.benchmark torch.backends.cudnn.deterministictorch.backends.cudnn.benchmark True&#xff1a;将会让程序在开始时花费一点额外时间&#xff0c;为整个网络的每个卷积层搜索最适合它的卷积实现算法&#xff0c…

2024最新修复版独立付费进群系统源码全开源

1、修复SQL表 2、修复支付文件 3、修复支付图标不显示 4、修复定位、分销逻辑、抽成逻辑 5、新增支持源支付、易支付的支付接口 6、修复官方微信、支付宝支付接口文件 本来早就可以完工的&#xff0c;被99ai群里的几个傻逼耽搁了&#xff0c;做好自己就行了&#xff0c;这…

腾讯云轻量服务器地域怎么选择?上海/北京/广州哪个合适?

腾讯云轻量应用服务器地域如何选择&#xff1f;地域就近选择&#xff0c;北方选北京地域、南方选广州地域&#xff0c;华东地区选上海地域。广州上海北京地域有什么区别&#xff1f;哪个好&#xff1f;区别就是城市地理位置不同&#xff0c;其他的差不多&#xff0c;不区分好坏…

【Oracle】ORA-00936: 缺失表达式

ORA-00936: 缺失表达式 in 后面 拼接参数无数据会引起 ORA-00936: 缺失表达式。 若from前存在逗号&#xff0c;语法不规范会引起 ORA-00936: 缺失表达式。 数据类型不匹配&#xff0c;若在日期的选择上&#xff0c;要求输入字符串型&#xff08;varchar2&#xff09;&#xff0…

为什么 VSCode 不用 Qt 而要用 Electron?

为什么 VSCode 不用 Qt 而要用 Electron? 在开始前我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Qt 的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&am…

SSA-LSTM多输入回归预测 | 樽海鞘优化算法-长短期神经网络 | Matlab

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编译&am…

【C语言】字符串函数上

&#x1f451;个人主页&#xff1a;啊Q闻 &#x1f387;收录专栏&#xff1a;《C语言》 &#x1f389;道阻且长&#xff0c;行则将至 前言 这篇博客是字符串函数上篇&#xff0c;主要是关于长度不受限制的字符串函数&#xff08;strlen,strcpy,strcat,strcm…

React路由结合Material UI的ListItemButton组件完成导航示例

React路由结合Material UI的ListItemButton组件完成导航示例 1、创建菜单列表NavigationList.jsx2、App.js 1、创建菜单列表NavigationList.jsx import React from react; import { ListItemButton, ListItemText, List } from mui/material; import { NavLink as RouterLink …

【GIT】使用Vscode同步git仓库,错误和解决方法记录

这里写目录标题 命令行操作仓库常见命令1 报错“在签出前&#xff0c;请清理存储库工作树。”2 报错“fatal: unable to access https://github.com/...: OpenSSL SSL_read: Connection was reset, errno 10054”3 报错“fatal: bad boolean config value “false” for http.s…

(黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

&#xff08;黑马出品_高级篇_01&#xff09;SpringCloudRabbitMQDockerRedis搜索分布式 微服务技术——保护 今日目标1.初识Sentinel1.1.雪崩问题及解决方案1.2.服务保护技术对比1.3.Sentinel介绍和安装1.3.1.初识Sentinel1.3.2.安装Sentinel 1.…

Purple Pi OH鸿蒙开发板7天入门OpenHarmony开源鸿蒙教程【六】

今天我们来从OpenHarmony简介、环境搭建、创建第一个OpenHarmony项目等方面开始OpenHarmony应用开发的第一步。 一. OpenHarmony简介 OpenHarmony 是由开放原子开源基金会&#xff08;OpenAtom Foundation&#xff09;孵化及运营的开源项目,目标是面向全场景、全连接、全智能…

今天我们来学习一下关于MySQL数据库

目录 前言: 1.MySQL定义&#xff1a; 1.1基础概念&#xff1a; 1.1.1数据库&#xff08;Database&#xff09;&#xff1a; 1.1.2表&#xff08;Table&#xff09;&#xff1a; 1.1.3记录&#xff08;Record&#xff09;与字段&#xff08;Field&#xff09;&#xff1a; …

jenkins + gitea 自动化部署Docker项目(vue + .NET Core)

废话不多说&#xff0c;服务先安装好Jenkins 和 gitea 理论上 gitlab 一样的实现流程 Jenkins 配置&#xff1a; 第一步装插件 安装 Generic Event 安装 gitea 相关插件 创建一个任务 设置 git 根据自己git 的认证填写对应的认证方式 构建环境记得勾选这个&#xff0c;会清…

pytorch模型转onnx格式,编写符号函数实现torch算子接口和onnx算子的映射,新建简单算子--模型部署记录整理

对于深度学习模型来说&#xff0c;模型部署指让训练好的模型在特定环境中运行的过程。相比于软件部署&#xff0c;模型部署会面临更多的难题&#xff1a; 运行模型所需的环境难以配置。深度学习模型通常是由一些框架编写&#xff0c;比如 PyTorch、TensorFlow。由于框架规模、依…

rt-thread之sal+lwip的tcp客户端示例记录(接收非阻塞)

示例记录 #include "lwip_test.h" #include "lwip/sockets.h" #include "netdev.h"#define DBG_ENABLE #define DBG_TAG "lwip.tst" #define DBG_LVL DBG_LOG#include <rtdbg.h>#define SERVER_PORT 8080 #define SERVER_HOST …

《ElementPlus 与 ElementUI 差异集合》icon 图标使用(包含:el-button,el-input和el-dropdown 差异对比)

安装 注意 ElementPlus 的 Icon 图标 要额外安装插件 element-plus/icons-vue. npm install element-plus/icons-vue注册 全局注册 定义一个文件 element-icon.js &#xff0c;注意代码第 6 行。加上了前缀 ElIcon &#xff0c;避免组件命名重复&#xff0c;且易于理解为 e…

还是了解下吧,大语言模型调研汇总

大语言模型调研汇总 一. Basic Language ModelT5GPT-3LaMDAJurassic-1MT-NLGGopherChinchillaPaLMU-PaLMOPTLLaMABLOOMGLM-130BERNIE 3.0 Titan 二. Instruction-Finetuned Language ModelT0FLANFlan-LMBLOOMZ & mT0GPT-3.5ChatGPTGPT-4AlpacaChatGLMERNIE BotBard 自从Cha…

如何创建Gitflow图表

如何创建Gitflow图表 drawio是一款强大的图表绘制软件&#xff0c;支持在线云端版本以及windows, macOS, linux安装版。 如果想在线直接使用&#xff0c;则直接输入网址drawon.cn或者使用drawon(桌案), drawon.cn内部完整的集成了drawio的所有功能&#xff0c;并实现了云端存储…