Advertisement
Guest User

Untitled

a guest
Apr 20th, 2018
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.34 KB | None | 0 0
  1. import sys
  2.  
  3. import pygame
  4.  
  5. # Screen size and cell size used by the maze window
  6. # Width and height of SCREEN_SIZE should be divisible by CELL_SIZE
  7. SCREEN_SIZE = (640, 480)
  8. CELL_SIZE = 32
  9.  
  10. # Some useful numbers needed for the bit manipulation
  11. # Left-most 4 bits store backtrack path, next 4 bits solution,
  12. # next 4 bits border and last 4 bits walls knocked down.
  13. # From left to right, each 4 bit cluster represents W, S, E, N
  14. # NOTE: Border bits are not currently used
  15. #                   directions
  16. #                WSENWSENWSENWSEN
  17. DEFAULT_CELL = 0b0000000000000000
  18. #                |bt||s ||b ||w |
  19. WALL_BITS = 0b0000000000001111
  20. BACKTRACK_BITS = 0b1111000000000000
  21. SOLUTION_BITS = 0b0000111100000000
  22.  
  23. # Indices match each other
  24. # WALLS[i] corresponds with COMPASS[i], DIRECTION[i], and OPPOSITE_WALLS[i]
  25. WALLS = [0b1000, 0b0100, 0b0010, 0b0001]
  26. OPPOSITE_WALLS = [0b0010, 0b0001, 0b1000, 0b0100]
  27. COMPASS = [(-1, 0), (0, 1), (1, 0), (0, -1)]
  28. DIRECTION = ['W', 'S', 'E', 'N']
  29.  
  30. # Colors
  31. BLACK = (0, 0, 0, 255)
  32. NO_COLOR = (0, 0, 0, 0)
  33. WHITE = (255, 255, 255, 255)
  34. GREEN = (0, 255, 0, 255)
  35. RED = (255, 0, 0, 255)
  36. BLUE = (0, 0, 255, 255)
  37. LIGHT_BLUE = (0, 0, 255, 100)
  38. PURPLE = (150, 0, 150, 255)
  39.  
  40.  
  41. class Maze:
  42.     def __init__(self, initial_state='idle'):
  43.         # Maze set up
  44.         self.state = initial_state
  45.         self.w_cells = int(SCREEN_SIZE[0] / CELL_SIZE)
  46.         self.h_cells = int(SCREEN_SIZE[1] / CELL_SIZE)
  47.         self.total_cells = self.w_cells * self.h_cells
  48.         self.maze_array = [DEFAULT_CELL] * self.total_cells
  49.  
  50.         # Pygame set up
  51.         pygame.init()
  52.         self.screen = pygame.display.set_mode(SCREEN_SIZE)
  53.         self.background = pygame.Surface(self.screen.get_size())
  54.         self.m_layer = pygame.Surface(self.screen.get_size())
  55.         self.s_layer = pygame.Surface(self.screen.get_size())
  56.         self.setup_maze_window()
  57.  
  58.     # Return cell neighbors within bounds of the maze
  59.     # Use self.state to determine which neighbors should be included
  60.     def cell_neighbors(self, cell):
  61.         # TODO: Logic for getting neighbors based on self.state
  62.         pass
  63.  
  64.     # Connect two cells by knocking down the wall between them
  65.     # Update wall bits of from_cell and to_cell
  66.     def connect_cells(self, from_cell, to_cell, compass_index):
  67.         # TODO: Logic for updating cell bits
  68.         self.draw_connect_cells(from_cell, compass_index)
  69.  
  70.     # Visit a cell along a possible solution path
  71.     # Update solution bits of from_cell and backtrack bits of to_cell
  72.     def visit_cell(self, from_cell, to_cell, compass_index):
  73.         # TODO: Logic for updating cell bits
  74.         self.draw_visited_cell(from_cell)
  75.  
  76.     # Backtrack from cell
  77.     # Blank out the solution bits so it is no longer on the solution path
  78.     def backtrack(self, cell):
  79.         # TODO: Logic for updating cell bits
  80.         self.draw_backtracked_cell(cell)
  81.  
  82.     # Visit cell in BFS search
  83.     # Update backtrack bits for use in reconstruct_solution
  84.     def bfs_visit_cell(self, cell, from_compass_index):
  85.         # TODO: Logic for updating cell bits
  86.         self.draw_bfs_visited_cell(cell)
  87.  
  88.     # Reconstruct path to start using backtrack bits
  89.     def reconstruct_solution(self, cell):
  90.         self.draw_visited_cell(cell)
  91.         # TODO: Logic for reconstructing solution path in BFS
  92.  
  93.     # Check if x, y values of cell are within bounds of maze
  94.     def cell_in_bounds(self, x, y):
  95.         return ((x >= 0) and (y >= 0) and (x < self.w_cells)
  96.                 and (y < self.h_cells))
  97.  
  98.     # Cell index from x, y values
  99.     def cell_index(self, x, y):
  100.         return y * self.w_cells + x
  101.  
  102.     # x, y values from a cell index
  103.     def x_y(self, index):
  104.         x = index % self.w_cells
  105.         y = int(index / self.w_cells)
  106.         return x, y
  107.  
  108.     # x, y point values from a cell index
  109.     def x_y_pos(self, index):
  110.         x, y = self.x_y(index)
  111.         x_pos = x * CELL_SIZE
  112.         y_pos = y * CELL_SIZE
  113.         return x_pos, y_pos
  114.  
  115.     # Build solution array using solution bits
  116.     # Use DIRECTION to return cardinal directions representing solution path
  117.     def solution_array(self):
  118.         solution = []
  119.  
  120.         # TODO: Logic to return cardinal directions representing solution path
  121.  
  122.         return solution
  123.  
  124.     # 'Knock down' wall between two cells, use in creation as walls removed
  125.     def draw_connect_cells(self, from_cell, compass_index):
  126.         x_pos, y_pos = self.x_y_pos(from_cell)
  127.         if compass_index == 0:
  128.             pygame.draw.line(self.m_layer, NO_COLOR, (x_pos, y_pos + 1),
  129.                              (x_pos, y_pos + CELL_SIZE - 1))
  130.         elif compass_index == 1:
  131.             pygame.draw.line(self.m_layer, NO_COLOR, (x_pos + 1,
  132.                                                       y_pos + CELL_SIZE), (x_pos + CELL_SIZE - 1,
  133.                                                                            y_pos + CELL_SIZE))
  134.         elif compass_index == 2:
  135.             pygame.draw.line(self.m_layer, NO_COLOR, (x_pos + CELL_SIZE,
  136.                                                       y_pos + 1), (x_pos + CELL_SIZE,
  137.                                                                    y_pos + CELL_SIZE - 1))
  138.         elif compass_index == 3:
  139.             pygame.draw.line(self.m_layer, NO_COLOR, (x_pos + 1, y_pos),
  140.                              (x_pos + CELL_SIZE - 1, y_pos))
  141.  
  142.     # Draw green square at cell, use to visualize solution path being explored
  143.     def draw_visited_cell(self, cell):
  144.         x_pos, y_pos = self.x_y_pos(cell)
  145.         pygame.draw.rect(self.s_layer, GREEN, pygame.Rect(x_pos, y_pos,
  146.                                                           CELL_SIZE, CELL_SIZE))
  147.  
  148.     # Draws a red square at cell, use to change cell to visualize backtrack
  149.     def draw_backtracked_cell(self, cell):
  150.         x_pos, y_pos = self.x_y_pos(cell)
  151.         pygame.draw.rect(self.s_layer, RED, pygame.Rect(x_pos, y_pos,
  152.                                                         CELL_SIZE, CELL_SIZE))
  153.  
  154.     # Draw green square at cell, use to visualize solution path being explored
  155.     def draw_bfs_visited_cell(self, cell):
  156.         x_pos, y_pos = self.x_y_pos(cell)
  157.         pygame.draw.rect(self.s_layer, LIGHT_BLUE, pygame.Rect(x_pos, y_pos,
  158.                                                                CELL_SIZE, CELL_SIZE))
  159.  
  160.     # Process events, add each layer to screen (blip) and refresh (flip)
  161.     # Call this at the end of each traversal step to watch the maze as it is
  162.     # generated. Skip call until end of creation/solution to make faster.
  163.     def refresh_maze_view(self):
  164.         check_for_exit()
  165.         self.screen.blit(self.background, (0, 0))
  166.         self.screen.blit(self.s_layer, (0, 0))
  167.         self.screen.blit(self.m_layer, (0, 0))
  168.         pygame.display.flip()
  169.  
  170.     def setup_maze_window(self):
  171.         # Set up window and layers
  172.         pygame.display.set_caption('MyMaze')
  173.         pygame.mouse.set_visible(0)
  174.         self.background = self.background.convert()
  175.         self.background.fill(WHITE)
  176.         self.m_layer = self.m_layer.convert_alpha()
  177.         self.m_layer.fill(NO_COLOR)
  178.         self.s_layer = self.s_layer.convert_alpha()
  179.         self.s_layer.fill(NO_COLOR)
  180.  
  181.         # Draw grid lines (will be whited out as walls knocked down)
  182.         for y in range(self.h_cells + 1):
  183.             pygame.draw.line(self.m_layer, BLACK, (0, y * CELL_SIZE),
  184.                              (SCREEN_SIZE[0], y * CELL_SIZE))
  185.         for x in range(self.w_cells + 1):
  186.             pygame.draw.line(self.m_layer, BLACK, (x * CELL_SIZE, 0),
  187.                              (x * CELL_SIZE, SCREEN_SIZE[1]))
  188.  
  189.         # Color start cell blue and exit cell purple.
  190.         # Assumes start at top-left and exit at bottom-right
  191.         pygame.draw.rect(self.s_layer, BLUE,
  192.                          pygame.Rect(0, 0, CELL_SIZE, CELL_SIZE))
  193.         pygame.draw.rect(self.s_layer, PURPLE, pygame.Rect(
  194.             SCREEN_SIZE[0] - CELL_SIZE, SCREEN_SIZE[1] -
  195.             CELL_SIZE, CELL_SIZE, CELL_SIZE))
  196.  
  197.  
  198. def check_for_exit():
  199.     # Aims for 60fps, checks for events.
  200.     # Without event check every frame, window will not exit!
  201.     clock = pygame.time.Clock()
  202.     clock.tick(60)
  203.     for event in pygame.event.get():
  204.         if event.type == pygame.QUIT:
  205.             sys.exit(0)
  206.         elif event.type == pygame.KEYDOWN:
  207.             if event.key == pygame.K_ESCAPE:
  208.                 sys.exit(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement