C语言:简单的三子棋游戏

news2024/9/20 14:57:04

       谈到三子棋,想必大家都不陌生,童年的回忆呀,读小学的时候有事没事就和同学玩上个几把,玩起来很得劲,作为一个学习计算机的博主,自然而然用代码来实现三子棋啦,再次感受童年的记忆,闲话少谈,直接进入今天的主题-----C语言实现简单的三子棋游戏。

1b26a990963d4e7992a4b51aa6a7241c.jpeg

 一:三子棋框架。

b7bf5d05cf5d4ad7bffb29aa53ba1d6b.png

二:test.c实现

 ①:写出主函数。

主函数主要是能循环,继续玩,并且能包括三子棋所有功能。

a588f41fd4b64f60845f9c1f4995a67a.png

②: 其次game()函数的实现。(实现玩游戏)

1.初始化棋盘为空格  void InitBoard(char board[ROW][COL], int row, int col)

2.打印棋盘  void DisplayBoard(char board[ROW][COL], int row, int col)

3.下棋 :  玩家下棋 void PlayerMove(char board[ROW][COL], int row, int col)

                电脑下棋 void CompaterMove(char board[ROW][COL], int row, int col)

4.判断输赢  char Iswin(char board[ROW][COL], int row, int col)

void game()
{
	char board[ROW][COL] = { 0 };   //定义一个3×3的字符数组
	char ret;
	//初始化棋盘为空格
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	//下棋
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		CompaterMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	//ret == * 为玩家赢
	//ret == # 为电脑赢
	//ret == Q 为平局
	//ret == C 为继续

	if (ret == '*')
	{
		printf("玩家赢\n");
	}
	else if (ret == '#')
	{
		printf("电脑赢\n");
	}
	else {
		printf("平局\n");
	}
}

细节注意:玩家下一个子就打印一下棋盘,玩家下一个子就打印一下棋盘,如不再继续下子,说明没有地方可以下子了,就跳出while(1)循环,看判断输赢返回的是什么,就判断输赢和平局。想要这些函数可以使用,直接调用game.h---->#include"game.h"

三:game.h实现

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

#define ROW 3  //行
#define COL 3  //列

//打印菜单
void menu();
//初始化棋盘为空格
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 CompaterMove(char board[ROW][COL], int row, int col);
//判断输赢
char Iswin(char board[ROW][COL], int row, int col);

三:game.c实现(重点)

①.打印菜单(简单)

//打印菜单
void menu()
{
	printf("*********************************\n");
	printf("*********    1.play    **********\n");
	printf("*********    0.exit    **********\n");
	printf("*********************************\n");
}

②.初始化棋盘为空格

       因为初始化3×3棋盘空格,所以需要传入char board[ROW][COL], int row, int col,字符数组,行,列。

void InitBoard(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++)
		{
			board[i][j] = ' ';
		}
	}
	
	/*for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			printf("%c", board[i][j]);
		}
		printf("\n");
	}*/

}

③.打印棋盘

02c21e3eff224dc88e7802ec781ee0df.png

 

void DisplayBoard(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++)
		{
			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");
		}
	}

}

④.玩家下棋

细节注意:如果玩家下好了就在棋盘打印*,如果输入的坐标有误,用循环while(1),输入成功就跳出循环,直到输入成功。

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 >= 1 && x <= row) && (y >= 1 && y <= col))
		{
			//没有下子的坐标,打印*
			if (board[x - 1][y - 1] == ' ')
			{
				board[x - 1][y - 1] = '*';
				break;
			}
			//此坐标已有子, 请重新输入
			else	
			{
				printf("此坐标已有子,请重新输入\n");
			}
		}
		//错误的坐标
		else
		{
			printf("输入错误,请重新输入坐标\n");
		}
	}
}

