class TestMap(unittest.TestCase): def setUp(self): self.t1 = Tile() self.t2 = Tile(view='2') self.t3 = Tile(view='3') self.tile_grid1 = [[self.t1] * 10 for i in range(11)] self.tile_grid2 = [[self.t2] * 3, [self.t3] * 3, [self.t2, self.t3, self.t2]] self.m1 = Map(tiles=self.tile_grid1, name='map1', info='made of the same Tile repeated for 110 times') self.m2 = Map(tiles=self.tile_grid2) def test_dimensions(self): self.assertTupleEqual(self.m1._dim, (11, 10)) def test_tile(self): self.assertEqual(self.m1.get_tile(1, 1), self.t1) # test view property on Tile obtained by Map.get_tile self.assertEqual(self.m1.get_tile(1, 1).view, None) def test_view(self): self.assertListEqual(self.m1.view(2, 2, 5, 5), [[self.t1.view] * 4 for i in range(4)]) self.assertListEqual(self.m1.view_all(), [[None] * 10] * 11) self.assertListEqual( self.m2.view_all(), [['2', '2', '2'], ['3', '3', '3'], ['2', '3', '2']])
class TestMap(unittest.TestCase): def setUp(self): self.t1 = Tile() self.t2 = Tile(view='2') self.t3 = Tile(view='3') self.tile_grid1 = [[self.t1] * 10 for i in range(11)] self.tile_grid2 = [[self.t2] * 3, [self.t3] * 3, [self.t2, self.t3, self.t2]] self.m1 = Map(tiles=self.tile_grid1, name='map1', info='made of the same Tile repeated for 110 times') self.m2 = Map(tiles=self.tile_grid2) def test_dimensions(self): self.assertTupleEqual(self.m1._dim, (11, 10)) def test_tile(self): self.assertEqual(self.m1.get_tile(1, 1), self.t1) # test view property on Tile obtained by Map.get_tile self.assertEqual(self.m1.get_tile(1, 1).view, None) def test_view(self): self.assertListEqual(self.m1.view(2, 2, 5, 5), [[self.t1.view] * 4 for i in range(4)]) self.assertListEqual(self.m1.view_all(), [[None] * 10] * 11) self.assertListEqual(self.m2.view_all(), [['2', '2', '2'], ['3', '3', '3'], ['2', '3', '2']])
def setUp(self): self.t1 = Tile() self.t2 = Tile(view='2') self.t3 = Tile(view='3') self.tile_grid1 = [[self.t1] * 10 for i in range(11)] self.tile_grid2 = [[self.t2] * 3, [self.t3] * 3, [self.t2, self.t3, self.t2]] self.m1 = Map(tiles=self.tile_grid1, name='map1', info='made of the same Tile repeated for 110 times') self.m2 = Map(tiles=self.tile_grid2)
def drawWall(cls, p1: Position, p2: Position, vertical: bool = False, horizontal: bool = False) -> None: """ Affiche une ligne de plusieurs murs INPUT : p1 : Position, position de la première cellule p2 : Position, position de la dernière cellule vertical : bool, si c'est un mur vertical horizontal : bool, si c'est un mur horizontal EXCEPTIONS : ValueError : si l'état du mur est inconnu, ou si aucune couleur n'est associée à l'état """ if vertical: p1_screen = (p1 + (0.5, 0)) * cls.cell_size p2_screen = (p2 + (0.5, 1)) * cls.cell_size etat = Map.getWall(p1) else: p1_screen = (p1 + (0, 0.5)) * cls.cell_size p2_screen = (p2 + (1, 0.5)) * cls.cell_size etat = Map.getWall(p1) if etat != Map.EMPTY: width = cls.WALL_WIDTH if etat == Map.RED_WALL: # Si c'est un mur rouge, on le met en gras width = 5 try: color = cls.color_scheme[etat] except KeyError as e: raise ValueError("État de mur inconnu : " + str(etat)) from e # On dessine une ligne allant de p1 à p2 cls.grille.create_line(p1_screen.x, p1_screen.y, p2_screen.x, p2_screen.y, fill=color, width=width)
def beforeDraw(cls) -> None: """ Méthode qui s'exécute avant l'affichage de la fenêtre """ if cls.is_running: while time.time() - cls.time_before_draw < cls.time_between_frame: time.sleep(0.01) can_display = Map.modifyCell() for i in range(int(cls.draw_time / cls.time_between_frame)): Map.modifyCell() cls.skipped_frame += 1 if can_display: cls.time_before_draw = time.time() cls.draw() else: print("Affichage final")
def init(self): all_walls = [] id_map = [] for x, y in Map.dimensions: p = Position((x, y)) id_map.append(p) if Map.isCellPosValid(p + Direction.RIGHT): all_walls.append((p, Direction.RIGHT)) if Map.isCellPosValid(p + Direction.DOWN): all_walls.append((p, Direction.DOWN)) random.shuffle(all_walls) self.all_walls = Stack(*all_walls) self.id_map = UnionFind(*id_map) self.old_p_wall = None
def getRandomDirection(p: Position) -> (Direction, None): """ Fonction permettant d'obtenir une direction aléatoire valide. INPUT : p : Position, une position visited_pos : list liste tuple, la liste des cases déjà visitées OUTPUT : res : Direction ou None si aucune direction n'est valide """ list_dir = Direction.getRandomDirectionList() # On récupère les directions triées aléatoirement res = None for dir in list_dir: new_p = p + dir if Map.isCellPosValid(new_p): # Si la nouvelle case est bien dans le plateau """ if visited_pos[new_p.x][new_p.y] is None: # Si cette nouvelle case n'a jamais été visitée if Map.getWall(p + dir/2) == Map.WALL: # S'il y a bien un mur à briser res = dir """ if Map.getWall(p + dir / 2) == Map.WALL: # S'il y a bien un mur à briser res = dir return res
def applyAlgorith(self): if self.old_p_wall is not None: Map.setWall(self.old_p_wall, Map.EMPTY) self.p1, dir = self.all_walls.pop() self.p_wall = self.p1 + dir / 2 p2 = self.p1 + dir self.can_draw = False repr_p1 = self.id_map.find(self.p1) repr_p2 = self.id_map.find(p2) if repr_p1 != repr_p2: self.can_draw = True self.id_map.union(self.p1, p2) self.old_p_wall = self.p_wall self.edited_wall_count += 1
def drawPath(self): if self.slow: Map.setCell(self.p1, Map.YELLOW_CELL) if self.can_draw: Map.setWall(self.p_wall, Map.RED_WALL) if self.finished: Map.setWall(self.old_p_wall, Map.EMPTY)
def applyAlgorith(self): left_dir = Direction.all_directions[(self.dir_id + self.increment_direction_id) % 4] front_dir = Direction.all_directions[self.dir_id % 4] self.move_forward = True if Map.isWallPosValid(self.new_p + left_dir / 2) and Map.getWall( self.new_p + left_dir / 2) == Map.EMPTY: # Si le mur de droite est valide et est vide... self.dir_id += self.increment_direction_id # On tourne dans la direction choisie elif not Map.isCellPosValid(self.new_p + front_dir) or Map.getWall( self.new_p + front_dir / 2) == Map.WALL: # Sinon si la case devant est hors du plateau ou il y a un mur en face... self.dir_id += (self.increment_direction_id + 2) % 4 # On tourne dans la direction opposée self.move_forward = False left_dir = Direction.all_directions[(self.dir_id + self.increment_direction_id) % 4] front_dir = Direction.all_directions[self.dir_id % 4] # On recalcule les directions if self.move_forward: # S'il faut avancer on avance self.old_p = Position(self.new_p) self.new_p = self.new_p + front_dir self.go_forward_frame += 1 self.nb_iter += 1 if self.nb_iter == 4 * Map.width * Map.height: raise GenericResolution.NoSolutionError()
def drawCell(cls, p1: Position, p2: Position) -> None: """ Affiche une ligne de plusieurs cellules de même couleur INPUT : p1 : Position, position de la première cellule p2 : Position, position de la dernière cellule EXCEPTIONS : ValueError : si l'état de la cellule est inconnu ValueError : si une cellule est en fait un mur """ etat = Map.getCell(p1) if etat != Map.EMPTY: try: color_in = cls.color_scheme[etat] except KeyError as e: raise ValueError("Couleur inconnue : " + str(etat)) from e if etat == Map.WALL: raise ValueError("Il y a un mur sur une case (!)") color_out = color_in p1 = p1 * cls.cell_size p2 = p2 + (1, 1) p2 = p2 * cls.cell_size # On dessine un rectange allant de p1 à p2 cls.grille.create_rectangle(p1.x + 1, p1.y + 1, p2.x, p2.y, outline=color_out, fill=color_in)
def checkIfFinished(self): if self.new_p == Map.goal_pos: self.finished = True Map.setCell(self.old_p, Map.SOLUTION_PATH)
def drawPath(self): if self.slow: self.current_state = Map.getCell(self.new_p) Map.setCell(self.new_p, Map.ORANGE_CELL) if self.slow: Map.setCell(self.new_p, self.current_state) if self.move_forward: if Map.getCell(self.new_p) == Map.EMPTY: Map.setCell(self.new_p, Map.SOLUTION_PATH) if self.old_p not in (Map.start_pos, Map.goal_pos): Map.setCell(self.old_p, Map.SOLUTION_PATH) elif Map.getCell(self.old_p) == Map.SOLUTION_PATH or Map.getCell( self.new_p) == Map.SOLUTION_PATH: if Map.getCell(self.new_p) not in (Map.START, Map.GOAL): Map.setCell(self.new_p, Map.VISITED_PATH) if self.old_p not in (Map.start_pos, Map.goal_pos): Map.setCell(self.old_p, Map.VISITED_PATH)
elif algo_name == "RECURSIVE_BACKTRACKER_RES": from resolution.recursive_backtracker_res import Resolution else: raise ValueError("Algorithme non reconnu : " + algo_name) ################################################################################ gen = Generation() if allow_resolution: res = Resolution() res_name = res.ALGORITHM_NAME else: res_name = "None" Map.__init__() Display.__init__(gen_name=gen.ALGORITHM_NAME, res_name=res_name) # Initialisation du terrain et de la fenêtre gen.start() # Lancement de la génération if allow_resolution: res.start() # Lancement de la résolution Map.resetAll(save=False) # On réinitialise la grille Display.run() # Lancement de l'affichage
""" created 05/11/2016 author: marcello version: 0.1 """ from environment.map import Map from environment.tile import Tile from gui.simple_gui import CharGui t1 = Tile(view='1') t2 = Tile(view='2') m1 = Map(tiles=[[t1, t2, t1], [t2, t1, t2], [t1, t2, t1]]) txt_gui = CharGui(map=m1, step=30) txt_gui.mainloop()
def draw(cls) -> None: """ Procédure pour dessiner à l'écran. """ t1 = time.time() # Repère temporel pour savoir la durée d'un affichage if not cls.is_running: # Si la fenêtre est fermée on arrête return cls.grille.delete(Tk.ALL) # On réinitialise la grille ######################################################################## # On dessine les cellules # On va parcourir la map ligne par ligne # pour chercher les cellules adjacentes de même couleur # pour ne dessiner qu'un seul rectange plutot que plusieurs carrés. # tkinter supporte mal plusieurs centaines de formes à afficher for y in range(Map.height): first_p = Position((0, y)) old_p = Position(first_p) for x in range(Map.width): new_p = Position((x, y)) if Map.getCell(first_p) == Map.getCell(new_p): pass else: cls.drawCell(first_p, old_p) first_p = Position(new_p) old_p = Position(new_p) cls.drawCell(first_p, old_p) ######################################################################## # On dessine les murs # Murs verticaux for x in range(Map.width - 1): first_p = Position((x + 0.5, 0)) old_p = Position(first_p) for y in range(Map.height): new_p = Position((x + 0.5, y)) if Map.getWall(first_p) == Map.getWall(new_p): pass else: cls.drawWall(first_p, old_p, vertical=True) first_p = Position(new_p) old_p = Position(new_p) cls.drawWall(first_p, old_p, vertical=True) # Murs horizontaux for y in range(Map.height - 1): first_p = Position((0, y + 0.5)) old_p = Position(first_p) for x in range(Map.width): new_p = Position((x, y + 0.5)) if Map.getWall(first_p) == Map.getWall(new_p): pass else: cls.drawWall(first_p, old_p, horizontal=True) first_p = Position(new_p) old_p = Position(new_p) cls.drawWall(first_p, old_p, horizontal=True) ######################################################################## # On dessine les 4 murs extérieurs # Mur vertical gauche cls.grille.create_line(3, 0, 3, Map.height * cls.cell_size, fill=Display.BLACK, width=cls.WALL_WIDTH) # Mur vertical droit cls.grille.create_line(cls.width, 0, cls.width, Map.height * cls.cell_size, fill=Display.BLACK, width=cls.WALL_WIDTH) # Mur horizontal en haut cls.grille.create_line(0, 3, Map.width * cls.cell_size, 3, fill=Display.BLACK, width=cls.WALL_WIDTH) # Mur horizontal en bas cls.grille.create_line(0, Map.height * cls.cell_size, Map.width * cls.cell_size, Map.height * cls.cell_size, fill=Display.BLACK, width=cls.WALL_WIDTH) cls.frame_count += 1 cls.updateTitle() delta_t = time.time() - t1 # Calcul du temps mis cls.draw_time = delta_t cls.window.after(1, cls.beforeDraw)