用c++实现五子棋小游戏

五子棋是一款经典小游戏,今天我们就用c++实现简单的五子棋小游戏

目录

用到的算法:

思路分析

定义变量 

开始写代码

 

完整代码 

结果图:


用到的算法:

  1. 合法移动的判断:isValidMove 函数通过检查指定位置是否在棋盘范围内,并且该位置是否为空位来确定是否为合法的移动。

  2. 获胜条件的检查:checkWin 函数通过遍历四个方向(水平、垂直、两个对角线)来检查是否存在连续的五个相同类型的棋子。它使用两个 while 循环,一个向一个方向移动,另一个向相反方向移动,以统计横向、纵向和对角线上相同类型棋子的数量。

  3. 棋盘状态的打印:printBoard 函数使用嵌套的 for 循环来遍历棋盘的每个位置,并输出相应的符号来表示该位置的状态。

  4. 棋盘是否已满的检查:isBoardFull 函数使用嵌套的 for 循环来遍历棋盘的每个位置,检查是否存在空位。如果不存在空位,则棋盘已满

思路分析

  1. 初始化:创建一个空的棋盘,大小为15x15,用二维向量表示。初始时所有位置都是空位。

  2. 循环游戏:进入一个无限循环,在每一轮中依次执行以下步骤:

    • 打印当前棋盘状态;
    • 根据当前轮到的玩家,提示玩家输入下子位置;
    • 检查输入的下子位置是否合法,即在棋盘范围内且为空位,如果不合法则提示重新输入;
    • 在棋盘上下子,并判断是否获胜或棋盘已满;
    • 如果获胜或棋盘已满,根据情况打印相应的信息,并结束游戏。
  3. 判断获胜和棋盘是否已满:

    • 每次下子后,调用 checkWin 函数来检查当前位置是否连成五子,如果是则返回获胜;
    • 如果没有获胜,则调用 isBoardFull 函数来判断棋盘是否已满,如果棋盘已满则返回平局。
  4. 输出棋盘状态:

    • printBoard 函数使用嵌套的 for 循环遍历棋盘的每个位置,根据该位置的状态输出相应的符号,用于展示当前棋盘状态

定义变量 

  • BOARD_SIZE 定义了棋盘的大小,这里设置为15x15。
  • EMPTYBLACK 和 WHITE 定义了棋盘上的三种状态:空位、黑棋和白棋。
  • board 是一个二维向量,表示棋盘,初始时所有位置都是空位。
  • isValidMove 函数用于判断某个位置是否可以下子。合法的位置必须在棋盘范围内,并且为空位。
  • checkWin 函数用于判断某个位置下子后是否获胜。它检查当前位置在四个方向上(水平、垂直、两个对角线)是否有连续的连续的五个相同类型棋子。如果有则返回 true,否则返回 false。
  • printBoard 函数用于打印当前棋盘的状态。
  • isBoardFull 函数用于判断棋盘是否已经满了(即没有空位),如果棋盘已满,则返回 true,否则返回 false。
  • main 函数是程序的入口。它使用一个无限循环,每次循环轮流让玩家下子,然后判断是否游戏结束。如果有一方获胜或者棋盘已满,则打印相应的信息,并结束游戏。

开始写代码

void printBoard() {for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {cout << board[i][j] << " ";}cout << endl;}cout << endl;
}

 

这段代码为打印棋盘状态的函数printBoard(),使用了嵌套的循环来遍历棋盘,并输出每个位置的状态。

具体的实现逻辑如下:

  1. 外层循环for (int i = 0; i < BOARD_SIZE; i++)遍历棋盘的行数,从第一行开始到最后一行。
  2. 内层循环for (int j = 0; j < BOARD_SIZE; j++)遍历棋盘的列数,从第一列开始到最后一列。
  3. 在内层循环中,通过board[i][j]获取当前位置的状态值,并使用cout输出该状态值。
  4. 输出一个空格,以分隔不同位置的状态值。
  5. 内层循环结束后,通过cout << endl;输出换行符,以换行显示下一行的棋盘状态。
  6. 外层循环结束后,通过cout << endl;再次输出一个换行符,以在棋盘状态的输出之间添加空行。

这样,调用printBoard()函数可以按照指定格式输出当前棋盘的状态。每个位置上的状态值可以是空格、X或O等字符,表示空位、玩家1和玩家2的棋子。通过这个函数,可以直观地展示游戏棋盘的状态给玩家。

