Python 回溯迷宫真慢
Python backtracking maze really slow
检查编辑,
我在 youtube 上观看 The Coding Train 时写了一些代码......迷宫回溯生成器。 youtuber在javascript写了代码,我在python写的时候试着看懂代码。看来他不得不改变帧率,因为他的程序太快了,只是为了看到生成部分。当我经过大约 10 个方块后,它已经很慢了。
这不可能是硬件问题,我有一个 i5-4690K CPU 和一个很好匹配的 GPU,它一定是代码中的问题!但是我找不到它是什么。
我重新看了剧集,以便找出问题所在,但似乎我写的一切都很好。
from tkinter import *
import math
import random
import time
# initialization canvas
root = Tk()
canvas = Canvas(root, width=400, height=400, bg="#333333")
canvas.pack()
# some global variables
w = 40;
cols = math.floor(int(canvas["width"])/w)
rows = math.floor(int(canvas["height"])/w)
grid = []
current = None
class Cell():
line_color = "#AAAAAA"
visited_color = "green"
visited = False
rectangle = None
def __init__(self, i, j):
self.i = i
self.j = j
self.wall = [True, True, True, True] # top , right, bottom, left
def __repr__(self):
return "({}, {})".format(self.i, self.j)
def draw_lines(self):
x = self.i*w
y = self.j*w
if self.visited :
self.rectangle = canvas.create_rectangle(x, y, x+w, y+w, fill="purple", outline="")
canvas.update()
if self.wall[0]:
canvas.create_line(x, y, x+w, y, fill=self.line_color)
else:
canvas.create_line(x, y, x+w, y, fill="purple")
if self.wall[1]:
canvas.create_line(x+w, y, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x+w, y, x+w, y+w, fill="purple")
if self.wall[2]:
canvas.create_line(x, y+w, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x, y+w, x+w, y+w, fill="purple")
if self.wall[3]:
canvas.create_line(x, y, x, y+w, fill=self.line_color)
else:
canvas.create_line(x, y, x, y+w, fill="purple")
def checkNeighbors(self):
neighbors = []
top = None
bottom = None
left = None
right = None
if index(self.i, self.j-1) != -1:
top = grid[index(self.i, self.j-1)]
if index(self.i, self.j+1) != -1:
bottom = grid[index(self.i, self.j+1)]
if index(self.i-1, self.j) != -1:
left = grid[index(self.i-1, self.j)]
if index(self.i+1, self.j) != -1:
right = grid[index(self.i+1, self.j)]
if top is not None and top.visited is False:
neighbors.append(top)
if right is not None and right.visited is False:
neighbors.append(right)
if bottom is not None and bottom.visited is False:
neighbors.append(bottom)
if left is not None and left.visited is False:
neighbors.append(left)
if len(neighbors) > 0:
r = random.randint(0, len(neighbors)-1)
return neighbors[r]
else:
return None
def removeWalls(a, b):
x = a.i - b.i
y = a.j - b.j
if x != 0:
if x == 1:
a.wall[3] = False
b.wall[1] = False
else:
a.wall[1] = False
b.wall[3] = False
if y != 0:
if y == 1:
a.wall[0] = False
b.wall[2] = False
else:
a.wall[2] = False
b.wall[0] = False
def index(i, j):
if j < 0 or j > rows - 1 or i < 0 or i > cols - 1:
return -1
return j + i * cols
def setup():
global current
for i in range(rows):
for j in range(cols):
cell = Cell(i, j)
grid.append(cell)
current = grid[0]
next_one = None
def draw():
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
for cell in grid:
cell.draw_lines()
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
for cell in grid:
print(cell.visited)
setup()
draw()
root.mainloop()
我很抱歉把所有的代码都放上去,但我认为所有这些都与性能有关,没有放任何有用的评论,抱歉我正在努力成为一个更好的程序员并改变它坏习惯
大编辑:
我测试过在完成计算后只绘制迷宫,它只需要不到一秒钟的时间,所以我认为它必须与我正在创建的小部件(线)的数量有关..?我怎样才能最小化小部件,以便我可以看到按照我想要的方式创建的迷宫?
你画线,即使它们没有改变。相反,只绘制更改的单元格。
此外,你有无限循环。即使堆栈不再包含更多元素,您也不会停止。在这里你应该打破循环。
这里有一个改进:
def draw():
for cell in grid:
cell.draw_lines()
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current.draw_lines()
next_one.draw_lines()
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
else:
break
检查编辑, 我在 youtube 上观看 The Coding Train 时写了一些代码......迷宫回溯生成器。 youtuber在javascript写了代码,我在python写的时候试着看懂代码。看来他不得不改变帧率,因为他的程序太快了,只是为了看到生成部分。当我经过大约 10 个方块后,它已经很慢了。 这不可能是硬件问题,我有一个 i5-4690K CPU 和一个很好匹配的 GPU,它一定是代码中的问题!但是我找不到它是什么。
我重新看了剧集,以便找出问题所在,但似乎我写的一切都很好。
from tkinter import *
import math
import random
import time
# initialization canvas
root = Tk()
canvas = Canvas(root, width=400, height=400, bg="#333333")
canvas.pack()
# some global variables
w = 40;
cols = math.floor(int(canvas["width"])/w)
rows = math.floor(int(canvas["height"])/w)
grid = []
current = None
class Cell():
line_color = "#AAAAAA"
visited_color = "green"
visited = False
rectangle = None
def __init__(self, i, j):
self.i = i
self.j = j
self.wall = [True, True, True, True] # top , right, bottom, left
def __repr__(self):
return "({}, {})".format(self.i, self.j)
def draw_lines(self):
x = self.i*w
y = self.j*w
if self.visited :
self.rectangle = canvas.create_rectangle(x, y, x+w, y+w, fill="purple", outline="")
canvas.update()
if self.wall[0]:
canvas.create_line(x, y, x+w, y, fill=self.line_color)
else:
canvas.create_line(x, y, x+w, y, fill="purple")
if self.wall[1]:
canvas.create_line(x+w, y, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x+w, y, x+w, y+w, fill="purple")
if self.wall[2]:
canvas.create_line(x, y+w, x+w, y+w, fill=self.line_color)
else:
canvas.create_line(x, y+w, x+w, y+w, fill="purple")
if self.wall[3]:
canvas.create_line(x, y, x, y+w, fill=self.line_color)
else:
canvas.create_line(x, y, x, y+w, fill="purple")
def checkNeighbors(self):
neighbors = []
top = None
bottom = None
left = None
right = None
if index(self.i, self.j-1) != -1:
top = grid[index(self.i, self.j-1)]
if index(self.i, self.j+1) != -1:
bottom = grid[index(self.i, self.j+1)]
if index(self.i-1, self.j) != -1:
left = grid[index(self.i-1, self.j)]
if index(self.i+1, self.j) != -1:
right = grid[index(self.i+1, self.j)]
if top is not None and top.visited is False:
neighbors.append(top)
if right is not None and right.visited is False:
neighbors.append(right)
if bottom is not None and bottom.visited is False:
neighbors.append(bottom)
if left is not None and left.visited is False:
neighbors.append(left)
if len(neighbors) > 0:
r = random.randint(0, len(neighbors)-1)
return neighbors[r]
else:
return None
def removeWalls(a, b):
x = a.i - b.i
y = a.j - b.j
if x != 0:
if x == 1:
a.wall[3] = False
b.wall[1] = False
else:
a.wall[1] = False
b.wall[3] = False
if y != 0:
if y == 1:
a.wall[0] = False
b.wall[2] = False
else:
a.wall[2] = False
b.wall[0] = False
def index(i, j):
if j < 0 or j > rows - 1 or i < 0 or i > cols - 1:
return -1
return j + i * cols
def setup():
global current
for i in range(rows):
for j in range(cols):
cell = Cell(i, j)
grid.append(cell)
current = grid[0]
next_one = None
def draw():
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
for cell in grid:
cell.draw_lines()
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
for cell in grid:
print(cell.visited)
setup()
draw()
root.mainloop()
我很抱歉把所有的代码都放上去,但我认为所有这些都与性能有关,没有放任何有用的评论,抱歉我正在努力成为一个更好的程序员并改变它坏习惯
大编辑: 我测试过在完成计算后只绘制迷宫,它只需要不到一秒钟的时间,所以我认为它必须与我正在创建的小部件(线)的数量有关..?我怎样才能最小化小部件,以便我可以看到按照我想要的方式创建的迷宫?
你画线,即使它们没有改变。相反,只绘制更改的单元格。
此外,你有无限循环。即使堆栈不再包含更多元素,您也不会停止。在这里你应该打破循环。
这里有一个改进:
def draw():
for cell in grid:
cell.draw_lines()
global current
global next_one
stack = []
almost = False
while True:
current.visited = True
next_one = current.checkNeighbors()
if next_one:
stack.append(current)
removeWalls(current, next_one)
current.draw_lines()
next_one.draw_lines()
current = next_one
elif len(stack) > 0:
cell = stack.pop()
current = cell
else:
break