-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmazeClass.py
More file actions
168 lines (146 loc) · 6.19 KB
/
mazeClass.py
File metadata and controls
168 lines (146 loc) · 6.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from tkinter import *
import random
import sys
sys.setrecursionlimit(10000)
random.seed(9000)
class Cell:
def __init__(self, i, j):
self.i = i
self.j = j
self.walls = [True, True, True, True] # top right bottom left
self.visited = False
self.neighbours = []
def randomNeighbour(self):
if self.areAvailableNeighbours():
r = random.randint(0, len(self.neighbours)-1) # pick random neighbour
while self.neighbours[r].visited: # pick randomly until it's not visited
r = random.randint(0, len(self.neighbours)-1)
return self.neighbours[r] # return randomly picked neighbour
else:
return -1
def areAvailableNeighbours(self):
for i in self.neighbours:
if not i.visited:
return True
if i.visited:
continue
return False
class Board:
def __init__(self, sizeOfTile, sizeOfMaze, timeMs):
self.sizeOfTile = sizeOfTile
self.sizeOfMaze = sizeOfMaze
self.time_ms = timeMs
self.stack = Stack() # visited tiles will be pushed onto this stack
self.grid = [] # tile matrix
self.board = Tk()
self.board.title("Maze Generator using DFS and Backtracking")
self.canvas = Canvas(self.board, width=self.sizeOfMaze, height=self.sizeOfMaze, bg="gray") # creates Canvas
self.canvas.create_text(self.sizeOfMaze-60, self.sizeOfMaze-10, font="Arial 10", text="Created by FH")
self.canvas.pack()
self.rows = int(int(self.canvas.cget('height'))/self.sizeOfTile)
self.cols = int(int(self.canvas.cget('width'))/self.sizeOfTile)
self.stack = Stack() # visited tiles will be on this stack
for i in range(self.rows): # creates array (1d grid) of Cells
for j in range(self.cols):
cell = Cell(i, j)
self.grid.append(cell)
for i in self.grid:
self.checkNeighbours(i) # goes through all tiles, fills neighbours array in each
def index(self, i, j): # returns 1D index for 2D pseudomatrix
if i < 0 or j < 0 or i > self.rows-1 or j > self.cols-1:
return -1
return self.cols*i+j
def checkNeighbours(self, cell):
topIndex = self.index(cell.i-1, cell.j)
if topIndex > -1:
cell.neighbours.append(self.grid[topIndex])
rightIndex = self.index(cell.i, cell.j+1)
if rightIndex > -1:
cell.neighbours.append(self.grid[rightIndex])
bottomIndex = self.index(cell.i+1, cell.j)
if bottomIndex > -1:
cell.neighbours.append(self.grid[bottomIndex])
leftIndex = self.index(cell.i, cell.j-1)
if leftIndex > -1:
cell.neighbours.append(self.grid[leftIndex])
def show(self, cell):
x = cell.j*self.sizeOfTile # x position for the top left corner
y = cell.i*self.sizeOfTile # y position for the top left corner
if cell.visited:
self.canvas.create_rectangle(x, y, x+self.sizeOfTile, y+self.sizeOfTile, fill='#5D33FF', width=0)
if cell.walls[0]:
self.canvas.create_line(x, y, x+self.sizeOfTile, y)
if cell.walls[1]:
self.canvas.create_line(x+self.sizeOfTile, y, x+self.sizeOfTile, y+self.sizeOfTile)
if cell.walls[2]:
self.canvas.create_line(x+self.sizeOfTile, y+self.sizeOfTile, x, y+self.sizeOfTile)
if cell.walls[3]:
self.canvas.create_line(x, y+self.sizeOfTile, x, y)
self.canvas.after(self.time_ms)
self.canvas.update()
def leadTile(self, cell):
x = cell.j * self.sizeOfTile
y = cell.i * self.sizeOfTile
self.canvas.create_rectangle(x, y, x+self.sizeOfTile, y+self.sizeOfTile, fill='#FF0000', width=0)
self.canvas.update()
def deleteWall(self, current, next):
if current.i - next.i == 1: # if upper neighbour
current.walls[0] = False
next.walls[2] = False
elif current.i - next.i == -1: # lower nb
current.walls[2] = False
next.walls[0] = False
if current.j - next.j == 1: # left nb
current.walls[3] = False
next.walls[1] = False
elif current.j - next.j == -1: # right nb
current.walls[1] = False
next.walls[3] = False
self.canvas.update()
def printMaze(self, current):
current.visited = True
nextTile = current.randomNeighbour()
if nextTile != -1: # if nextTile exists
self.stack.push(current) # push to stack
self.deleteWall(current, nextTile)
self.leadTile(current) # print leadTile
self.show(current)
self.printMaze(nextTile) # recursively go to the next tile
elif not self.stack.isEmpty(): # if stack is not empty
self.leadTile(current)
self.show(current)
self.printMaze(self.stack.pop()) # go back to the last tile
else:
print("Maze done!")
return 0
def printMazeSmallStack(self, current): # doesn't push to stack if no nbs after the last one
current.visited = True
nextTile = current.randomNeighbour()
if nextTile != -1: # if nextTile exists
nextTile.visited = True
for i in current.neighbours:
if not i.visited:
self.stack.push(current) # push to stack
break
self.deleteWall(current, nextTile)
self.leadTile(current) # print leadTile
self.show(current)
self.printMazeSmallStack(nextTile) # recursively go to the next tile
elif not self.stack.isEmpty(): # if stack is not empty
self.leadTile(current)
self.show(current)
self.printMazeSmallStack(self.stack.pop()) # go back to the last tile
else:
print("Maze done!")
return 0
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)