bool isValidMove(int row, int col) {return (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE && board[row][col] == EMPTY);
}

 

这段代码是用于判断玩家落子是否合法的函数isValidMove(row, col),其中rowcol分别表示玩家输入的坐标值。

具体的实现逻辑如下:

  1. 首先,通过row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE判断玩家输入的坐标值是否在棋盘范围内。如果超出了棋盘范围,则此次落子不合法。
  2. 否则,通过board[row][col] == EMPTY判断该位置是否已有棋子(即状态值是否为EMPTY)。如果该位置上没有棋子,则此次落子合法,返回true
  3. 如果该位置上已经有棋子,则此次落子不合法,返回false

通过这个函数,可以快速判断玩家输入的坐标是否合法。如果不合法,则需要提示玩家重新输入坐标;如果合法,则可以继续进行游戏。

 


bool checkWin(int row, int col, char player) {int directions[4][2] = {{1, 0}, {0, 1}, {1, 1}, {-1, 1}};for (int i = 0; i < 4; i++) {int count = 1;int dx = directions[i][0], dy = directions[i][1];int r = row + dx, c = col + dy;while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] == player) {count++;r += dx;c += dy;}dx = -dx, dy = -dy;r = row + dx, c = col + dy;while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] == player) {count++;r += dx;c += dy;}if (count >= 5)return true;}return false;
}

 

这段代码是用于检查玩家是否取得胜利的函数checkWin(row, col, player),其中rowcol表示最后一次落子的坐标,player表示当前玩家的符号。

具体的实现逻辑如下:

  1. 首先,定义一个二维数组directions[4][2]来表示四个方向,分别为向下、向右、右下、左下。每个方向由两个元素组成,分别表示在行方向和列方向上的增量。
  2. 使用一个循环遍历四个方向。
  3. 在循环内部,初始化一个计数器count为1,表示已经有一颗当前玩家的棋子。
  4. 根据当前方向的增量(dx, dy),计算下一个检查的位置(r, c),并检查该位置是否在棋盘范围内且值等于当前玩家的符号。
  5. 如果满足条件,将计数器count加1,并更新下一个位置(r, c)为当前位置加上增量(dx, dy)
  6. 重复步骤4和步骤5,直到碰到越界或者不是当前玩家的棋子。
  7. 然后,将增量(dx, dy)取相反数,即改变方向。
  8. 再次计算下一个检查的位置(r, c),并检查该位置是否在棋盘范围内且值等于当前玩家的符号。
  9. 如果满足条件,将计数器count加1,并更新下一个位置(r, c)为当前位置加上增量(dx, dy)
  10. 重复步骤8和步骤9,直到碰到越界或者不是当前玩家的棋子。
  11. 检查计数器count是否大于等于5,如果是,则表示当前玩家在其中一个方向上取得了胜利,返回true
  12. 如果四个方向都遍历完毕,仍未满足取胜条件,则返回false

通过这个函数,可以判断当前玩家是否在最后一次落子后取得了胜利。根据游戏规则,只有当任意一方在横、竖、斜对角线方向上连续五个棋子时才算获胜。

完整代码 

#include <iostream>
#include <vector>using namespace std;const int BOARD_SIZE = 15;
const char EMPTY = '-';
const char BLACK = 'X';
const char WHITE = 'O';vector<vector<char> > board(BOARD_SIZE, vector<char>(BOARD_SIZE, EMPTY));bool isValidMove(int row, int col) {return (row >= 0 && row < BOARD_SIZE && col >= 0 && col < BOARD_SIZE && board[row][col] == EMPTY);
}bool checkWin(int row, int col, char player) {int directions[4][2] = {{1, 0}, {0, 1}, {1, 1}, {-1, 1}};for (int i = 0; i < 4; i++) {int count = 1;int dx = directions[i][0], dy = directions[i][1];int r = row + dx, c = col + dy;while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] == player) {count++;r += dx;c += dy;}dx = -dx, dy = -dy;r = row + dx, c = col + dy;while (r >= 0 && r < BOARD_SIZE && c >= 0 && c < BOARD_SIZE && board[r][c] == player) {count++;r += dx;c += dy;}if (count >= 5)return true;}return false;
}void printBoard() {for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {cout << board[i][j] << " ";}cout << endl;}cout << endl;
}bool isBoardFull() {for (int i = 0; i < BOARD_SIZE; i++) {for (int j = 0; j < BOARD_SIZE; j++) {if (board[i][j] == EMPTY)return false;}}return true;
}int main() {int row, col;char currentPlayer = BLACK;while (true) {printBoard();cout << "Player " << currentPlayer << ", enter your move (row col): ";cin >> row >> col;if (!isValidMove(row, col)) {cout << "Invalid move! Try again." << endl;continue;}board[row][col] = currentPlayer;if (checkWin(row, col, currentPlayer)) {cout << "Player " << currentPlayer << " wins!" << endl;break;} else if (isBoardFull()) {cout << "It's a draw!" << endl;break;}currentPlayer = (currentPlayer == BLACK) ? WHITE : BLACK;}printBoard();return 0;
}

 

