C语言实现简易n子棋小游戏(代码含注解)

利用C语言简单实现一个n子棋小游戏,棋盘大小由自己定义

将源文件分为   执行游戏的测试文件(test.c)和保存游戏运行逻辑的相关函数的文件(game.c)

头文件中声明符号和函数的定义(game.h)

游戏执行主要依靠二维数组实现,电脑走棋采用随机值的方法简易地实现而非采用高级的算法

头文件 game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include <math.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
//符号的定义(定义几子棋)
#define ROW 3
#define COL 3

//函数的定义
void InitBoard(char board[ROW][COL], int row, int col);//初始化棋盘
void PrintBoard(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);//判断游戏结果

源文件 test.c

#include "game.h"            //引用头文件
void game() {
	char ret;
	char board[ROW][COL];  //二维数组存储游戏数据,ROW、COL为行和列,在头文件game.h中定义
	InitBoard(board,ROW,COL);//初始化棋盘为空格
	PrintBoard(board, ROW, COL);//打印棋盘
	while (1) {
		printf("玩家走\n\n");
		PlayerMove(board, ROW, COL);  //玩家下棋
		Sleep(500);
		PrintBoard(board, ROW, COL);  
		//判断玩家是否赢得游戏
		ret=IsWin(board, ROW, COL);		//返回值为*代表玩家获胜、#代表电脑获胜、D代表平局、C代表未出结果,游戏继续
		if (ret != 'C') {
			break;
		}
		printf("电脑走\n\n");
		ComputerMove(board, ROW, COL);//玩家下棋
		Sleep(1300);
		PrintBoard(board, ROW, COL);
		//判断电脑是否赢得游戏
		ret = IsWin(board, ROW, COL);
		if (ret != 'C') {
			break;
		}

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

	}
	else if (ret == 'D') {
		printf("平局\n\n");
	}
	PrintBoard(board, ROW, COL);//打印游戏结果

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

}
int main() {
	int n;
	srand((unsigned int)time(NULL));//设置随机数种子
	do
	{
		menu();
		printf("请选择:\n");
		scanf("%d", &n);
		switch (n)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("选择错误,重新选择\n");
			break;
		}
	} while (n);
	return 0;
}

源文件 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 PrintBoard(char board[ROW][COL], int row, int col) {          //打印棋盘
	for (int j = 0; j < col; j++) {
		printf(" ___");
	}
	printf(" \n");
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			printf("| %c ",board[i][j]);
		}
		printf("|\n");
		if (i < row ) {
			for (int j = 0; j < col; j++) {
				printf("|___");
			}
			printf("|\n");
		}

	}
	printf("\n");
}
void PlayerMove(char board[ROW][COL], int row, int col) {
	while (1) {                            //若输入错误则一直循环
		int x, y;
		printf("请输入坐标:\n");
		scanf("%d %d", &x, &y);
        if (x <= row && x >= 1 && y <= col && y >= 1) {         //判断坐标是否合法
			if (board[x - 1][y - 1] == ' ')                     //玩家输入的坐标需要减1,因为数组从0开始,同时判断坐标是否被占用过
			{
				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;
		}
	}
}

char IsWin(char board[ROW][COL], int row, int col) {
	int x = 0;                   //计数器判断一行或一列是否遍历结束
	int sum1 = 0;                //判断*的数量
	int sum2 = 0;                //判断#的数量

	for (int i = 0; i < col; i++) {
		for (int j = 0; j < row; j++) {               //判断每行上是否有连续三个相等的符号
			if (board[i][j] == '*') {
				sum1 += 1;
			}
			if (board[i][j] == '#') {
				sum2 +=1;
			}
			x++;
			if(x==row){                                 //一行统计完时
				if (sum1 == row) {                        //一行全是*
					return '*';
				}
				else if (sum2 == row) {
					return '#';                         //一行全是#
				}
				else {                                  //一行中未分胜负则计数器清零统计下一行
					sum1 = 0;                         
					sum2 = 0;
					x = 0;
				}
			}

		}
	}
	for (int j = 0; j < row; j++) {
		for (int i = 0; i < col; i++) {                //行未分出胜负,则开始统计列
			if (board[i][j] == '*') {
				sum1 += 1;
				
			}
			if (board[i][j] == '#') {
				sum2 += 1;
			
			}
			x++;
			if (x == row) {                             //一列统计完时
				if (sum1 == row) {                        //一列全是*
					return '*';
				}
				else if (sum2 == row) {
					return '#';                         //一列连全是#
				}
				else {                                  //一列中未分胜负则计数器清零统计下一列
					sum1 = 0;
					sum2 = 0;
					x = 0;
				}
			}
		}
	}
	for (int i = 0; i < col; i++) {
		for (int j = 0; j < row; j++) {                 //行列都为分出胜负统计主对角线元素
			if (i == j) {
				if (board[i][j] == '*') {
					sum1 += 1;
				}
				else if (board[i][j] == '#') {
					sum2 += 1;
				}
			}
		}
	}
	if (sum1 == row) {
		return '*';                                     //主对角线上元素都为*
	}
	else if (sum2 == row) {
		return '#';                                     //主对角线上元素都为#
	}
	else {
		sum1 = 0;
		sum2 = 0;                                       //计数器清零统计副对角线
	}
	//查看副对角线上的元素,可以先复制一个横向翻转的临时棋盘board1,查看主对角线上的元素
	char board1[ROW][COL];
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			board1[i][j] = board[i][col-j-1];
		}
	}
	//判断临时棋盘的主对角线元素
	for (int i = 0; i < col; i++) {
		for (int j = 0; j < row; j++) {                 
			if (i == j) {
				if (board1[i][j] == '*') {
					sum1 += 1;
				}
				else if (board1[i][j] == '#') {
					sum2 += 1;
				}
			}
		}
	}
	if (sum1 == row) {
		return '*';                                     //主对角线上元素都为*
	}
	else if (sum2 == row) {
		return '#';                                     //主对角线上元素都为#
	}
	else {
		sum1 = 0;
		sum2 = 0;                                       //计数器清零
	}
	//查看是否为平局,则是以上都判断完后,棋盘是否满了,满了则返回‘D’,不满则继续
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			if (board[i][j] == ' ') {
				return 'C';                     //有地方是空的,游戏还未出结果
			}
		}
	}
	return 'D';                                 //棋盘满了且没分出胜负,则为平局
}

