我必须提一下,这是我第一次在这个网站上发帖,请原谅我,如果我不遵循本网站的指南。
我的问题可能很简单,但我无法理解。我的骑士游览算法以递归方式找到骑士的路径。它适用于索引[0,0],它完美地遍历数组的空间......但是,除了索引[0,0]之外的任何东西,程序都会挂起似乎永恒的东西。这是我的代码:
# knightstour.py
#
# created by: M. Peele
# section: 01
#
# This program implements a brute-force solution for the Knight's tour problem
# using a recursive backtracking algorithm. The Knight's tour is a chessboard
# puzzle in which the objective is to find a sequence of moves by the knight in
# which it visits every square on the board exactly one. It uses a 6x6 array for
# the chessboard where each square is identified by a row and column index, the
# range of which both start at 0. Let the upper-left square of the board be the
# row 0 and column 0 square.
#
# Imports the necessary modules.
from arrays import *
# Initializes the chessboard as a 6x6 array.
chessBoard = Array2D(6, 6)
# Gets the input start position for the knight from the user.
row = int(input("Enter the row: "))
col = int(input("Enter the column: "))
# Main driver function which starts the recursion.
def main():
knightsTour(row, col, 1)
# Recursive function that solves the Knight's Tour problem.
def knightsTour(row, col, move):
# Checks if the given index is in range of the array and is legal.
if _inRange(row, col) and _isLegal(row, col):
chessBoard[row, col] = move # Sets a knight-marker at the given index.
# If the chessBoard is full, returns True and the solved board.
if _isFull(chessBoard):
return True, _draw(chessBoard)
# Checks to see if the knight can make another move. If so, makes that
# move by calling the function again.
possibleOffsets = ((-2, -1), (-2, 1), (-1, 2), (1, 2), \
(2, 1), (2, -1), (1, -2), (-1, -2))
for offset in possibleOffsets:
if knightsTour(row + offset[0], col + offset[1], move + 1):
return True
# If the loop terminates, no possible move can be made. Removes the
# knight-marker at the given index.
chessBoard[row, col] = None
return False
else:
return False
# Determines if the given row, col index is a legal move.
def _isLegal(row, col):
if _inRange(row, col) and chessBoard[row, col] == None:
return True
else:
return False
# Determines if the given row, col index is in range.
def _inRange(row, col):
try:
chessBoard[row, col]
return True
except AssertionError:
return False
# A solution was found if the array is full, meaning that every element in the
# array is filled with a number saying the knight has visited there.
def _isFull(chessBoard):
for row in range(chessBoard.numRows()):
for col in range(chessBoard.numCols()):
if chessBoard[row, col] == None:
return False
return True
# Draws a pictoral representation of the array.
def _draw(chessBoard):
for row in range(chessBoard.numRows()):
for col in range(chessBoard.numCols()):
print("%4s" % chessBoard[row, col], end = " ")
print()
# Calls the main function.
main()
答案 0 :(得分:1)
您的代码没有明显错误。事实上,将chessBoard
替换为list
list
并适当更改其余代码,它适用于所有合法输入。
有关改编的代码,请参阅this pastebin。有关仅循环遍历所有有效输入的修改版本,请参阅this one。如果你运行它,它会打印出36个已完成的电路板。
因此,如果您遇到问题,或者您没有运行此处发布的相同代码,或者您的Array2D
实施中存在错误。
您的代码有一些奇怪的事情。
首先,您几乎不想检查== None
。如果您确实需要检查某些内容是否为None
,请使用is
运算符,而不是==
。如果所有“真实”值都是真实的,只需将值本身用作布尔值(因为None
是假的)。有关详细信息,请参阅PEP 8中的Programming Recommendations。
接下来,您将全局设置分为main
函数和全局模块范围。通常你想在同一个地方做这一切。
最后,使用一个改变全局变量的递归函数是一件奇怪的事情。并不是说它在你的情况下不起作用(但只是因为你只能在退出之前运行一个测试),但通常在递归函数中你想要将值作为“累加器”参数传递,或者做一切不可变的事情(通过传递副本并备份)。
答案 1 :(得分:0)
abarnert的代码工作的原因是他的函数在重写时使用负索引访问数组。所以,如果你看结果,它们是不正确的(骑士从板的顶部跳到底部)。