-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcell.py
More file actions
196 lines (158 loc) · 5.56 KB
/
cell.py
File metadata and controls
196 lines (158 loc) · 5.56 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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
from wall import *
from cost_functions import *
def is_valid_position(position, maximum, minimum=0):
return (minimum <= position[0] and minimum <= position[1]) and (maximum >= position[0] and maximum >= position[1])
class Cell:
def __init__(self, display, position, color=(59, 171, 173), side=None, grid_size=None):
self.display = display
self.grid_size = 10 if grid_size is None else grid_size
display_size = min(self.display.get_size())
self.side = display_size/self.grid_size if side is None else side
self.position = position
self.color = color
self.original_color = self.color
self.upper_wall = Wall(self.display, self.PxlPosition, width=self.unit, height=self.side, parent=self)
self.lower_wall = Wall(self.display, (self.PxlPosition[0], self.PxlPosition[1] + (self.unit * 7)), width=self.unit, height=self.side, parent=self)
self.right_wall = Wall(self.display, (self.PxlPosition[0] + (self.unit * 7), self.PxlPosition[1]), width=self.unit, height=self.side, horizontal=0, parent=self)
self.left_wall = Wall(self.display, self.PxlPosition, width=self.unit, height=self.side, horizontal=0, parent=self)
self._neighbors = []
self.available = True
self.role = None
self.end = None
self.start = None
self.parent = None
self._g = None
self._h = None
self._f = None
def __repr__(self):
return str(self.position)
@property
def neighbors(self):
return [n for n in self._neighbors if n is not None and n.role != 3 and n.available]
def connect_with_neighbors(self, cell_list):
for direction in DIRECTIONS:
x, y = apply_transform(self.position, direction)
if is_valid_position((x, y), self.grid_size - 1):
other_cell = cell_list[y][x]
self.add_neighbor(other_cell)
@property
def walls(self):
return (self.upper_wall, self.left_wall, self.lower_wall, self.right_wall)
@property
def x(self):
return int(self.PxlPosition[0] + self.unit)
@property
def y(self):
return int(self.PxlPosition[1] + self.unit)
@property
def unit(self):
return self.side/8
@property
def PxlPosition(self):
return ((self.position[0] * self.side), (self.position[1] * self.side))
@property
def size(self):
return (self.unit * 6, self.unit * 6)
def draw(self):
if self.role is not None:
c = COLORS[self.role]
else:
c = self.color
pygame.draw.rect(self.display, c, ((self.x, self.y), self.size))
for wall in self.walls:
wall.draw()
def add_neighbor(self, neighbor):
direction = determine_direction(self.position, neighbor.position)
if direction == 0:
merge_walls(neighbor.lower_wall, self.upper_wall)
elif direction == 1:
merge_walls(neighbor.right_wall, self.left_wall)
elif direction == 2:
merge_walls(neighbor.upper_wall, self.lower_wall)
elif direction == 3:
merge_walls(neighbor.left_wall, self.right_wall)
else:
raise Exception(f"The Cell at the position {neighbor.position} can not be a neighbor of the Cell at {self.position}")
self._neighbors.append(neighbor)
def is_touched(self):
mpos = pygame.mouse.get_pos()
start = self.PxlPosition
end = (self.PxlPosition[0] + self.side, self.PxlPosition[1] + self.side)
return (start[0] <= mpos[0] and mpos[0] <= end[0]) and (start[1] <= mpos[1] and mpos[1] <= end[1])
def is_clicked(self, button=0):
return int(self.is_touched() and pygame.mouse.get_pressed()[button])
def use(self):
self.available = False
def unuse(self):
self.available = False
self.color = self.original_color
def use_as_pointer(self):
self.color = (255, 0, 0)
def f_cost(self):
if self._f is not None:
return self._f
if self.start is None or self.end is None:
raise Exception(f"There is no assigned start or end cell for the cell at {self.position}")
return f(self.position, self.start.position, self.end.position)
def g_cost(self):
if self._g is not None:
return self._g
if self.start is None:
raise Exception(f"There is no assigned start cell for the cell at {self.position}")
return g(self.position, self.start.position)
def h_cost(self):
if self._h is not None:
return self._h
if self.end is None:
raise Exception(f"There is no assigned end cell for the cell at {self.position}")
return g(self.position, self.end.position)
@property
def best_neighbor(self):
for neighbor in self.neighbors:
neighbor.color = (0, 255, 0)
self.color = (255, 0, 0)
self.use()
costs_list = [(neighbor, neighbor.f_cost(), neighbor.g_cost(), neighbor.h_cost()) for neighbor in self.neighbors if neighbor is not None and neighbor.available and neighbor.role != 3]
if len(costs_list) == 0:
return None
costs_list = sorted(costs_list, key=lambda x: x[1])
b = costs_list[0]
repeats = [cost[1] for cost in costs_list].count(b[1])
if repeats == 1:
b[0].use()
return b[0]
else:
costs_list = costs_list[:repeats]
costs_list = sorted(costs_list, key=lambda x: x[3])
costs_list[0][0].use()
return costs_list[0][0]
def main():
pygame.init()
DISPLAY = pygame.display.set_mode((600, 600))
pygame.display.set_caption('Cell Test')
cell = Cell(DISPLAY, (3, 3))
cell2 = Cell(DISPLAY, (3, 4))
cell.add_neighbor(cell2)
def update_display():
global hidden
DISPLAY.fill((255, 255, 255))
if cell.is_clicked():
cell.lower_wall.hide()
if cell2.is_clicked():
cell2.upper_wall.hide()
if cell.is_clicked(2):
cell.lower_wall.show()
if cell2.is_clicked(2):
cell2.upper_wall.show()
cell.draw()
cell2.draw()
pygame.display.update()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
update_display()
pygame.quit()
if __name__ == '__main__':
main()