运行结果(以3子为例):

以上为C语言简易实现n子棋的内容

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

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

相关文章

小程序基础学习(组件通信)

介绍 点击子组件的按钮&#xff0c;把点击事件发送给页面 例如&#xff1a;点击这个“最大的一头猪”&#xff0c;由组件内部设置点击事件然后在传递给页面。 实现原理 给组件内部需要点击的文本设置点击事件 在组件内部监听点击事件&#xff0c;并发送给页面点击事件的详细信…

上门预约按摩平台有哪些功能,做上门推拿App开发详细攻略;

随着生活节奏的加快和工作压力的增加&#xff0c;越来越多的人开始注重身心健康。上门推拿服务作为一种便捷、个性化的健康护理方式&#xff0c;逐渐受到市场的青睐。为了满足这一市场需求&#xff0c;我们计划开发一款上门推拿App&#xff0c;为用户提供方便、专业的推拿服务。…

element-ui el-table表格勾选框条件禁用,及全勾选按钮禁用, 记录

项目场景&#xff1a; 表格的部分内容是可以被勾选的&#xff0c;部分内容是不可以被勾选的 使用的是 “element-plus”: “^2.2.22”, 以上应该都是兼容的 问题描述 要求el-table表格中&#xff0c;部分内容不可以被勾选&#xff0c;全选框在没有可选内容时&#xff0c;是禁…

Java_线程通信

一、线程通信 首先&#xff0c;什么是线程通信呢&#xff1f; 当多个线程共同操作共享资源时&#xff0c;线程间通过某种方式互相告知自己的状态&#xff0c;以相互协调&#xff0c;避免无效的资源挣抢。 线程通信的常见模式&#xff1a;是生产者与消费者模型 生产者线程负…

130基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原

基于MATLAB并结合IBD算法的盲迭代反卷积法进行图像复原 ,输出复原前后图像&#xff0c;PSF频谱结果。程序已调通&#xff0c;可直接运行。 130 matlab盲迭代反卷积IBD (xiaohongshu.com)

入门教程:使用 Postman 发送 post 请求

Postman 是一个实用的开发工具&#xff0c;它让发送各类 POST 请求成为了可能&#xff0c;包括文本、JSON、XML 以及文件等。开发者利用此工具不仅能够检验API的功能性&#xff0c;还能仿真客户端的请求行为&#xff0c;进而深入了解客户端如何与 API 进行互动。 HTTP 协议中的…

在线旅游2024:新旧交锋,暗流涌动

旅游热带来的泼天富贵&#xff0c;还在继续传递。 2023年大火的“烧烤之都”淄博曾是最大受益者&#xff0c;小烧烤风靡整个夏天。最近的哈尔滨凭借冰雪和异域特色一举成为新晋“网红旅游城市”&#xff0c;元旦假期的游客接待量和旅游总收入双双达到历史峰值。 “网红城市”…

工具推荐:知识库软件有了这些就够了