在这个五子棋游戏代码中,可以通过以下方式进行输入和输出:

输入:

  1. 玩家输入下子位置:可以通过命令行提示玩家输入坐标,例如,要求玩家输入行和列的数字,表示下子位置的坐标。
  2. 其他玩家操作:例如,要求玩家输入指令来选择重新开始游戏或退出游戏。

输出:

  1. 打印当前棋盘状态:使用嵌套的循环遍历棋盘,根据棋盘上每个位置的状态输出相应的符号,可以使用空格、X和O等字符来表示空位、玩家1和玩家2的棋子。
  2. 提示玩家操作:例如,提示玩家输入坐标来下子,或者提示玩家输入指令以进行其他操作。
  3. 游戏结果输出:当游戏结束时,根据游戏结果输出胜利者或者平局信息。
  4. 错误提示:如果玩家输入了无效的指令或下子位置,可以输出错误提示信息,要求玩家重新输入。

在代码中,可以使用适当的输入函数,如input()来接收玩家输入,并使用适当的输出函数,如print()来输出信息到控制台。通过合理地组织输入和输出,可以实现与玩家的有效交互,并提供友好的游戏体验。

结果图:

如果想要更加华丽美观的代码,关注博主赞赏2元回复“五子棋华丽代码”即可。

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

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

相关文章

游戏视频录制软件对比,哪款最适合你的需求?

随着电子竞技和游戏直播行业的迅速崛起&#xff0c;越来越多的玩家渴望记录并分享自己在游戏中的精彩瞬间。游戏视频录制软件正是满足这一需求的关键工具。本文将针对三款优秀的游戏视频录制软件进行对比分析&#xff0c;以便为读者提供选购建议。 游戏视频录制软件1&#xff1…

十天学完基础数据结构-第一天(绪论)

1. 数据结构的研究内容 数据结构的研究主要包括以下核心内容和目标&#xff1a; 存储和组织数据&#xff1a;数据结构研究如何高效地存储和组织数据&#xff0c;以便于访问和操作。这包括了在内存或磁盘上的数据存储方式&#xff0c;如何将数据元素组织成有序或无序的集合&…

移动端H5封装一个 ScrollList 横向滚动列表组件,实现向左滑动

效果&#xff1a; 1.封装组件&#xff1a; <template><div class"scroll-list"><divclass"scroll-list-content":style"{ background, color, fontSize: size }"ref"scrollListContent"><div class"scroll…

