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-7
int path = -1;
// 当前path能到达的格子数,初始化为8
int 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;
}
}
运行结果(仅部分结果):