【问题标题】:Simple Console Chess Game简单的控制台国际象棋游戏
【发布时间】:2017-11-30 05:03:46
【问题描述】:

我目前正在开发一款小型 C++ 控制台游戏。我遇到的第一个问题是棋盘显示不好(字符串 8x8 数组)。但首先,让我给你做个简短的介绍。

我的想法是将每个国际象棋人物视为一个对象 - 因此白色和黑色都有自己的实例 - 对于典当它是 16 个实例(白色和黑色相等 8 个),对于车它是 4 个,等等。 .

然后我创建了另一个类,称为ChessBoard,它存储诸如被杀数字、特定玩家的结果等信息,并用于监督其他类。最重要的是,它存储了上面提到的字符串数组,其中包含每个图形的图形表示(std::string pic 行)。现在,回到问题:当我尝试打印出这个数组以检查它的完整性和顺序时,它显示它的所有单元格都是垂直显示的。我想以这种方式显示它(P字段代表具体的数字,一个空字段位于下方):

***** ***** ***** ***** ***** ***** ***** *****
* P * * P * * P * * P * * P * * P * * P * * P *
***** ***** ***** ***** ***** ***** ***** *****
----- ----- ----- ----- ----- ----- ----- -----
|   | |   | |   | |   | |   | |   | |   | |   |
----- ----- ----- ----- ----- ----- ----- -----

这就是实际发生的情况:

我知道这个问题在这个网站上被提出了很多次,但是我尝试了其他用户给出的所有可能的解决方案,但它不起作用 - 唯一的区别是一些单一标志的位置,但整体阵列的显示是还是很糟糕。

项目的依赖:

BoardLogic.h -> BoardComponents.h

ma​​in.cpp -> BoardLogic.cpp -> BoardComponents.cpp

我会给你一个项目文件的小视图。 这是我工作的一个开始,所以我只投射了 Pawn 的实例并尝试在板上正确显示它们。

BoardComponents.h

#ifndef BOARDCOMPONENTS_H_
#define BOARDCOMPONENTS_H_
#include "BoardLogic.h"
#include <string>

class Pawn {
public:
    bool isAlive;
    std::string pic = "*****\n* P *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    Pawn::currentPosition pPos;
private:

};

class Rook {
public:
    bool isAlive;
    std::string pic = "*****\n* R *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    Rook::currentPosition rPos;
private:

};

class Knight {
public:
    bool isAlive;
    std::string pic = "*****\n* k *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    Knight::currentPosition kPos;
private:

};

class Bishop {
public:
    bool isAlive;
    std::string pic = "*****\n* B *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    Bishop::currentPosition bPos;
private:

};

class Queen {
public:
    bool isAlive;
    std::string pic = "*****\n* Q *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    Queen::currentPosition qPos;
private:

};

class King {
public:
    bool isAlive;
    std::string pic = "*****\n* K *\n*****";
    struct currentPosition {
        int x;
        int y;
    };
    King::currentPosition kingPos;
private:

};

class ChessBoard {
public:
    std::string chessBoard[8][8];
    int wChessKilled;
    int bChessKilled;
    int wPlayerResult;
    int bPlayerResult;
    bool winner;
private:

};

#endif

BoardLogic.cpp - 此文件创建游戏的新实例及其组件类

#include "BoardLogic.h"
#include "BoardComponents.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

void ChessGame::NewGameInstance() {

    ChessBoard * cBoard = new ChessBoard;
    Pawn * wPawn = new Pawn[8];
    Pawn * bPawn = new Pawn[8];
    Rook * wRook = new Rook[2];
    Rook * bRook = new Rook[2];
    Knight * wKnight = new Knight[2];
    Knight * bKnight = new Knight[2];
    Bishop *wBishop = new Bishop[2];
    Bishop *bBishop = new Bishop[2];
    Queen *wQueen = new Queen;
    Queen *bQueen = new Queen;
    King * wKing = new King;
    King *bKing = new King;

    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            cBoard->chessBoard[i][j] = "-----\n|   |\n-----";
        }
    }

    for (int i = 0; i < 8; i++) {
        wPawn[i].pPos.x = i;
        wPawn[i].pPos.y = 1;
        bPawn[i].pPos.x = i;
        bPawn[i].pPos.y = 6;
        wPawn[i].isAlive = true;
        bPawn[i].isAlive = true;
        cBoard->chessBoard[wPawn[i].pPos.x][wPawn[i].pPos.y] = wPawn[i].pic;
        cBoard->chessBoard[bPawn[i].pPos.x][bPawn[i].pPos.y] = bPawn[i].pic;
    }

    for (int i = 0; i < 8; i++) {
        for (int j = 7; j >= 0; j--) {
            cout << cBoard->chessBoard[i][j];
        }
    }

