问题说明
我想在8x8板上创建Knight's Tour,到目前为止只使用了递归来实现代码。
8x8棋盘的骑士之旅大约有19百万次动作。
src = https://en.wikipedia.org/wiki/Knight%27s_tour#Number_of_tours
我的观点是,即使到达一个不能再移动的正方形,它也可以每次都递归地返回以找到解决方案而不会终止。
我使用2个列表solution_list-存储旅行的解决方案 和pos_visited-存储以前访问的位置,这些位置没有进一步的移动。
错误
这个问题Knight's Tour in Python - Getting Path from Predecessors帮助我弄清楚哪里出了问题。
最初,移动到上一个位置没有问题,但是随着pos_visited列表增加功能 Next_move ,因此,无法从没有移动的move_set中选择移动并抛出'IndexError :无法从空序列中进行选择。”
我只添加了必要的代码和相关功能以提高可读性。
import random
def Start_Tour(board, solution_list, move_set, pos_visited):
# clears board
clear_board(board, solution_list, move_set, pos_visited)
# ASKS STARTING POSITION
print("Give initial coordinates to start: ")
x_initial, y_initial = first_pos(board)
board[x_initial][y_initial] = "♘"
# Displays board
display_board(board)
solution_list.append([x_initial, y_initial])
print(f"Starting position defined at {x_initial, y_initial}")
count = 0
while count < 65:
# Move_set gets valid and unoccupied coordinates in board
move_set = potential_moves(x_initial, y_initial, board)
# check if move_set is empty
if len(move_set) == 0:
# BACKTRACK if empty
print("Moving Back")
retrack(board, solution_list, pos_visited)
# Else-Place Knight
else:
# choose one move as xn,yn at random
xn, yn = Next_move(move_set, pos_visited)
# place marker in xn,yn
board[xn][yn] = "♘"
# clears previous position
clear_previous_pos(board, solution_list)
# adds position to solution_list
solution_list.append([xn, yn])
print(f"\n solution_list -> {solution_list}")
print("\n")
# displays board
display_board(board)
# sets x_initial and y_initial for generating next set of potential moves
x_initial = xn
y_initial = yn
count += 1
print(f"\n {count}")
def potential_moves(a, b, board):
"""
Takes current position of knight(a,b) and generates possible moves as a list
"""
move_set = [
[a - 1, b - 2],
[a - 2, b - 1],
[a - 2, b + 1],
[a - 1, b + 2],
[a + 1, b + 2],
[a + 2, b + 1],
[a + 2, b - 1],
[a + 1, b - 2],
]
for x, y in move_set[:]:
if x in range(0, 8) and y in range(0, 8) and board[x][y] == " ":
pass
else:
move_set.remove([x, y])
return move_set
def retrack(board, solution_list, pos_visited):
"""
helps knight to move back to previous position.
"""
x_current, y_current = solution_list.pop(-1) # x,y have no more valid moves
pos_visited.append([x_current, y_current]) # adds x,y to positions already visited
board[x_current][y_current] = " " # erases current x,y pos'n
x, y = solution_list[-1] # returns pos'n before getting stuck
if len(potential_moves(x, y, board)) != 0 and [x, y] not in pos_visited:
return x, y
else:
return retrack(board, solution_list, pos_visited)
def Next_move(move_set, pos_visited):
"""
returns a move at random from move_set if it isn't visited already.
"""
xn, yn = random.choice(move_set)
if positions_visited(xn, yn, pos_visited):
return xn, yn
else:
move_set.remove([xn, yn])
move_set1 = move_set
return Next_move(move_set, pos_visited)
def positions_visited(n1, n2, pos_visited): # Checks for position in tracker
"""
checks if position has been visited already
"""
if [n1, n2] in pos_visited:
return False
else:
return True
This is the output I get so far before an error is thrown.
P.S:我已经学习Python 2个月了,对算法的了解还不多。在尝试使用算法之前,我首先想提供一种具有基本方法的解决方案。如果您可以详细解释是否认为我应该采用其他方法,这将非常有帮助。
谢谢
-桑托什
编辑:我添加了追溯错误
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-22-aba4d6ed48dc> in <module>
----> 1 Start_Tour(cb,solution_list,move_set,pos_visited)
<ipython-input-18-0c959cf546f8> in Start_Tour(board, solution_list,
move_set, pos_visited)
31
32 # choose one move as xn,yn
----> 33 xn,yn = Next_move(move_set,pos_visited)
34
35 #place marker in xn,yn
<ipython-input-21-c2489e88fd1e> in Next_move(move_set, pos_visited)
9 move_set.remove([xn,yn])
10 move_set1 = move_set
---> 11 return Next_move(move_set,pos_visited)
<ipython-input-21-c2489e88fd1e> in Next_move(move_set, pos_visited)
3 #returns a move at random from move_set if it isn't visited already.
----> 4 xn,yn = random.choice(move_set)
5 if positions_visited(xn,yn,pos_visited):
6 return xn,yn
F:\Anaconda\lib\random.py in choice(self, sea)
259 i = self._randbelow(len(seq))
260 except ValueError:
--> 261 raise IndexError('Cannot choose from an empty
sequence') from None
262 return seq[i]
263
IndexError: Cannot choose from an empty sequence
答案 0 :(得分:0)
我觉得您的问题出在这里的代码中。由于某种原因,显然没有填充您的move_set列表。也就是说,正在发生的情况是else
循环的for
部分正在为每个可能的动作执行。这是有道理的,因为根据董事会的判断,骑士没有可能采取任何行动。每个board[x][y]
不等于' '
。
def potential_moves(a,b,board):
'''
Takes current position of knight(a,b) and generates possible moves as a list
'''
move_set = [[a-1,b-2],[a-2,b-1],[a-2,b+1],[a-1,b+2],[a+1,b+2],[a+2,b+1],[a+2,b-1],[a+1,b-2]]
for x,y in move_set[:]:
if x in range(0,8) and y in range(0,8) and board[x][y]==' ':
pass
else:
move_set.remove([x,y])
return move_set
编辑:正如您的帖子中的评论所指出的那样。看来骑士cb
没有在您的retrack
函数中定义,因此无法做出任何动作,我认为这是为了防止骑士没有做出任何动作。