[C语言]连子棋游戏

文章目录

  • 一、前言
  • 二、游戏思路
  • 三、游戏方法
    • 1、初始化
    • 2、判断胜利
    • 3、交互
    • 4、电脑下棋
  • 四、核心方法说明
    • 1、初始化游戏
    • 2、销毁棋盘
    • 3、显示游戏
    • 4、电脑下棋
    • 5、用户下棋
    • 6、判断游戏状态
    • 7、游戏交互
  • 五、游戏效果展示与源码分享
    • 1、游戏效果
    • 2、源代码

一、前言

对于指针和数组理解尚不深入的读者,我们强烈建议您先通过以下链接进行学习,以便更好地理解和参与后续的连子棋游戏讨论:传送门。这些基础知识将为您搭建连子棋游戏框架提供坚实的支撑。


二、游戏思路

我们的连子棋游戏将基于经典的五子棋规则进行开发:传送门。

  • 游戏中,玩家和电脑将分别使用黑色和白色的棋子进行轮流下棋。
  • 当某一方的棋子能够在横向、纵向或斜向上连成连续的指定个数棋子时,该方即获得胜利。
  • 用户可以在前面选择游戏连子数量(四子以上)。

三、游戏方法

1、初始化

在游戏开始前,我们需要进行一系列初始化操作,包括创建游戏棋盘(通常使用二维数组表示),并初始化棋盘上的每个位置为空(表示尚未放置棋子)。此外,还需要设置当前玩家为黑方,并准备接收玩家的输入。

2、判断胜利

每当玩家在棋盘上放置一枚棋子后,我们需要遍历棋盘以检查是否存在已经连成了胜利所需的棋子串。这通常涉及到对棋盘进行多次遍历,分别检查横向、纵向和斜向上的棋子连续性。

3、交互

游戏过程中,玩家将通过标准输入(如键盘)来输入棋子的放置位置(通常是棋盘的行列坐标)。程序需要接收这些输入,并验证其有效性(确保坐标在棋盘范围内且该位置尚未放置棋子)。然后,程序将根据输入更新棋盘状态,并再次检查是否获得胜利。

4、电脑下棋

为了实现单人游戏模式,我们还需要为电脑玩家实现一个下棋算法。这通常涉及到一些人工智能算法的应用,如随机下棋、简单策略判断或更复杂的搜索算法(如蒙特卡洛树搜索)。在实现时,我们可以根据游戏复杂度和性能要求来选择合适的算法。


四、核心方法说明

1、初始化游戏

/** 初始化连子棋游戏* @param board 指向存储游戏棋盘的指针的指针* @param row 棋盘的行数* @param col 棋盘的列数*/
void init_board(char*** board, int row, int col)
{//开辟棋盘*board = (char**)malloc(sizeof(char*) * row);if (!(*board)){fprintf(stderr, "内存分配失败\n");exit(EXIT_FAILURE);}for (int i = 0; i < row; i++){(*board)[i] = (char*)malloc((col + 2) * sizeof(char));if ((*board)[i] == NULL){fprintf(stderr, "内存分配失败\n");//释放之前已分配的内存for (int j = 0; j < i; j++){free((*board)[j]);}free(*board);exit(EXIT_FAILURE);}}//初始化棋盘for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){(*board)[i][j] = ' ';}}
}

2、销毁棋盘

/** 销毁连子棋棋盘* @param board 指向存储游戏棋盘的指针的指针* @param row 棋盘的行数* @param col 棋盘的列数*/
void free_board(char*** board, int row, int col)
{assert(board != NULL);//销毁每一行for (int i = 0; i < row; i++){free((*board)[i]);}//销毁指针数组free(*board);*board = NULL;
}

3、显示游戏

/** 显示连子棋游戏* @param board 游戏棋盘* @param row 棋盘的行数* @param col 棋盘的列数*/
void show_board(char** board, int row, int col)
{assert(board != NULL);//打印列标for (int i = 0; i <= col; i++)printf("%d ", i);printf("\n");for (int i = 0; i < row; i++){printf("%d ", i + 1);//打印行标for (int j = 0; j < col; j++){//不同颜色显示棋子if (board[i][j] == '*')printf("\033[1;31m*\033[0m ");else if (board[i][j] == '#')printf("\033[1;33m*\033[0m ");elseprintf("%c ", board[i][j]);}printf("\n");}
}