⑤.电脑下棋

        细节注意:因为要产生随机坐标,就要用到#include<stdlib.h> #include<time.h>两个函数,而在主函数需要写上srand((unsigned int)time(NULL));(这里可以看看博主的C语言猜数字游戏),如果电脑下好了就在棋盘打印#,如果输入的坐标有误,用循环while(1),输入成功就跳出循环,直到输入成功。

void CompaterMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % row;
		y = rand() % col;
		if (board[x][y] == ' ')
		{
			board[x][y] = '#';
			break;
		}
	}
}

⑥.判断输赢

          只要判断行,列,对角线,平局问题。行,列,对角线判断完成就返回*或者#或者Q或者C

 * 为玩家赢   # 为电脑赢  Q 为平局   C 为继续。

//判断平局
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;
	int j = 0;
	//列
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		{
			return board[i][0];
		}
	}
	//行
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[0][i];
		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return  board[1][1];
	}
	if (IsFull(board, ROW, COL) == 1)
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}

OK,上述test.c   game.h  game.c文件讲解完毕,上完整代码。

test.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void game()
{
	char board[ROW][COL] = { 0 };
	char ret;
	//初始化棋盘为空格
	InitBoard(board, ROW, COL);
	//打印棋盘
	DisplayBoard(board, ROW, COL);
	//下棋
	while (1)
	{
		//玩家下棋
		PlayerMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
		//电脑下棋
		CompaterMove(board, ROW, COL);
		DisplayBoard(board, ROW, COL);
		//判断输赢
		ret = Iswin(board, ROW, COL);
		if (ret != 'C')
			break;
	}
	//ret == * 为玩家赢
	//ret == # 为电脑赢
	//ret == Q 为平局
	//ret == C 为继续

	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("请输入-->");
		scanf("%d", &input);
		switch(input)
		{
		case 1:
			game();//玩游戏
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
			break;
		}
	} while (input);

	return 0;
}

game.h:

#pragma once

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

#define ROW 3
#define COL 3

//打印菜单
void menu();
//初始化棋盘为空格
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 CompaterMove(char board[ROW][COL], int row, int col);
//判断输赢
char Iswin(char board[ROW][COL], int row, int col);

game.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

//打印菜单
void menu()
{
	printf("*********************************\n");
	printf("*********    1.play    **********\n");
	printf("*********    0.exit    **********\n");
	printf("*********************************\n");
}

//初始化棋盘为空格
void InitBoard(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++)
		{
			board[i][j] = ' ';
		}
	}
	
	/*for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			printf("%c", board[i][j]);
		}
		printf("\n");
	}*/

}

//打印棋盘
void DisplayBoard(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++)
		{
			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)
{
	int x = 0;
	int y = 0;
	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("输入错误,请重新输入坐标\n");
		}
	}
}

//电脑下棋
void CompaterMove(char board[ROW][COL], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		x = rand() % row;
		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;
	int j = 0;
	//列
	for (i = 0; i < row; i++)
	{
		if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ')
		{
			return board[i][0];
		}
	}
	//行
	for (i = 0; i < col; i++)
	{
		if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ')
		{
			return board[0][i];
		}
	}
	//对角线
	if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ')
	{
		return board[1][1];
	}
	if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')
	{
		return  board[1][1];
	}
	if (IsFull(board, ROW, COL) == 1)
	{
		return 'Q';
	}
	else
	{
		return 'C';
	}
}

    不知不觉就到了尾声啦,作为小白的我,可能写的不是很好,不对的地方还请各位小伙伴留言给我谢谢啦。7221dfce3a9741758214cd250913d198.pngfbd9f005bc434c6194c5e57df8ebe7ae.png

985e495a86484b0f81e67ec753a59e3b.gif

 

 

 

 

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

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

相关文章

yolov8 实例分割 C++部署

此处仅为个人结果记录&#xff0c;并无完整部署代码 目录 Pre 一、OpenCV DNN C 部署 二、ONNX RUNTIME C 部署 Pre 一定要知道&#xff0c;yolov8的输出与Yolov5 7.0 实例分割的输出不一样&#xff0c; output0: float32[1,116,8400]。 116是4个box坐标信息80个类别概率…

