我正在用 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;
首先,我建议你将
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";
}
}
}