4、电脑下棋

/** 电脑下棋* @param board 指向存储游戏棋盘的指针的指针* @param row 棋盘的行数* @param col 棋盘的列数* @param sum 连子个数* @return 游戏状态*/
int computer_play(char*** board, int row, int col, int sum)
{
start:assert(board != NULL);//电脑随机下棋int x = rand() % row + 1;int y = rand() % col + 1;if ((*board)[x - 1][y - 1] == ' '){(*board)[x - 1][y - 1] = '*';}else{goto start;}return is_win(*board, row, col, sum, x, y);
}

5、用户下棋

/** 用户下棋* @param board 指向存储游戏棋盘的指针的指针* @param row 棋盘的行数* @param col 棋盘的列数* @param sum 连子个数* @return 游戏状态*/
int user_play(char*** board, int row, int col, int sum)
{
start:assert(board != NULL);int x = -1, y = -1;printf("请选择下棋点(x,y):");scanf("%d,%d", &x, &y);if (clear_input()){x = -1, y = -1;}if ((x < 1 || x > row || y < 1 || y > col) || (*board)[x - 1][y - 1] != ' '){system("cls");printf("输入错误!\n");getchar();system("cls");show_board(*board, row, col);goto start;}(*board)[x - 1][y - 1] = '#';return is_win(*board, row, col, sum, x, y);
}

6、判断游戏状态

/** 判断是否连续sum个* @param board 游戏棋盘* @param row 棋盘的行数* @param col 棋盘的列数* @param sum 连子个数* @param x 当前下棋的行* @param y 当前下棋的列* @param dx 判断偏移x方向* @param dy 判断偏移y方向* @return 是否连续sum个*/
int is_sum(char** board, int row, int col, int sum, int x, int y, int dx, int dy)
{assert(board != NULL);assert(x >= 1 && x <= row && y >= 1 && y <= col);char flag = board[x - 1][y - 1];int count = 0;for (int i = -(sum - 1); i < sum; i++){int nx = x + dx * i;int ny = y + dy * i;if (nx >= 1 && nx <= row && ny >= 1 && ny <= col){if (board[nx - 1][ny - 1] == flag){count++;if (count == sum)return 1;}else{count = 0;}}}return 0;
}/** 判断是否结束* @param board 游戏棋盘* @param row 棋盘的行数* @param col 棋盘的列数* @param sum 连子个数* @param x 当前下棋的行* @param y 当前下棋的列* @return 游戏状态*/
int is_win(char** board, int row, int col, int sum, int x, int y)
{assert(board != NULL);assert(x >= 1 && x <= row && y >= 1 && y <= col);int direxction[4][2] = { {-1, 0}, {-1, 1}, {0, 1}, {1, 1} };for (int i = 0; i < 4; i++){if (is_sum(board, row, col, sum, x, y, direxction[i][0], direxction[i][1])){return board[x - 1][y - 1] == '*' ? -1 : 1;}}//是否平局for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (board[i][j] == ' ')return sum;}}return 0;
}

7、游戏交互

/** 清除标准输入缓冲区中直到换行符的所有字符,并返回一个标志位。* @return 如果缓冲区中有字符被清除,则返回1;否则返回0。*/
int clear_stdin(void)
{int flag = 0;while (getchar() != '\n')flag = 1;return flag;
}/** 连子棋游戏交互* @param board 指向存储游戏棋盘的指针的指针* @param row 棋盘的行数* @param col 棋盘的列数* @param sum 连子个数*/
void game(char*** board, int row, int col, int sum)
{init_board(board, row, col);srand((unsigned)time(NULL));int win = 0;while (1){system("cls");show_board(*board, row, col);win = user_play(board, row, col, sum);if (win == 1){system("cls");show_board(*board, row, col);free_board(board, row, col);printf("游戏胜利!\n");getchar();system("cls");break;}if (win == 0){system("cls");show_board(*board, row, col);free_board(board, row, col);printf("游戏平局!\n");getchar();system("cls");break;}win = computer_play(board, row, col, sum);if (win == -1){system("cls");show_board(*board, row, col);free_board(board, row, col);printf("游戏失败!\n");getchar();system("cls");break;}if (win == 0){system("cls");show_board(*board, row, col);free_board(board, row, col);printf("游戏平局!\n");getchar();system("cls");break;}}
}

