В этом коде много проблем - достаточно того, что его стоит полностью изучить:
import random
def main():
global tries,moves
Первый из многих примеров чрезмерного использования глобальных переменных.По возможности передавайте параметры;или создать класс.Это общая стратегия, которая поможет вам создать более понятные (и, следовательно, более отлаживаемые) алгоритмы;и в общем смысле это одна из причин, по которой ваш код дает сбой - не из-за какой-то конкретной ошибки, а потому, что сложность вашего кода затрудняет поиск ошибок.
tries,moves=0,0
restart()
def restart():
global a,indexes,x,y
Почему вы называете свою доску a
?Это ужасное имя!Используйте что-то описательное, например squares_visited
.
a=[[0 for y in range(8)] for x in range(8)] #Costrutto chic
indexes=[x for x in range(8)]
Minor: в python 2 [x for x in range(8)] == range(8)
- они делают одно и то же, поэтому понимание списка не требуется.В 3 он работает немного по-другому, но если вам нужен список (а не range
объект), просто передайте его list
, как в (list(range(8))
).
#Random part
x=random.randint(0,7)
y=random.randint(0,7)
a[x][y]=1
start()
Итак, мое понимание кода на данный момент таково, что a
- это доска, x
и y
- начальные координаты, и вы отметили первое посещенное место с помощью 1
.Все идет нормально.Но потом все начинает становиться неопрятным, потому что вы вызываете start
в конце restart
вместо того, чтобы вызывать его из функции управления верхнего уровня.Это теоретически нормально, но делает рекурсию более сложной, чем необходимо;это еще одна часть вашей проблемы.
def start():
global i,indexes,moves,tries
Ага, еще больше глобалов ...
i=0
random.shuffle(indexes) #List filled with random numbers that i'll use as indexes
while i<=7:
if indexes[i]==0:
move(-2,-1)
elif indexes[i]==1:
move(-2,1)
elif indexes[i]==2:
move(-1,-2)
elif indexes[i]==3:
move(-1,2)
elif indexes[i]==4:
move(1,-2)
elif indexes[i]==5:
move(1,2)
elif indexes[i]==6:
move(2,-1)
elif indexes[i]==7:
move(2,1)
i+=1
Хорошо, так что вы пытаетесь последовательно просмотреть каждый индекс в indexes
.Почему вы используете while
?И почему i
глобальный ??Я не вижу его где-либо еще.Это слишком сложно.Просто используйте цикл for
для итерации по indexes
напрямую, как в
for index in indexes:
if index==0:
...
Хорошо, теперь для конкретных проблем ...
for _ in a:
if 0 in _:
print "Wasted moves: %d"%(moves)
tries+=1
moves=0
restart()
print "Success obtained in %d tries"%(tries)
Я не понимаючто вы пытаетесь сделать здесьКажется, что вы звоните restart
каждый раз, когда вы обнаруживаете 0
(то есть не посещенное место) на вашей доске.Но restart
сбрасывает все значения платы до 0
, поэтому, если нет другого способа заполнить доску 1
с до достижения этой точки, это приведет к бесконечной рекурсии.Фактически, взаимная рекурсия между move
и start
может быть в состоянии достичь этого в принципе, но на самом деле это слишком сложно!Проблема в том, что нет четкого условия завершения рекурсии.
def move(column,row):
global x,y,a,moves
try: b=a[x+row][y+column]
except IndexError: return 0
if b==0 and 0<=x+row<=7 and 0<=y+column<=7:
x=x+row
y=y+column
a[x][y]=1
moves+=1
start()
else: return 0
Здесь, в принципе, кажется, что если ваш ход достигнет 1
или уйдет с доски, то текущая ветвь рекурсии заканчивается.Но поскольку i
и indexes
глобальны выше в start
, когда start
вызывается повторно, он перетасовывает indexes
и сбрасывает i
в 0!Результат - хаос!Я даже не могу понять, как это повлияет на рекурсию;вполне вероятно, что поскольку i
каждый раз сбрасывается в начале start
, а каждый успешный вызов move
приводит к вызову start
, цикл while
при запуске не будет никогда прекратить!
Полагаю, возможно, что в конечном итоге этому процессу удастся побывать на каждом квадрате, и в этот момент все может работать так, как ожидается, но на самом деле это слишком сложно, чтобы даже прогнозировать.
try :main()
#except: print "I couldn't handle it" <-Row added to prevent python from returning a huge amount of errors
Не уверен, что вы подразумеваете под этой последней строкой, но это не похоже на хороший знак - вы исправляете ошибку, а не находите основную причину.
Я собираюсь немного поиграть с этим кодом и посмотреть, смогу ли я заставить его вести себя немного лучше, если де-глобализировать некоторые его состояния ... скоро сообщу.
Обновление :
Хорошо, я глобализировал indexes
, как описано выше.Затем я заменил рекурсию start
/ restart
на бесконечный цикл в restart
, оператор return
в start
, где раньше был вызов restart
, и sys.exit()
в концеstart
(чтобы выйти из бесконечного цикла при успехе).Результат ведет себя больше, чем ожидалось.Это все еще плохой дизайн, но он работает сейчас, в том смысле, что он рекурсивно пробует несколько случайных путей, пока не будет посещена каждая локальная позиция.
Конечно, это все еще не удавалось;это просто продолжает цикл.На самом деле поиск решения, вероятно, потребует гораздо большего переосмысления этого алгоритма!Но, следуя моим вышеизложенным предложениям, некоторые должны помочь, по крайней мере.