我如何为我的国际象棋游戏代码添加快退按钮? C++

问题描述 投票:0回答:1

我正在用 C++ 做一个国际象棋小项目作为我的家庭作业。问题是我不知道如何复制我最后一步的动态数组(例如白棋做了一个非法的棋步,但有棋盘的副本,所以我倒回并白棋再次走)

这是我的程序的完整代码 。 。 .

#include <iostream>
#include <Windows.h>
#include <io.h>
#include <fcntl.h>
#include <string>
using namespace std;



wstring  board[8][8] = {
    L"\033[31m♜ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♚ \033[0m", L"\033[31m♛ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♜ \033[0m",
    L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ",
    L"♖ ", L"♘ ", L"♗ ", L"♔ ", L"♕ ", L"♗ ", L"♘ ", L"♖ "
};
wstring* backboard = &board[8][8];
void SaveBoard() {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
            backboard = &board[8][8];
        }
    }
}
void Back() {
    for (int i = 0; i < 8; i++) {
        for (int j = 0; j < 8; j++) {
             board[8][8] = *backboard;
        }
    }
}
// board printing
void printBoard() {
    wcout << L"   A B C D E F G H" << endl;
    for (int i = 0; i < 8; i++) {
        wcout << 8 - i << L" |";
        for (int j = 0; j < 8; j++) {
            wcout << board[i][j];
        }
        wcout << L"| " << 8 - i << endl;
    }
    wcout << L"   A B C D E F G H" << endl;
}


// Moving 
bool movePiece(string from, string to) {
    
    int fromX = from[0] - 'A';    
    int fromY = 8 - (from[1] - '0'); 
    int toX = to[0] - 'A';
    int toY = 8 - (to[1] - '0');

    
    if (fromX < 0 || fromX >= 8 || fromY < 0 || fromY >= 8 || toX < 0 || toX >= 8 || toY < 0 || toY >= 8) {
        wcout << L"Wrong coordinates!" << endl;
        return false;
    }

    wstring piece = board[fromY][fromX];

    SaveBoard();

    board[toY][toX] = piece;
    board[fromY][fromX] = L"  ";

    return true;
}


int main() {
    _setmode(_fileno(stdout), _O_U16TEXT); // Setting for Unicode symbols
    SetConsoleCP(1251);     // u don`t need this since i translated everything
    SetConsoleOutputCP(1251);
    SetConsoleMode;
    ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    string from, to;

    while (true) {
        printBoard();

        wcout << L"Move piece or use back/exit: ";
        cin >> from;

        if (from == "exit") break;
        if (from == "back") {
            Back();
            wcout << L"Returned." << endl;
            continue;
        
        }
        else {
            wcout << L"Not Returned. Try again." << endl;
        }
        cin >> to;

        if (!movePiece(from, to)) {
            wcout << L"Move didn`t work. Try again." << endl;
        }
    }

    return 0;
}

我想要的 - 在棋盘内移动棋子(每个棋子都可以移动到他们想要的任何地方)和倒带命令将游戏返回到上一个棋步。

如果有什么令人困惑的地方,我很抱歉,但这是我的第一篇溢出帖子,我不是英语专业的

我尝试使用阵列,但我碰巧处理的是在板退后就消失了,所有的空白空间和碎片

wstring  board[8][8] = {
    L"\033[31m♜ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♚ \033[0m", L"\033[31m♛ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♜ \033[0m",
    L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ",
    L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ",
    L"♖ ", L"♘ ", L"♗ ", L"♔ ", L"♕ ", L"♗ ", L"♘ ", L"♖ "
};

所以这就是板子,我必须为项目添加颜色,这导致了使用“后退”时整个板子消失的问题。我很确定我已经修复了它

SetConsoleMode;
ENABLE_VIRTUAL_TERMINAL_PROCESSING;
c++ chess
1个回答
0
投票

首先,我建议你将

wstring[8][8]
放在处理单板的类中,我们称之为
Board
,然后添加一些函数来访问数组。当您这样做时,您可以使用
std::array<std::array<std::wstring, 8>, 8>
来获取一些可能会派上用场的成员函数。

示例:

#include <array>
#include <iostream>
#include <string>
#include <utility>

class Board {
public:
    using row_type = std::array<std::wstring, 8>;
    using board_type = std::array<row_type, 8>;

    Board() = default;
    Board(board_type&& init) : m_data(std::move(init)) {}

    row_type& operator[](std::size_t Y) { // add const qualified if needed
        return m_data[Y];
    }