五、游戏效果展示与源码分享

1、游戏效果

请添加图片描述

上图所展示的是我们精心打造的游戏效果,动态的画面、流畅的操作,是否已经让你跃跃欲试了呢?

2、源代码

为了让更多爱好者能够深入学习和交流,我们已将本游戏的源代码开源至Gitee平台。你可以通过以下传送门轻松获取,一起探索游戏的奥秘,共同进步。
已经在Gitee上开源:传送门


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

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

相关文章

关于std::swap原理

swap 操作交换两个相同类型容器的内容。调用swap之后&#xff0c;两个容器中的元素将会 交换&#xff1a; vector<striong> svec1(10); //10个元素的vector vector<string> svec2(24); //24个元素的vector swap(svec1,svec2); 调…

C++ | Leetcode C++题解之第413题等差数列划分

题目&#xff1a; 题解&#xff1a; class Solution { public:int numberOfArithmeticSlices(vector<int>& nums) {int n nums.size();if (n 1) {return 0;}int d nums[0] - nums[1], t 0;int ans 0;// 因为等差数列的长度至少为 3&#xff0c;所以可以从 i2 开…

一款免费开源且功能强大的思维导图软件-思绪思维导图

思绪思维导图是一款免费开源的思维导图软件&#xff0c;旨在帮助用户有效地组织和表达思想。它提供了丰富的功能&#xff0c;包括支持富文本、图片、图标、超链接、备注、标签等内容&#xff0c;以及关联线、概要等特性。 思绪思维导图下载&#xff1a;https://pan.quark.cn/s…

在STM32工程中使用Mavlink与飞控通信

本文讲述如何在STM32工程中使用Mavlink协议与飞控通信&#xff0c;特别适合自制飞控外设模块的项目。 需求来源&#xff1a; 1、增稳云台里的STM32单片机需要通过串口接收飞控传来的云台俯仰、横滚控制指令和相机拍照控制指令&#xff1b; 2、自制的有害气体采集器需要接收飞…

基于Springboot的医疗健康助手开题报告

文未可获取一份本项目的java源码和数据库参考。 一&#xff0e;选题意义, 研究现状,可行性分析 选题意义&#xff1a;随着科技的高速发展&#xff0c;人们的生活水平也正在稳步提高&#xff0c;解决温饱问题以后&#xff0c;广大人民群众也越来越注重自己的身体健康&#xff0…

[Redis][前置知识][下][高并发架构演进]详细讲解

目录 1.单机架构2.应⽤数据分离架构3.应⽤服务集群架构4.读写分离/主从分离架构5.引⼊缓存⸺冷热分离架构6.垂直分库/分表7.业务拆分⸺微服务8.总结 1.单机架构 只有一台服务器&#xff0c;这个服务器负责所有的工作 大部分公司的产品&#xff0c;都是这种单机架构 2.应⽤数…

自己建网站怎么建

自己建立一个网站可能听起来有点复杂&#xff0c;但实际上&#xff0c;有很多简单且免费的方法可以实现。下面将介绍一些基本步骤&#xff0c;帮助你开始自己建立一个网站。 首先&#xff0c;你需要明确你的网站目的是什么。是个人博客、商业网站&#xff0c;还是其他类型的网…

frp内网穿透功能使用教程

frp 是一款高性能的反向代理应用&#xff0c;专注于内网穿透。它支持多种协议&#xff0c;包括 TCP、UDP、HTTP、HTTPS 等&#xff0c;并且具备 P2P 通信功能。使用 frp&#xff0c;您可以安全、便捷地将内网服务暴露到公网&#xff0c;通过拥有公网 IP 的节点进行中转。 文档地…

