C++实现简单五子棋游戏

 更新时间:2020年5月23日 09:40  点击:1839

五子棋是世界智力运动会竞技项目之一,是一种两人对弈的纯策略型棋类游戏,是世界智力运动会竞技项目之一,通常双方分别使用黑白两色的棋子,下在棋盘直线与横线的交叉点上,先形成5子连线者获胜。

规则

(1)对局双方各执一色棋子。
(2)空棋盘开局。
(3)黑先、白后,交替下子,每次只能下一子。
(4)棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
(5)黑方的第一枚棋子可下在棋盘任意交叉点上。
(6)轮流下子是双方的权利,但允许任何一方放弃下子权(即:PASS权)

五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。黑方禁手有三三禁手、四四禁手和长连禁手三种。

实现方案

通过缩小棋盘来抑制五子棋先行的优势,在这里使用15路棋盘。

(1)提供3个选择模式

(2)输入坐标(注意横纵坐标之间需要空格)

(3)输入非法坐标

(4)判断输赢

  • 判断行是否满足条件
  • 判断列是否满足条件
  • 判断主对角线是否满足条件
  • 判断副对角线是否满足条件

之后可选择yes再来一局,也可以选择no退出游戏。

源代码如下:

#define _CRT_SECURE_NO_WARNINGS 1

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

using namespace std;

const int N = 15; //15*15的棋盘
const char ChessBoard = ' '; //棋盘标志
const char flag1 = 'o'; //玩家1或电脑标志
const char flag2 = 'x'; //玩家2标志

typedef struct Position{ //坐标
 int row; //行
 int col; //列
}Position;

class GoBang{ //五子棋类
public:
 GoBang(){
 InitChessBoard(); //初始化棋盘
 }
 void Play(){ //下棋
 Position Play1; //玩家1或电脑
 Position Play2; //玩家2
 while (1){
 int mode = ChoiceMode();
 while (1){
 if (mode == 1){ //电脑VS玩家
 ComputerChess(Play1, flag1); //电脑走
 if (GetVictory(Play1, 0, flag1)){ //0代表电脑,为真则表示电脑获胜
 break;
 }
 PlayChess(Play2, 2, flag2); //玩家2走
 if (GetVictory(Play2, 2, flag2)){ //2代表玩家2
 break;
 }
 }
 else{ //玩家1VS玩家2
 PlayChess(Play1, 1, flag1); //玩家1走
 if (GetVictory(Play1, 1, flag1)){ //玩家1赢
 break;
 }
 PlayChess(Play2, 2, flag2); //玩家2走
 if (GetVictory(Play2, 2, flag2)){ //玩家2赢
 break;
 }
 }
 }
 cout << "======再来一局=======" << endl;
 cout << "yes or no :"; 
 char s[] = "yes";
 cin >> s;
 if (strcmp(s, "no") == 0){
 break;
 }
 }
 }

protected:
 void InitChessBoard(){ //初始化棋盘
 for (int i = 0; i < N + 1; ++i){
 for (int j = 0; j < N + 1; ++j){
 _ChessBoard[i][j] = ChessBoard;
 }
 }
 }

 int ChoiceMode(){ //选择模式
 system("cls");
 //系统调用,清屏
 InitChessBoard(); //重新初始化棋盘
 cout << "*************************************************" << endl;
 cout << "******************0、退出************************" << endl;
 cout << "******************1、电脑VS玩家******************" << endl;
 cout << "******************2、玩家VS玩家******************" << endl;
 cout << "*************************************************" << endl;
 while (1){
 int i = 0;
 cout << "请选择模式:";
 cin >> i;
 if (i == 0){ //退出
 exit(1);
 }
 if (i == 1 || i == 2){
 return i;
 }
 else{
 cout << "非法输入,请重新输入!" << endl;
 }
 }
 }

 void PrintChessBoard(){ //打印棋盘
 printf(" 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n");
 printf(" |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|\n");
 for (int i = 1; i < N + 1; ++i)
 {
 printf("%2d ", i);
 printf("| %c | %c | %c | %c | %c | %c | %c | %c | %c | %c | %c | %c | %c | %c | %c |\n", _ChessBoard[i][1], _ChessBoard[i][2], _ChessBoard[i][3], _ChessBoard[i][4], _ChessBoard[i][5], _ChessBoard[i][6], _ChessBoard[i][7], _ChessBoard[i][8], _ChessBoard[i][9], _ChessBoard[i][10], _ChessBoard[i][11], _ChessBoard[i][12], _ChessBoard[i][13], _ChessBoard[i][14], _ChessBoard[i][15]);
 printf(" |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|\n");
 }
 cout << endl;
 }

