C++学习-骑士巡游问题
C++学习-骑士巡游问题
代码如下,这里使用的是可达性试探法
#include <array>
#include <iostream>
#include <iomanip>using namespace std;// 骑士合法的移动方式,水平和竖直成对
const array <int, 8> horizontal = {2,1,-1,-2,-2,-1,1,2
};
const array <int, 8> vertical = {-1,-2,-2,-1,1,2,2,1
};// 生成棋盘中每个位置的可达位置数
void initBoard(array<array<int, 8>, 8>&, const array<array<int, 8>, 8>&);// 判断一个位置是否可走
bool isLegal(const int, const int, const int, const array<array<int, 8>, 8>&);// 打印一个棋盘的内容
void displayBoard(const array<array<int, 8>, 8>&);// 走下一步
bool getPath(int&, int&, array<array<int, 8>, 8>&, array<array<int, 8>, 8>&, int&);int main()
{// 一个 8 * 8 的array对象用于保存可达信息,每个位置能到达的其他位置的数量array<array<int, 8>, 8> board1 = {};// 一个 8 * 8 的array对象用于保存骑士移动路径array<array<int, 8>, 8> board2 = {};// 初始化可达位置的棋盘initBoard(board1, board2);// 输出棋盘cout << "board1:" << endl;displayBoard(board1);cout << "\nboard2:" << endl;displayBoard(board2);int times = 0;for (int row = 0; row < 8; row++){for (int column = 0; column < 8; column++){// 骑士巡游int rows = row;int columns = column;int count = 1;board2 = {};initBoard(board1, board2);while (getPath(rows, columns, board1, board2, count)){}if (count == 65){cout << "\n巡游完成.(" << row << ", " << column << ")" << endl;cout << "After move:" << endl;cout << "board1:" << endl;displayBoard(board1);cout << "\nboard2:" << endl;displayBoard(board2);times++;}}}cout << "\n\ntimes = " << times << endl;
}void initBoard(array<array<int, 8>, 8>& board1, const array<array<int, 8>, 8>& board2)
{for (int row = 0; row < board1.size(); row++){for (int column = 0; column < board1[0].size(); column++){int total = 0;for (int i = 0; i < horizontal.size(); i++){if (isLegal(row, column, i, board2)){total++;}}board1[row][column] = total;}}
}bool isLegal(const int row, const int column, const int i, const array<array<int, 8>, 8>& board)
{int rows = row + horizontal[i];int columns = column + vertical[i];// 超出棋盘if (rows < 0 || rows > 7 || columns < 0 || columns > 7){return false;}else if(board[rows][columns] != 0) // 当前位置已经走过{return false;}else{return true;}
}void displayBoard(const array<array<int, 8>, 8>& board)
{for (const auto& row : board){for (const auto& item : row){cout << left << setw(3) << item;}cout << endl;}
}// row为起始行,column为起始列,board为记录骑士移动的棋盘
bool getPath(int& row, int& column, array<array<int, 8>, 8>& board1, array<array<int, 8>, 8>& board2,int& count) // 计数器
{// 骑士走到当前位置board2[row][column] = count++;// 重新生成对应的可达棋盘initBoard(board1, board2);// 最难到达的走法,0-7int path = -1;// 当前path能到达的格子数,初始化为8int minimum = 8;for (int i = 0; i < 8; i++){// 移动首先必须合法if (isLegal(row, column, i, board2)){int rows = row + horizontal[i];int columns = column + vertical[i];if (board1[rows][columns] < minimum){path = i;minimum = board1[rows][columns];}}}// 有路可走if (path != -1){row += horizontal[path];column += vertical[path];return true;}else{return false;}
}
运行结果(仅部分结果):