【问题讨论】:

  • 有点跑题了,但是您是否考虑过将您的国际象棋游戏分成两个不同的部分? IE。引擎和用户界面?有标准的国际象棋协议允许您的引擎与其他用户界面一起工作,而其他引擎也可以与您的 ui 一起工作。您甚至可以让您的引擎与另一个引擎对战。 en.wikipedia.org/wiki/Chess_engine
  • 当然,但是由于我想学习一些更高级的编程技术,我真的很想从头开始创建它。是的,我想拆分程序,这就是我使用这个班级系统的原因。最终,文件“BoardComponents”将存储棋盘的所有元素(棋子等)及其统计数据,而“BoardLogic”将处理游戏中的事件、规则等。这种解决方案并不特别,它是只是一种自我保护的本能:P

标签: c++ arrays multidimensional-array chess


【解决方案1】:

您的ChessBoard 必须具有行的概念,并且必须先呈现该行中的所有项目,然后才能进入下一行。字符串集合并不理想。

在渲染中使用“\n”是个问题。您需要绘制该行中项目的所有“第一行”,然后绘制所有第二行,依此类推。解决这个问题的简单方法至少是为每件作品使用一个字符:'K','Q' ...'p'。

别忘了你还需要为每一行的空位绘制“一些东西”(空格)。

【讨论】:

  • 感谢您的建议,我也怀疑这种情况。稍后我会仔细研究它。编辑。如果我理解正确,我应该为每个对象的表示(棋子、车、空单元格等)创建一个 char 数组,然后将它们全部合并到一个巨大的实体中(在这种情况下为棋盘)?跨度>
【解决方案2】:

您可以做的是拥有一个 2D 字符数组 (31 * 47)。由于每个网格都是 3x5 数组,因此棋盘的宽度为 5 * 8 + 7(中间有间隙)。高度为 3 * 8 + 7。

当你想打印棋盘时,你从棋子中取出图片,将它分成 3 行,然后将它相应地放在 2D 字符数组上。当你把棋子放在棋盘上后,你就可以把整个二维数组放在 1 go 中了。

关于如何将 3x5 阵列放置到板阵列上的一个示例:

//row and col are physical position on the board, both ranging from 0 to 7
void PlaceOnBoard(char[][47] board, char[][5] pattern, int row, int col)
{
    int start_row = row * 4;
    int start_col = col * 6;
    for (int i = 0; i < 3; ++i)
        for (int j = 0; j < 5; ++j)
            board[start_row + i][start_col + j] = pattern[i][j];

}

另一种选择是每次在棋盘上打印出一行时,您会进行 3 次迭代,第一次迭代将打印每个棋子的第一行,第二次迭代将打印第二行...

【讨论】:

  • 这就是我已经完成的 - 现在,每个数字(以及空单元格)都有一个带有“图形”表示的 char[3][5] 数组,我目前尝试注入进入更大的 char[32][48] 数组,这非常困难,因为我不知道如何成功嵌套 for 循环(一个用于填充主“板”数组,一个用于特定对象)。
  • 添加一个如何将棋子从物理坐标映射到棋盘坐标的示例
  • 是的,它肯定越来越近了。现在我需要将其调整为我现有的代码。您的示例的唯一问题是我不能将它与我的目标数组递归使用,因为它们是在另一个函数中强制转换的。这是顺便说一句。我在处理结构和数组时经常遇到的最大问题——我不知道如何处理从另一个函数访问在一个函数中创建的对象/结构/数组的问题)——在大多数情况下,使用“return”语句是不合适的由于其性质/数据类型而引起的问题。
  • 如果数组是在另一个函数中创建的,有两种选择: (1) 将其创建为 std::array 或 std::vector 并返回对象。 (2) 使用指针以动态方式创建它并仅返回指针。老实说,您应该在棋盘类中保存大字符数组,并且只允许通过您的公共方法进行修改,从同一类中的方法访问变量应该非常容易,您也不必传递数组。
  • 顺便说一句,在我的示例中,数组来自调用者,因此调用者访问它应该没有任何问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 2016-04-04
  • 1970-01-01
  • 2015-05-02
  • 2015-07-16
相关资源
最近更新 更多