政务场景|看「API-SMAC」如何守好API,保障流动数据安全

API让一切都变得更加容易。 在数字化进程加速中&#xff0c;API作为高速通道&#xff0c;让数据的流动变得更加自由。当然&#xff0c;黑客也这么认为。从前窃取数据需要攻入内网&#xff0c;再经过一系列复杂的横向移动最终访问目标数据库&#xff0c;极易被安全设备拦截。现在…

endNote X9 增加 / 删除参考文献 文献编号自动更新

文章目录 1 增插参考文献2 删减参考文献3 EndNote X9 插入参考文献常见问题总结4 EndNote X9 快速上手教程&#xff08;毕业论文参考文献管理器&#xff09; 1 增插参考文献 当前已经插入5个文献&#xff0c;文献编号及附录列表如下 例如在&#xff0c;2和3之间新插入文献 “邱…

基于粒子群优化算法的最佳方式优化无线传感器节点的位置(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 此代码优化了由于电池耗尽而产生覆盖空洞后 WSN 节点的位置。如果活动通信中的任何节点死亡&#xff0c;则通过PSO优化再次定位…

动态联编和静态联编

基本概念 1.静态联编&#xff08;早联编&#xff09;&#xff1a;在程序被编译时进行联编。程序执行快&#xff0c;但灵活性较小。 2.动态联编&#xff08;晚联编&#xff0c;滞后联编&#xff09;&#xff1a;编译时无法确定要调用的函数&#xff0c;在程序运行时联编。灵活…

代码随想录算法训练营day37 | 738.单调递增的数字,968.监控二叉树

代码随想录算法训练营day37 | 738.单调递增的数字&#xff0c;968.监控二叉树 738.单调递增的数字968.监控二叉树&#xff08;难&#xff09; 738.单调递增的数字 教程视频&#xff1a;https://www.bilibili.com/video/BV1Kv4y1x7tP/?spm_id_from333.788&vd_sourceddffd5…

Pytorch环境下基于Transformer的滚动轴承故障诊断

关于python的集成环境&#xff0c;我一般Anaconda 和 winpython 都用&#xff0c;windows下主要用Winpython&#xff0c;IDE为spyder&#xff08;类MATLAB界面&#xff09;。 winpython脱胎于pythonxy&#xff0c;面向科学计算&#xff0c;兼顾数据分析与挖掘&#xff1b;Anaco…

如何恢复数据?数据恢复,5个实用方法!

案例&#xff1a;如何恢复数据 【我是个比较粗心的人&#xff0c;总是会莫名奇妙的就丢失各种电脑的数据&#xff0c;想问下大家在使用电脑时&#xff0c;如果有数据的丢失&#xff0c;是如何恢复数据的呢&#xff1f;】 在使用Windows电脑时&#xff0c;数据丢失或删除是非常…

支付系统设计二:统一开发框架

文章目录 前言一、项目分层二、模块职责简介1. API层2. Service层2.1 操作执行服务2.2 操作器2.3 操作执行器2.4 参数校验2.5 操作器实现 3. Domain层4. Infrastructure层4.1 Dal层 三、对应类图四、开发内容3.1 约定请求报文格式3.2 新增交易码与操作器映射枚举类3.3 配置参数…

2 # 函数柯里化

什么是函数柯里化 函数柯里化&#xff08;Currying&#xff09;是一种将接受多个参数的函数转换为一系列接受单一参数的函数的技术。 通过函数柯里化&#xff0c;我们可以将原来接受多个参数的函数&#xff0c;转换为一系列只接受单一参数的函数&#xff0c;每个函数接收一个…

前端面试题总结(初级前端:HTML + CSS + JavaScript + Ajax + Vue2全家桶)

theme: channing-cyan 求关注&#x1f62d; 壹、HTML CSS 1. 对HTML语义化的理解 去掉或者丢失样式的时候能够让页面呈现出清晰的结构&#xff1b;代码结构清晰&#xff0c;方便团队的管理和维护&#xff0c;并且语义化更具可读性&#xff1b;提升用户体验&#xff0c;在…

什么是daemon与服务(service)

什么是daemon与服务(service) 在Linux系统中&#xff0c;daemon是指一类在后台运行的服务进程&#xff0c;通常以d结尾。它们不与用户进行交互&#xff0c;也不接受用户的输入&#xff0c;而是在系统启动时自动启动并一直运行&#xff0c;为操作系统、应用程序和其他服务提供支…

Julia入门-3、Julia包管理工具

文章目录 0、Julia 的包管理工具是Pkg1、使用Julia包管理工具过慢 0、Julia 的包管理工具是Pkg Julia 的包管理工具是Pkg&#xff0c;可以用于安装、更新、卸载和管理 Julia 中的软件包。以下是一些常用的 Pkg命令&#xff1a; Pkg.add("Package")&#xff1a;安装一…

Node.js 与 WebAssembly

目录 1、简介 2、关键概念 3、生成WebAssembly模块 4、如何使用它 5、与操作系统交互 1、简介 首先&#xff0c;让我们了解为什么WebAssembly是一个很棒的工具&#xff0c;并学会自己使用它。 WebAssembly是一种类似汇编的高性能语言&#xff0c;可以从各种语言编译&…

深度学习 - 47.DIN 深度兴趣网络保姆级实现 By Keras

目录 一.引言 二.DIN 模型分析 1.Input 输入 2.Embedding & Concat 嵌入与合并 3.DIN 深度兴趣网络 4.MLP 全连接 三.DIN 模型实现 1.Input 2.DIN Layer 2.1 init 初始化 2.2 build 构建 2.3 call 调用 3.Dice Layer 3.1 init 初始化 3.2 build 构建 3.3 …

网络安全:渗透神器 kali 的安装.

网络安全&#xff1a;渗透神器 kali 的安装. Kali Linux是一款基于Debian的Linux发行版&#xff0c;专门用于渗透测试和网络安全评估。它包含了大量的渗透测试工具和网络安全工具&#xff0c;适用于各种不同的渗透测试场景和需求。 目录&#xff1a; 网络安全&#xff1a;渗透…

MS5814可选内置基准、四通道数模转换器

MS5814/5814T 是一款 12bit 四通道输出的电压型 DAC&#xff0c;集成可选内部基准&#xff0c;接口采用四线串口模式&#xff0c;可以兼容 TMS320、SPI、QSPI 和 Microwire 串口。MS5814/5814T 控制数据有 16bit&#xff0c;包括 DAC 地址&#xff0c;控制字节和 12bitDAC 数据…

MySQL——BasicKnowledge

1. Mysql Version ​​​​​​​​​​​​ 2.install & uninstall 2.1 Linux My Content 3.Configure 3.1 设置IP访问 参考链接 3.1.1 方法一&#xff1a;改表法 --登入mysql后&#xff0c;更改"mysql"数据库中"user"表里的 "host&quo…

“三问五步”落地医疗行业数据安全建设体系|盾见

个 文|龚磊 2021年6月10日&#xff0c;我国《数据安全法》颁布&#xff0c;并于2021年9月1日正式施行&#xff0c;作为数据领域的纲领性和基础性法律&#xff0c;以准确定义数据、数据处理、数据安全为出发点&#xff0c;提出解决数据全生命周期中的数据安全问题&#xff0c;达…

深入浅出,理解知识图谱技术及其应用

知识图谱是一个将各种实体之间的关系以图谱的形式呈现出来的技术。这些实体可以是人、地点、组织或任何其他类型的实体。知识图谱将这些实体与它们之间的关系链接在一起&#xff0c;从而形成一个表示知识的图形结构。本文将介绍知识图谱的基础知识&#xff0c;包括它的定义、应…