 void ComputerChess(Position& pos, char flag){ //电脑走
 //PrintChessBoard(); //打印棋盘
 int x = 0;
 int y = 0;
 while (1){ //循环查找空位置
 x = (rand() % N) + 1; //产生从1~N的随机数
 srand((unsigned int)time(NULL));
 y = (rand() % N) + 1; //产生从1~N的随机数
 srand((unsigned int)time(NULL));
 if (_ChessBoard[x][y] == ChessBoard){ //如果这个位置为空(没有棋子),跳出循环,下棋
 break;
 }
 }
 pos.row = x;
 pos.col = y;
 _ChessBoard[pos.row][pos.col] = flag;
 }

 void PlayChess(Position& pos, int player, char flag){
 PrintChessBoard(); //打印棋盘
 while (1){
 printf("请玩家%d输入坐标:", player);
 cin >> pos.row >> pos.col;
 if (JudgeValue(pos) == 1){ //判断坐标是否合法
 break;
 }
 cout << "坐标不合法,请重新输入:" << endl;
 }
 _ChessBoard[pos.row][pos.col] = flag;
 }

 int JudgeValue(const Position& pos){ //判断坐标的合法性
 //1.在棋盘上
 if (pos.row > 0 && pos.row <= N && pos.col > 0 && pos.col <= N){
 //2.所在位置为空(没有棋子)
 if (_ChessBoard[pos.row][pos.col] == ChessBoard){
 return 1; //合法
 } 
 }
 return 0; //非法
 }

 int JudgeVictory(Position pos, char flag){ //判断是否有玩家获胜(底层判断)
 int begin = 0;
 int end = 0;

 //1.判断行是否满足条件
 (pos.col - 4) > 0 ? begin = (pos.col - 4) : begin = 1;
 (pos.col + 4) > N ? end = N : end = (pos.col + 4);
 for (int i = pos.row, j = begin; j + 4 <= end; ++j){
 if (_ChessBoard[i][j] == flag && _ChessBoard[i][j + 1] == flag &&
 _ChessBoard[i][j + 2] == flag && _ChessBoard[i][j + 3] == flag &&
 _ChessBoard[i][j + 4] == flag)
 return 1;
 }
 //2.判断列是否满足条件
 (pos.row - 4) > 0 ? begin = (pos.row - 4) : begin = 1;
 (pos.row + 4) > N ? end = N : end = (pos.row + 4);
 for (int j = pos.col, i = begin ; i + 4 <= end; ++i){
 if (_ChessBoard[i][j] == flag && _ChessBoard[i + 1][j] == flag &&
 _ChessBoard[i + 2][j] == flag && _ChessBoard[i + 3][j] == flag &&
 _ChessBoard[i + 4][j] == flag)
 return 1;
 }
 //3.判断主对角线是否满足条件
 int len = 0; //相对长度
 int start = 0;
 int finish = 0;
 pos.row > pos.col ? len = pos.col - 1 : len = pos.row - 1;
 if (len > 4){
 len = 4;
 }
 begin = pos.row - len; //横坐标起始位置
 start = pos.col - len; //纵坐标起始位置

 pos.row > pos.col ? len = N - pos.row : len = N - pos.col;
 if (len > 4){
 len = 4;
 }
 end = pos.row + len; //横坐标结束位置
 finish = pos.col + len; //纵坐标结束位置

 for (int i = begin, j = start; (i + 4 <= end) && (j + 4 <= finish); ++i, ++j){
 if (_ChessBoard[i][j] == flag && _ChessBoard[i + 1][j + 1] == flag &&
 _ChessBoard[i + 2][j + 2] == flag && _ChessBoard[i + 3][j + 3] == flag &&
 _ChessBoard[i + 4][j + 4] == flag)
 return 1;
 }
 //4.判断副对角线是否满足条件
 (pos.row - 1) > (N - pos.col) ? len = N - pos.col : len = pos.row - 1;
 if (len > 4){
 len = 4;
 }
 begin = pos.row - len; //横坐标起始位置
 start = pos.col + len; //纵坐标起始位置

 (N - pos.row) > (pos.col - 1) ? len = pos.col - 1 : len = N - pos.row;
 if (len > 4){
 len = 4;
 }
 end = pos.row + len; //横坐标结束位置
 finish = pos.col - len; //纵坐标结束位置 
 for (int i = begin, j = start; (i + 4 <= end) && (j - 4 >= finish); ++i, --j){
 if (_ChessBoard[i][j] == flag && _ChessBoard[i + 1][j - 1] == flag &&
 _ChessBoard[i + 2][j - 2] == flag && _ChessBoard[i + 3][j - 3] == flag &&
 _ChessBoard[i + 4][j - 4] == flag)
 return 1;
 }
 //该位置并未下棋
 for (int x = 1; x < N + 1; ++x){
 for (int y = 1; y < N + 1; ++y){
 if (_ChessBoard[x][y] == ChessBoard){
 return 0; //未下棋
 }
 }
 }
 return -1; //和局
 }

