如何为C++国际象棋游戏实现回退按钮功能?
国际象棋回退功能修复方案
我正在用C++完成国际象棋作业,需求是实现棋子在棋盘内任意移动,以及通过back命令恢复上一步的棋盘状态。但现在执行back命令后,棋盘内容会全部消失。
我尝试用数组保存状态,但现有代码里的SaveBoard和Back函数逻辑完全错误,没正确完成棋盘状态的复制与恢复。之前还试过添加SetConsoleMode相关代码,但问题依然存在。以下是我的完整代码:
#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* backboard = &board[8][8];中board[8][8]超出了8x8数组的索引范围(合法索引为0-7),指向无效内存,无法保存棋盘状态。 - SaveBoard函数逻辑无效:只是反复让
backboard指向越界地址,完全没有复制棋盘内容。 - Back函数逻辑错误:仅操作越界的
board[8][8],没有遍历棋盘恢复内容,且*backboard本身是无效值,导致棋盘清空。 - SetConsoleMode调用错误:原代码只是写了函数名和常量,没有正确调用函数,无法启用虚拟终端处理。
- 输入逻辑混乱:错误的
else分支会跳过输入目标坐标的步骤,导致后续流程出错。
修复后的完整代码
#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[8][8]; void SaveBoard() { // 逐格复制棋盘内容到备份 for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { backboard[i][j] = board[i][j]; } } } void Back() { // 逐格从备份恢复到主棋盘 for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { board[i][j] = backboard[i][j]; } } } // 打印棋盘 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; } // 移动棋子 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"坐标错误!" << endl; return false; } // 移动前先保存当前状态 SaveBoard(); board[toY][toX] = board[fromY][fromX]; board[fromY][fromX] = L" "; return true; } int main() { _setmode(_fileno(stdout), _O_U16TEXT); // 启用Unicode输出 SetConsoleCP(1251); SetConsoleOutputCP(1251); // 正确启用虚拟终端处理,支持ANSI颜色 HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); DWORD mode = 0; GetConsoleMode(hOut, &mode); SetConsoleMode(hOut, mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); string from, to; while (true) { printBoard(); wcout << L"输入移动指令(格式如A1 A2),或输入back回退、exit退出:"; cin >> from; if (from == "exit") break; if (from == "back") { Back(); wcout << L"已回退到上一步状态。" << endl; continue; } // 获取目标坐标 cin >> to; if (!movePiece(from, to)) { wcout << L"移动失败,请重试。" << endl; } } return 0; }
内容的提问来源于stack exchange,提问作者Сергій Дегтярьов
相关产品推荐
相关产品推荐