C# OpenVino Yolov8 Pose 姿态识别

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenVino_Yolov8_Demo {public…

独立开发了一款Material3风格的RSS阅读器 - Agr Reader

截图 背景&#x1f4d6; 在之前接触到RSS后&#xff0c;发现RSS真是一个十分不错的信息聚合的方式&#xff0c;虽然现在看来RSS的时代已经开始落幕&#xff0c;但是至少目前还是处于能用的阶段。 在我用了Android上好几个RSS阅读App后&#xff0c;发现很多在全文解析方面不是…

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染&#xff0c;动态轨迹播放&#xff0c;自定义图形以及轨迹上显示箭头方向 1. 效果图2. 源码2.1 line.html2.2line_arrow.html 参考 今天要排查个问题&#xff0c;需要显示多个经纬度点连接成线段的方向&#xff0c;于是尝试下展示。 1. mapbox渲染经…

element plus封装el-select添加后缀图标并添加远程搜索和对话框功能

当提交的表单Form需要填某个实体的外键ID时&#xff0c;当然不可能使用el-input组件&#xff0c;这个适合提交字符串&#xff0c;然后用户又不可能记住某个引用的外键ID&#xff0c;这时候使用el-select还是必要的。 el-select组件一般都作为下拉选择框使用&#xff0c;但仅在…

远程计算机控制软件

远程控制软件允许您连接和控制位于不同位置的设备&#xff0c;对于 IT 帮助台技术人员来说&#xff0c;这是一个很好的工具&#xff0c;可以通过与用户协作、与他们聊天以及安全地访问他们的文件来轻松排除故障和修复远程设备。使用远程控制软件&#xff0c;距离不再是提供技术…

无涯教程-JavaScript - ATAN函数

描述 The ATAN function returns the arctangent, or inverse tangent, of a number. The returned angle is given in radians between -π/2 and π/2. The arctangent is the angle whose tangent is number. 语法 ATAN (number)争论 Argument描述Required/OptionalNumb…

Vulnhub实战-prime1

前言 VulnHub 是一个面向信息安全爱好者和专业人士的虚拟机&#xff08;VM&#xff09;漏洞测试平台。它提供了一系列特制的漏洞测试虚拟机镜像&#xff0c;供用户通过攻击和漏洞利用的练习来提升自己的安全技能。本次&#xff0c;我们本次测试的是prime1。 一、主机发现和端…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

【机器学习】文本多分类

声明&#xff1a;这只是浅显的一个小试验&#xff0c;且借助了AI。使用的是jupyter notebook,所以代码是一块一块&#xff0c;从上往下执行的 知识点&#xff1a;正则删除除数字和字母外的所有字符、高频词云、混淆矩阵 参考&#xff1a;使用python和sklearn的中文文本多分类…

DS相关题目

DS相关题目 题目一&#xff1a;消失的数字 拿到这道题目之后&#xff0c;首先可以想到的一个解题方法就是&#xff0c;我们可以先排序&#xff0c;排完序之后&#xff0c;这个数组其实就是一个有序的数组了&#xff0c;那只用比较数组中的每一个元素和他对应的下标是不是相等的…

代码管理工具git1

ctrl 加滚轮 放大字体 在计算机任意位置单击右键&#xff0c;选择&#xff1a;&#xff1a;Git Bash Here git version git清屏命令&#xff1a;ctrl L查看用户名和邮箱地址&#xff1a; $ git config user.name$ git config user.email修改用户名和邮箱地址&#xff1a;$ git…

C#中Visual Studio如何为解决方案设置启动项目

目录 第一种方法:快速选定启动项目的方法1.在解决方案资源管理器中,选择解决方案(最高层节点)2.选择解决方案节点的上下文(右键单击)菜单,然后选择“属性”。 “解决方案属性页”对话框随即显示第二种方法:右击First11或者second11,点击设置启动项目即可Visual Studio…

C#使用DirectX SDK 加载.x三维模型

最近因为项目要做显示一个三维模型&#xff0c;所以研究了下如何在Winform中加载并显示三维模型。在Windows平台巨硬公司提供了DirectX SDK用于渲染图形&#xff0c;参考了几篇文章做了个demo记录下&#xff0c;以便日后温习只用。这个SDK涉及到了计算机图形学的一些基础知识&a…

【物联网】简要解释RTK(Real-Time Kinematic)>>实时动态差分定位

引言&#xff1a; RTK&#xff08;Real-Time Kinematic&#xff09;技术是一种基于差分GPS的高精度定位技术&#xff0c;它通过实时通信和数据处理&#xff0c;能够提供厘米级甚至亚米级的定位精度。RTK技术在许多领域都得到了广泛应用&#xff0c;如测绘、航空航天、农业等。本…

Springboot -- DOCX转PDF(二)

之前记录了按照模板生成 DOCX 文件、并转换为 PDF 文件的方法 https://blog.csdn.net/qq_40096897/article/details/131979177?spm1001.2014.3001.5501 但是使用效果并不是很理想&#xff0c;转换完的 PDF 格式和原本的文档格式不匹配。所以在此重新找了一个文件转 PDF 的方法…

职场工作与生活

序言&#xff1a; 和很多在CSDN的博主一样&#xff0c;大家在工作之后就很少或者是不再回到CSDN&#xff0c;确实自己也一年多没上了。因为可能当初大家在这就是为了记录和分享当初自己学习技术的东西。而大家走出象牙塔开始工作后&#xff0c;发生了很大的转变。在国内…

PY32F003F18之输入捕获

输入捕获是定时器的功能之一&#xff0c;配合外部引脚&#xff0c;捕获脉宽时间或采集周期。 CPU中的定时器最基本的功能就是计数功能&#xff0c;其次是输入捕获(IC)&#xff0c;再次就是比较输出(OC)&#xff0c;还有就是使用引脚对外部时钟进行计数&#xff0c;触发信号捕捉…