C语言实现三子棋游戏(可以改变为四子棋或者多子棋版)

游戏介绍

三子棋游戏或者说是井字棋游戏,相信大家都玩过,一般的流程就是在一个棋盘上,玩家下棋之后,电脑下棋,然后判断输赢,如果没输没赢,就再玩家下棋,电脑下棋。

游戏框架

对于这个小游戏来说,代码量还算少量,所以我们可以分为三个文件来写,养成好习惯,方便以后在公司好合作,所以我们就 test.c   game.c   game.h 三个文件:

test.c:用来写游戏的基本逻辑,包含打印菜单,游戏逻辑的展现。

game.c:最核心的代码部分,用来写游戏逻辑的实现,这部分一般不给别人看。

game.h:包含代码需要的头文件,函数定义,常量等。

游戏基本逻辑的介绍

我们首先要给玩家一个菜单,玩家才能选择是否开始游戏。我们需要上来就打印菜单,玩家再选择,所以我们使用do while 循环,在这个循环里需要一个选择语句,所以基本逻辑就是这样:

菜单:

这里玩家输入1 或者 0 ,就很妙,while循环()里放 input,输入1 就又开始循环,输出菜单,输入0 就结束循环了,退出游戏。

游戏具体功能实现

初始化棋盘

我们发现棋盘有行和列,这与我们的二维数组很相符,所以我们就定义一个二维数组来当棋盘

记住这个定义常量,这样我们就可以很方便的改变成多子棋之类的。

初始化棋盘只需要把二维数组里全部设为空格就行。

打印棋盘

我们的棋盘长什么样的:

所以我们需要打印这些分隔符。

玩家下棋

需要注意的点是:

1. 我们数组的下标是从0开始的,但是玩家下棋的话,他可能不知道下标从0开始,所以我们就需要自己操作一下。

2. 玩家下棋的坐标必须在棋盘内才能下,并且下的坐标必须没有棋子才行,所以需要判断。

电脑下棋

我们的电脑随机下棋,所以用rand 和 srand 函数。

判断输赢

判断输赢是这里比较复杂的地方,我们游戏有四种状态:1.玩家赢游戏结束 2.电脑赢游戏结束 3.游戏平局游戏结束 4. 游戏继续。 我们每次玩家下棋和电脑下棋都需要判断输赢,所以我们的函数返回:

行和列:

我们的输赢就是一行或者一列一样的就是谁赢了,有一行,一列的判断。例如:在一行中判断,要相互两个之间是一样的并且不是空格,那么flag就加一,只要flag 等于col -1 就说明赢了。

对角线:

除了行和列,我们还有对角线的判断:

看图我们就可以寻找到两条对角线的规律,依次写我们的代码。

平局:

我们遍历数组的所有元素如果有一个空格就不会平局,当一个也没有了就平局。

游戏继续:

如果以上都不是,就直接游戏继续。

特别提示:我们四种情况的返回字符也非常巧妙,当我们玩家赢和电脑赢的时返回的是他们下的棋子,这样我们就可以减少一些代码量了,不用单独判断一行或者一列是谁赢了。

游戏完整代码

test.c

#include"game.h"

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

void play()
{
	char ret = 0;//判断输赢的字符
	char board[ROW][COL];
	//初始化棋盘
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		system("cls");//清空屏幕
		DisplayBoard(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		if (ret != 'A')
		{
			break;
		}
		//电脑下棋
		ComputerMove(board, ROW, COL);
		system("cls");
		printf("电脑下完棋了,该你了\n");
		DisplayBoard(board, ROW, COL);
		ret = IsWin(board, ROW, COL);
		if (ret != 'A')
		{
			break;
		}
	}
	if (ret == '*')
	{
		printf("玩家获胜\n");
	}
	else if (ret == '#')
	{
		printf("电脑获胜\n");
	}
	else
	{
		printf("平局\n");
	}
}


int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		meun();
		printf("请输入:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			play();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}

	} while (input);
}

game.c

#include"game.h"

void InitBoard(char board[ROW][COL], int row, int col)
{
	for (int 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)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			//打印数据
			printf(" %c ", board[i][j]);
			if (j < col - 1)
			{
				printf("|");
			}
		}
		printf("\n");
		//打印分隔符
		if (i < row - 1)
		{
			for (int h = 0; h < col; h++)
			{
				printf("---");
				if (h < col - 1)
				{
					printf("|");
				}
			}
		}
		printf("\n");
	}
}


void PlayerMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("玩家输入坐标:");
		scanf("%d %d", &x, &y);
		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)
{
	//随机下棋
	while (1)
	{
		int x = rand() % row;
		int y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

//对角线1
int Catercorner_diagonal_1(char board[ROW][COL], int row, int col)
{
	int flag = 0;
	for (int i = 0; i < row - 1; i++)
	{
		if (board[i][i] == board[i + 1][i + 1] && board[i][i] != ' ')
		{
			flag++;
		}
	}
	return flag;
}
//对角线2
int Catercorner_diagonal_2(char board[ROW][COL], int row, int col)
{
	int flag = 0;
	for (int i = 0; i < row - 1; i++)
	{
		int j = col - 1;
		if (board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ')
		{
			flag++;
		}
		j--;
	}
	return flag;
}

static 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)
{
	//判断行
	for (int i = 0; i < row ; i++)
	{
		int j = 0;
		int flag = 0;//计算一行是否一样的标志
		for (j = 0; j < col - 1; j++)
		{
			if (board[i][j] == board[i][j + 1]  && board[i][j] != ' ')
			{
				flag++;
			}
		}
		if (flag == col - 1)
		{
			return board[i][j];
		}
	}
	//判断列
	for (int j = 0; j < col; j++)
	{
		int i = 0;
		int flag = 0;//计算一列是否一样的标志
		for (i = 0; i < row - 1; i++)
		{
			if (board[i][j] == board[i + 1][j] && board[i][j] != ' ')
			{
				flag++;
			}
		}
		if (flag == row - 1)
		{
			return board[i][j];
		}
	}
	//判断对角线
	if (Catercorner_diagonal_1(board, ROW, COL) == row - 1)
	{
		return board[0][0];
	}
	if (Catercorner_diagonal_2(board, ROW, COL) == row - 1)
	{
		return board[0][col];
	}
	//判断平局
	if (IsFull(board, row, col))
	{
		return 'Q';
	}

	return 'A';
}

game.h

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

#define COL 3 //列
#define ROW 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);

//判断输赢
char IsWin(char board[ROW][COL], int row, int col);
//玩家赢 返回*
//电脑赢 返回#
//平局  返回Q
//游戏继续 返回A

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型探索之路-应用篇13:企业AI大模型选型指南

目录 前言 一、概述 二、有哪些主流模型&#xff1f; 三、模型参数怎么选&#xff1f; 四、参数有什么作用&#xff1f; 五、CPU和GPU怎么选&#xff1f; 六、GPU和显卡有什么关系&#xff1f; 七、GPU主流厂商有哪些&#xff1f; 1、NVIDIA芯片怎么选&#xff1f; 2、…

Web前端 Javascript笔记1

为什么学习 JavaScript? JavaScript 是 web 开发人员必须学习的 3 门语言中的一门&#xff1a; HTML 定义了网页的内容CSS 描述了网页的布局JavaScript 控制了网页的行为 JavaScript 是可插入 HTML 页面的编程代码。 JavaScript 插入 HTML 页面后&#xff0c;可由所有的现代浏…

FPGA原理与结构(8)——块RAM(Block RAM,BRAM)

系列文章目录&#xff1a;FPGA原理与结构&#xff08;0&#xff09;——目录与传送门 一、BRAM简介 大家对于RAM应该并不陌生&#xff0c;RAM就是一张可读可写的存储表&#xff0c;它经常被拿来与ROM进行对比&#xff0c;相比之下&#xff0c;ROM只可读。而在FPGA中&#xff0c…

图灵奖2023:Avi Wigderson的开创性贡献揭示计算中的随机性和伪随机性

文章目录 每日一句正能量前言背景什么是理论计算机科学&#xff1f;为什么随机性很重要&#xff1f;三篇影响深远的论文Avi Wigderson在计算复杂性理论方面的贡献及其对现代计算的影响Avi Wigderson对随机性和伪随机性在计算中作用的理解及其实际应用Avi Wigderson的学术生涯和…

用于密集视觉冲击的紧凑三维高斯散射Compact 3D Gaussian Splatting For Dense Visual SLAM

Compact 3D Gaussian Splatting For Dense Visual SLAM 用于密集视觉冲击的紧凑三维高斯散射 Tianchen Deng 邓天辰11Yaohui Chen 陈耀辉11Leyan Zhang 张乐妍11Jianfei Yang 杨健飞22Shenghai Yuan 圣海元22Danwei Wang 王丹伟22Weidong Chen 陈卫东11 Abstract 摘要 …

008、Python+fastapi,第一个后台管理项目走向第8步:ubutun 20.04下安装vscode+python环境配置

一、说明 白飘了3个月无影云电脑&#xff0c;开始选了个windows server 非常不好用&#xff0c;后台改为ubuntu想升级到22&#xff0c;没成功&#xff0c;那就20.04吧。 今天先安装下开发环境&#xff0c;后续2个月就想把他当做开发服务器&#xff0c;不知道行不行&#xff0c;…

行式存储VS列式存储对比

行式存储&#xff1a; 一行代表一个记录的所有字段。 可以快速读取和写入单条记录。 如果要检索一条数据&#xff0c;数据库会读取or写入整条记录&#xff0c;包含所有相关字段。 列式存储&#xff1a; 表中每一列的数据连续存放。这种方式在需要对某一列进行大量运算或分析时…

PSAvatar:一种基于点的可变形形状模型,用于3D高斯溅射的实时头部化身创建

PSAvatar: A Point-based Morphable Shape Model for Real-Time Head Avatar Creation with 3D Gaussian Splatting PSAvatar&#xff1a;一种基于点的可变形形状模型&#xff0c;用于3D高斯溅射的实时头部化身创建 Zhongyuan Zhao1,2, Zhenyu Bao1,2, Qing Li1, Guoping Qiu3,…

计算机虚拟机服务器中了mallox勒索病毒怎么办Mallox勒索病毒解密流程工具

在当今社会&#xff0c;人们的工作生活离不开网络&#xff0c;尤其企业离不开网络办公&#xff0c;网络为企业提供了极大便利&#xff0c;大大提升了企业的生产效率与办公水平&#xff0c;但网络是一把双刃剑&#xff0c;在为企业提供便利的同时也为企业的数据带来严重威胁。近…

【攻防世界】warmup

[HCTF 2018]WarmUp全网最详细解释_[hctf 2018]warmup的解-CSDN博客 php://filter 读取源码&#xff08;文件&#xff09; php://input 执行php代码&#xff0c;需要post请求提交数据 Content-Type为image/jpeg text. 绕过后缀的有文件格式有php,php3,php4,php5,pht…

探索企业级应用开发解决方案

1、什么是企业级应用 企业级应用是指为商业组织、大型企业创建并部署的应用。 企业级应用的结构复杂、涉及的外部资源众多、事务密集、数据量大、用户数多&#xff0c;需要较强的安全性。其特点有&#xff1a; &#xff08;1&#xff09;海量数据持久保存。 &#xff08;2&a…

不出天府锋巢直播产业基地,即可激活电商直播产业、产教融合及人才培训服务

天府锋巢直播产业基地打造直播产业产教融合及人才培训服务新模式&#xff0c;携手政府、企业、高校&#xff0c;促进直播产业与创新人才双向奔赴&#xff0c;推进教学与实战深度融合&#xff0c;推动实习与就业无缝衔接。 各方资讯一应俱全 直播产业产教融合及人才培训服务全套…

LabVIEW光学探测器板级检测系统

LabVIEW光学探测器板级检测系统 特种车辆乘员舱的灭火抑爆系统广泛采用光学探测技术来探测火情。光学探测器作为系统的关键部件&#xff0c;其探测灵敏度、响应速度和准确性直接关系到整个系统的运行效率和安全性。然而&#xff0c;光学探测器在长期使用过程中可能会因为灰尘污…

京东商品详情API接口(商品属性丨sku价格丨详情图丨标题等数据)

京东商品详情API接口是京东开放平台提供的一种API接口&#xff0c;通过调用该接口&#xff0c;开发者可以获取京东商品的标题、价格、库存、月销量、总销量、详情描述、图片等详细信息。下面针对您提到的商品属性、SKU价格、详情图以及标题等数据&#xff0c;做具体介绍&#x…

NL2SQL进阶系列(4):ConvAI、DIN-SQL、C3-浙大、DAIL-SQL-阿里等16个业界开源应用实践详解[Text2SQL]

NL2SQL进阶系列(4)&#xff1a;ConvAI、DIN-SQL等16个业界开源应用实践详解[Text2SQL] NL2SQL基础系列(1)&#xff1a;业界顶尖排行榜、权威测评数据集及LLM大模型&#xff08;Spider vs BIRD&#xff09;全面对比优劣分析[Text2SQL、Text2DSL] NL2SQL基础系列(2)&#xff1a…

用Cmake编译程序时,链接到FFmpeg库

用Cmake编译程序时&#xff0c;链接到FFmpeg库 一、前言 可喜可贺&#xff0c;折腾了一晚上终于把这个勾八链接成功了&#xff0c;已经要吐了。看到下面控制台的输出&#xff0c;吾心甚慰呀&#x1f62d; [100%] Linking CXX executable rknn_yolov5_demo [100%] Built targe…

如何解决selenium无头浏览器访问页面失败问题!!

无头浏览器简介 无头浏览器&#xff08;Headless browser&#xff09;是一种没有图形用户界面&#xff08;GUI&#xff09;的网络浏览器。它可以在后台运行&#xff0c;并通过编程接口进行控制和操作&#xff0c;而不需要显示界面。通常&#xff0c;传统的浏览器如 Chrome、Fi…

STL体系结构与各容器基本介绍

STL体系结构与各容器基本介绍 STL体系结构基本容器序列式关联式&#xff08;查找更快&#xff09;其他&#xff08;不常用&#xff09;使用分配器 STL体系结构 六大模块 容器算法迭代器适配器仿函数分配器 基本容器 序列式 array c11新标准array<类型&#xff0c;大小&…

C++:Hash应用【位图与布隆过滤器】

什么是位图&#xff1f; 我们先来看一个问题&#xff1a; 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在 这40亿个数中。【腾讯】 如果我们使用unordered_set容器来解决&#xff0c;40亿个数据&#xff0c;每个数据…

FastGPT+ChatGLM3本地部署

FastGPTChatGLM本地部署 本地部署硬性要求&#xff1a;显存13g以上 关于环境的安装就不多赘述&#xff0c;conda pip 可以解决大部分问题 ChatGLM本地运行 m3e-basechatglm3-6b 在huggingface上可以下载上述模型&#xff0c;如果没有梯子可以使用huggingface镜像 从git…