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-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;
	}
}

运行结果(仅部分结果):

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值