深度学习----------------------文本预处理

目录 文本预处理读取数据集词源化词表该部分总代码该部分总代码 整合所有功能该部分总代码 文本预处理 文本预处理&#xff1a;把文本当作一个时序序列 将解析文本的常见预处理步骤。 这些步骤通常包括&#xff1a; ①将文本作为字符串加载到内存中。 ②将字符串拆分为词元&…

【数据结构篇】~链表算法题3(环形链表)

链表算法题3&#xff08;环形链表&#xff09; 环形链表的证明1. 环形链表I​1) 思路2&#xff09;代码实现 2. 环形链表II​1) 思路11) 思路22&#xff09;代码实现 环形链表的证明 1. 环形链表I​ https://leetcode.cn/problems/linked-list-cycle/description/ 1) 思路 判断…

Nginx搭建直播服务器,并用rtmp,http-flv,hls三种模式拉流观看直播的流程

一、首先搭建直播服务器 环境widows&#xff0c;并且已经集成了 &#xff1a;nginx-http-flv-module模块 nginx.conf配置如下&#xff1a; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #error…

计算机人工智能前沿进展-大语言模型方向-2024-09-15

计算机人工智能前沿进展-大语言模型方向-2024-09-15 1. Towards the holistic design of alloys with large language models Z Pei, J Yin, J Neugebauer, A Jain - Nature Reviews Materials, 2024 利用大型语言模型实现合金的全面设计 摘要 文章讨论了大型语言模型在材料…

nginx服务器安装和部署代理

文章目录 Linux下面安装nginx nginx下载官网: [nginx: download](https://nginx.org/en/download.html) 使用yum命令安装gcc环境 yum install -y wget gcc-c pcre-devel zlib-devel openssl-devel//安装多个环境 wget gcc pcre-devel 支持正则表达式 zlib-devel提供了压缩和…

CleanClip vs 传统剪贴板:究竟谁更胜一筹?

在日常工作和生活中,复制粘贴可以说是我们使用最频繁的操作之一。传统的剪贴板功能虽然简单易用,但在功能性和效率上还有很大的提升空间。今天,我们就来比较一下新兴的剪贴板增强工具CleanClip与传统剪贴板,看看到底谁更胜一筹。 1. 剪贴历史管理 传统剪贴板只能存储最后一次…

Java项目实战II基于Java+Spring Boot+MySQL的图书管理系统的设计与实现 (源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在信息爆炸…

【图虫创意-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

用来用去还是用回了ueditor-Vue富文本编辑器二次扩展

用来用去还是用回了ueditor-Vue富文本编辑器二次扩展。我们使用用过UEditor、TinyMCE、CKEditor、wangEditor、Tiptap、Quill项目经历过多次富文本的编辑器的选型使用&#xff0c;发现现在新的富文本编辑总感觉还是没达到我们的要求&#xff0c;果然改回了ueditor。 UEditor 是…

PMP与CMMI:两种管理方法的对比

PMP与CMMI&#xff1a;两种管理方法的对比 PMP&#xff1a;专注于项目管理CMMI&#xff1a;组织过程改进的框架总结&#xff1a;互补而非替代 在现代企业管理中&#xff0c;项目管理和组织能力成熟度模型集成&#xff08;CMMI&#xff09;是两个经常被提及的概念。虽然它们都是…

java线程池编程示例

程序功能 这段代码展示了如何使用 Java 线程池 来并发执行多个任务。通过创建一个固定大小为 3 的线程池&#xff0c;程序提交了 5 个任务&#xff0c;并让线程池中的线程并发处理这些任务。每个任务模拟了一个耗时操作&#xff0c;最后程序等待所有任务完成后关闭线程池。 …

『功能项目』按G键持续显示对话内容【61】

本章项目成果展示 我们打开上一篇60靠近Npc显示可对话标识的项目&#xff0c; 本章要做的事情是当靠近Npc按G键显示内容后&#xff0c;再按G键实现两个人的对话显示功能 首先将以下资源图片放进Art文件夹中并设置为精灵模式 在桌面上创建一个文本 讲一下对话内容复制到文本中 …