    std::size_t size() const { return m_data.size(); }

    void print(std::wostream& os = std::wcout) const {
        os << L"   A B C D E F G H\n";
        for (std::size_t i = 0; i < size(); i++) {
            os << size() - i << L" |";
            for (auto& str : m_data[i]) {
                os << str;
            }
            os << L"| " << size() - i << L'\n';
        }
        os << L"   A B C D E F G H\n";
    }

private:
    board_type m_data{};
};

这为您提供了一个带有下标运算符的

Board
类型,用于访问二维数组中的元素,一个
size
函数和一个默认打印到屏幕的
print
函数。

对于实际问题:

为了返回,您可以

push()
每个
Board
std::stack
。如果您需要后退一步,请复制堆栈中
top()
上的内容,然后从堆栈中复制
pop()
中的该元素。然而,出于这个目的,我发现使用
std::vector
移动很方便,因为如果我们想将游戏重置为初始状态和其他一些东西,它可以
resize()
本身。

我将您的原始函数放在一个名为

Chess
的类中,以向用户隐藏
SaveBoard()
等实现细节。实例化时,它将把
static
initial_board
复制到非
static
成员变量
m_boards
,这是我们的
std::vector<Board>
,它将充当堆栈。
initial_board
将是该堆栈中的第一块板。

#include <cctype>
#include <string>
#include <stack>

class Chess {
    inline static const Board initial_board{{{
        {L"\033[31m♜ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♚ \033[0m", L"\033[31m♛ \033[0m", L"\033[31m♝ \033[0m", L"\033[31m♞ \033[0m", L"\033[31m♜ \033[0m"},
        {L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m", L"\033[31m♙ \033[0m"},
        {L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  "},
        {L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  "},
        {L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  "},
        {L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  ", L"  "},
        {L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ ", L"♙ "},
        {L"♖ ", L"♘ ", L"♗ ", L"♔ ", L"♕ ", L"♗ ", L"♘ ", L"♖ "}
    }}};

public:
    Chess() : m_boards{ initial_board } {} // put the initial board on the stack

    void Reset() {
        m_boards.resize(1); // remove all but the initial board
    }

    std::size_t getMoveNumber() const {
        return m_boards.size();
    }

    bool Back() {
        // if there's only the initial board on the stack, don't do anything
        if (m_boards.size() == 1) return false;
        m_boards.pop_back(); // remove last Board
        return true;
    }

    // accessors to the current Board:
    Board& getBoard() { return m_boards.back(); }
    const Board& getBoard() const { return m_boards.back(); }

    void printBoard() const {
        getBoard().print();
    }

    bool movePiece(std::string from, std::string to) {
        // check that positions have exactly 2 chars each
        if (from.size() != 2 || to.size() != 2) return false;

        std::size_t fromX = std::toupper(static_cast<unsigned char>(from[0])) - 'A';
        std::size_t fromY = 8 - (from[1] - '0');
        std::size_t toX = std::toupper(static_cast<unsigned char>(to[0])) - 'A';
        std::size_t toY = 8 - (to[1] - '0');

        if(fromX >= 8 || fromY >= 8 || toX >= 8 || toY >= 8) {
            std::wcout << L"Wrong coordinates!\n";
            return false;
        }
        
        SaveBoard();

        auto& board = getBoard();
        board[toY][toX] = board[fromY][fromX];
        board[fromY][fromX] = L"  ";

        return true;
    }

private:
    void SaveBoard() {
        m_boards.push_back(m_boards.back());
    }

    std::vector<Board> m_boards;
};

如您所见,当您现在调用

Back()
时,它只会删除放入堆栈中的最后一个条目(如果有要从中删除的条目)。

使用它可能看起来像这样:

int main() {
    // ... your initialization stuff ...
    std::string from, to;
    Chess game; // create a game instance

    while(true) {
        game.printBoard();
        std::wcout << L"Move number " << game.getMoveNumber() << L".\n";
        std::wcout << L"Move piece or use back/reset/exit: ";
        std::cin >> from;

        if(from == "exit") break;

        if (from == "reset") {
            game.Reset();
            std::wcout << L"Restarting game.\n";
            continue;
        }

        if(from == "back") {
            if (game.Back()) {
                std::wcout << L"Returned.\n";
            }
            else {
                std::wcout << L"Already at first move.\n";
            }
            continue;
        }
        std::wcout << L"Move to: ";
        std::cin >> to;

        if(!game.movePiece(from, to)) {
            std::wcout << L"Move didn`t work. Try again.\n";
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.