 bool GetVictory(Position& pos, int player, char flag){ //判断具体哪位玩家赢
 if (JudgeVictory(pos, flag) != 0){ //判断有无人获胜
 if (JudgeVictory(pos, flag) == 1){ //判断是否有人获胜,1表示获胜
 PrintChessBoard(); //打印棋盘
 if (player == 0){
 cout << "电脑获胜!" << endl;
 }
 else{
 printf("恭喜玩家%d获胜!\n", player);
 }
 }
 else{
 printf("和局!\n");
 }
 return true; //有人获胜
 } 
 return false; //没人获胜
 }

private:
 char _ChessBoard[N + 1][N + 1]; //棋盘
};

int main(){
 GoBang g;
 g.Play();
 system("pause");
 return 0;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持猪先飞。

[!--infotagslink--]

相关文章

  • C++ STL标准库std::vector的使用详解

    vector是表示可以改变大小的数组的序列容器,本文主要介绍了C++STL标准库std::vector的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2022-03-06
  • C++中取余运算的实现

    这篇文章主要介绍了C++中取余运算的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ string常用截取字符串方法

    这篇文章主要介绍了C++ string常用截取字符串方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++调用C#的DLL程序实现方法

    本文通过例子,讲述了C++调用C#的DLL程序的方法,作出了以下总结,下面就让我们一起来学习吧。...2020-06-25
  • C++中四种加密算法之AES源代码

    本篇文章主要介绍了C++中四种加密算法之AES源代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。...2020-04-25
  • C++ 整数拆分方法详解

    整数拆分,指把一个整数分解成若干个整数的和。本文重点给大家介绍C++ 整数拆分方法详解,非常不错,感兴趣的朋友一起学习吧...2020-04-25
  • C++中 Sort函数详细解析

    这篇文章主要介绍了C++中Sort函数详细解析,sort函数是algorithm库下的一个函数,sort函数是不稳定的,即大小相同的元素在排序后相对顺序可能发生改变...2022-08-18
  • C++万能库头文件在vs中的安装步骤(图文)

    这篇文章主要介绍了C++万能库头文件在vs中的安装步骤(图文),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-02-23
  • 详解C++ bitset用法

    这篇文章主要介绍了C++ bitset用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 浅谈C++中的string 类型占几个字节

    本篇文章小编并不是为大家讲解string类型的用法,而是讲解我个人比较好奇的问题,就是string 类型占几个字节...2020-04-25
  • C++ Eigen库计算矩阵特征值及特征向量

    这篇文章主要为大家详细介绍了C++ Eigen库计算矩阵特征值及特征向量,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-04-25
  • VSCode C++多文件编译的简单使用方法

    这篇文章主要介绍了VSCode C++多文件编译的简单使用方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-03-29
  • C++ pair的用法实例详解

    这篇文章主要介绍了C++ pair的用法实例详解的相关资料,需要的朋友可以参考下...2020-04-25
  • C++中的循环引用

    虽然C++11引入了智能指针的,但是开发人员在与内存的斗争问题上并没有解放,如果我门实用不当仍然有内存泄漏问题,其中智能指针的循环引用缺陷是最大的问题。下面通过实例代码给大家介绍c++中的循环引用,一起看看吧...2020-04-25
  • C++随机点名生成器实例代码(老师们的福音!)

    这篇文章主要给大家介绍了关于C++随机点名生成器的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • C++如何删除map容器中指定值的元素详解

    map容器是C++ STL中的重要一员,删除map容器中value为指定元素的问题是我们经常与遇到的一个问题,下面这篇文章主要给大家介绍了关于利用C++如何删除map容器中指定值的元素的相关资料,需要的朋友可以参考借鉴,下面来一起看看吧。...2020-04-25
  • C++ 约瑟夫环问题案例详解

    这篇文章主要介绍了C++ 约瑟夫环问题案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...2021-08-15
  • C++中cin的用法详细

    这篇文章主要介绍了C++中cin的用法详细,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25
  • 基于C++中常见编译错误的总结详解

    本篇文章是对C++中的常见编译错误进行了详细的分析介绍,需要的朋友参考下...2020-04-25
  • c++优先队列(priority_queue)用法详解

    这篇文章主要介绍了c++优先队列(priority_queue)用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-04-25