在现代企业中&#xff0c;信息传播、知识共享至关重要。由于公司内部员工、组织结构、业务流程如此庞大且复杂&#xff0c;失效和过时的信息可能会进一步增加混乱&#xff0c;影响效率。因此&#xff0c;有一个强大的知识库软件可以帮助公司整合所有的知识资源&#xff0c;确保…

C# winform应用

C# winform应用 需求&#xff1a;导入Excel文件时需要执行其他操作&#xff0c;实现如果取消导入就不执行其他操作 C#代码实现 private bool DLimport0(string tablename, string datebasename, string buttonname){string xxx "";string Tag "";stri…

fopen函数

目录 fopen函数 fopen函数 C 库函数 fopen 使用给定的模式 mode 打开 filename 所指向的文件。 FILE *fopen(const char *filename, const char *mode)filename — 字符串&#xff0c;表示要打开的文件名称。mode — 字符串&#xff0c;表示文件的访问模式&#xff0c;该指针…

数据库系统概念 第七版 中文答案 第3章 SQL介绍

3.1 将以下查询使用SQL语言编写&#xff0c;使用大学数据库模式。 &#xff08;我们建议您实际在数据库上运行这些查询&#xff0c;使用我们在书籍网站db-book.com上提供的示例数据。有关设置数据库和加载示例数据的说明&#xff0c;请参阅上述网站。&#xff09; a. 查找计算机…

Spring系列学习九、Spring MVC的使用

Spring MVC的使用 一、MVC设计模式概述二、Spring MVC的工作原理三、HandlerMapping和ViewResolver四、 处理表单、文件上传和异常处理五、前端页面&#xff08;View&#xff09;编写1. 引入Thymeleaf模板引擎2.页面相关的示例代码3.后端处理代码编写 六、总结 本章我们将与大家…

客户端请求服务器的步骤

当我们在浏览器地址栏输入’http://www.xxx.com/api/xxx"时&#xff0c;客户端是如何找到服务器并发送请求的&#xff1f; 1.先找到服务器 a.检测浏览器缓存有没有缓存该域名对应的IP地址&#xff0c;有则通过IP地址取找服务器。 b.检测本地的hosts文件&#xff0c;是否有…

写点东西《2024 年决心:更加以开源为中心》

写点东西《2024 年决心&#xff1a;更加以开源为中心》 简而言之1- 使用 Taipy 代替 Tableau 2- 使用 Cal.com 代替 Calendly 3- Plausible 代替 Google Analytics4- AppFlowy 代替 Notion5- Penpot 代替 Figma 6- Fonoster 代替 Twilio 7- NextCloud 替代 Dropbox 8- Jitsi 替…

羊驼2:开放的基础和微调聊天模型--Llama 2论文阅读

论文地址&#xff1a;https://arxiv.org/pdf/2307.09288.pdfd 代码地址&#xff1a;GitHub - facebookresearch/llama-recipes: Examples and recipes for Llama 2 model 问答 用了多少个gpu&#xff1f; 这篇文档中使用了3.3M GPU小时的计算&#xff0c;使用的硬件类型是A…

解决elementUI或elementPlus的按钮点击后需要失去焦点才能恢复原本样式问题

废话不多说直接上代码&#xff0c;只需要在button中添加如下代码即可 focus"(e) > e.target.blur()"

无重复字符的最长字串

题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 示例 1: 输入: s "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc"&#xff0c;所以其长度为 3。示例 2: 输入: s "bbbbb" 输出: 1 解…

虚拟政务大厅有什么好处,搭建虚拟政务大厅需要考虑哪些因素

引言&#xff1a; 在数字化时代&#xff0c;互联网技术推动了各行业发展&#xff0c;政务领域也不例外。虚拟政务大厅作为一种数字化解决方案&#xff0c;不仅改善了政务处理的效率和服务质量&#xff0c;还为政务处理带来了许多其他好处。 一、提高政务处理效率 1.虚拟政务大…

查询速度提升15倍!银联商务基于 Apache Doris 的数据平台升级实践

本文导读&#xff1a; 在长期服务广大规模商户的过程中&#xff0c;银联商务已沉淀了庞大、真实、优质的数据资产数据&#xff0c;这些数据不仅是银联商务开启新增长曲线的基础&#xff0c;更是进一步服务好商户的关键支撑。为更好提供数据服务&#xff0c;银联商务实现了从 H…

多模态大模型Clip

一、经典分类模型的问题: 类别固定当前的模型只能胜任一个任务&#xff0c;迁移到新任务上非常困难类别互斥当前的CV数据集标注劳动密集&#xff0c;成本较高&#xff0c;当前模型泛化能力较差 负样本的组成(Batchsize有N个文本-图像对) Batchsize太小&#xff0c;负样本太少…
最新文章