Advertisement
Guest User

Untitled

a guest
Feb 16th, 2019
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.01 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import pygame
  5. from pygame.locals import *
  6. import numpy as np
  7. import instances
  8. from solve import solve
  9. import random
  10. import time
  11.  
  12. def get_pent_idx(pent):
  13. """
  14. Returns the index of a pentomino.
  15. """
  16. pidx = 0
  17. for i in range(pent.shape[0]):
  18. for j in range(pent.shape[1]):
  19. if pent[i][j] != 0:
  20. pidx = pent[i][j]
  21. break
  22. if pidx != 0:
  23. break
  24. if pidx == 0:
  25. return -1
  26. return pidx - 1
  27.  
  28.  
  29. def is_pentomino(pent, pents):
  30. """
  31. Checks if a pentomino pent is part of pents
  32. """
  33. pidx = get_pent_idx(pent)
  34. if pidx == -1:
  35. return False
  36. true_pent = pents[pidx]
  37.  
  38. for flipnum in range(3):
  39. p = np.copy(pent)
  40. if flipnum > 0:
  41. p = np.flip(pent, flipnum - 1)
  42. for rot_num in range(4):
  43. if np.array_equal(true_pent, p):
  44. return True
  45. p = np.rot90(p)
  46. return False
  47.  
  48.  
  49. def add_pentomino(board, pent, coord, check_pent=False, valid_pents=None):
  50. """
  51. Adds a pentomino pent to the board. The pentomino will be placed such that
  52. coord[0] is the lowest row index of the pent and coord[1] is the lowest
  53. column index.
  54.  
  55. check_pent will also check if the pentomino is part of the valid pentominos.
  56. """
  57. if check_pent and not is_pentomino(pent, valid_pents):
  58. return False
  59. for row in range(pent.shape[0]):
  60. for col in range(pent.shape[1]):
  61. if pent[row][col] != 0:
  62. if board[coord[0] + row][coord[1] + col] != 0: # Overlap
  63. return False
  64. else:
  65. board[coord[0] + row][coord[1] + col] = pent[row][col]
  66. return True
  67.  
  68.  
  69. def remove_pentomino(board, pent_idx):
  70. board[board == pent_idx + 1] = 0
  71.  
  72.  
  73. def check_correctness(sol_list, board, pents):
  74. """
  75. Sol is a list of pentominos (possibly rotated) and their upper left coordinate
  76. """
  77. # All tiles used
  78. if len(sol_list) != len(pents):
  79. print("unused pent")
  80. print(len(sol_list))
  81. print(len(pents))
  82. return False
  83. # Construct board
  84. sol_board = np.zeros(board.shape)
  85. seen_pents = [0] * len(pents)
  86. for pent, coord in sol_list:
  87. pidx = get_pent_idx(pent)
  88. if seen_pents[pidx] != 0:
  89. print("See multiple times")
  90. return False
  91. else:
  92. seen_pents[pidx] = 1
  93. if not add_pentomino(sol_board, pent, coord, True, pents):
  94. print("Failed to add")
  95. return False
  96.  
  97. # Check same number of squares occupied
  98. if np.count_nonzero(board) != np.count_nonzero(sol_board):
  99. print("Square uncovered")
  100. return False
  101. # Check overlap
  102. if np.count_nonzero(board) != np.count_nonzero(np.multiply(board, sol_board)):
  103. print("Overlap")
  104. return False
  105.  
  106. return True
  107.  
  108.  
  109. class Application:
  110. def __init__(self, scale=20, fps=30):
  111. self.running = True
  112. self.displaySurface = None
  113. self.scale = scale
  114. self.fps = fps
  115. self.windowTitle = "CS440 MP2"
  116.  
  117. # Initializes the pygame context and certain properties of the maze
  118. def initialize(self, board, pentominos):
  119. self.gridDim = board.shape
  120. self.pentominos = pentominos
  121. self.board = board
  122. self.windowHeight = self.gridDim[0] * self.scale
  123. self.windowWidth = self.gridDim[1] * self.scale
  124.  
  125. self.blockSizeX = int(self.windowWidth / self.gridDim[1])
  126. self.blockSizeY = int(self.windowHeight / self.gridDim[0])
  127.  
  128. # Simple wrapper for drawing a wall as a rectangle
  129. def drawWall(self, row, col):
  130. self.drawColorBlock(row, col, (0, 0, 0))
  131.  
  132. # Simple wrapper for drawing a tile as a rectangle
  133. def drawTile(self, row, col):
  134. self.drawColorBlock(row, col, (255, 255, 255))
  135.  
  136. def drawColorBlock(self, row, col, fill_col):
  137. pygame.draw.rect(self.displaySurface, fill_col,
  138. (col * self.blockSizeX, row * self.blockSizeY, self.blockSizeX, self.blockSizeY), 0)
  139.  
  140. def draw_board(self):
  141. for row in range(self.gridDim[0]):
  142. for col in range(self.gridDim[1]):
  143. if self.board[row][col] == 0:
  144. self.drawWall(row, col)
  145. else:
  146. self.drawTile(row, col)
  147.  
  148. def draw_solution_and_sleep(self, pents, slp):
  149. random.seed(3)
  150. self.draw_board()
  151. for idx, p in enumerate(pents):
  152. shape = p[0]
  153. shape_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
  154. offset = p[1]
  155. for row in range(len(shape)):
  156. for col in range(len(shape[row])):
  157. if shape[row][col] != 0:
  158. self.drawColorBlock(row + offset[0], col + offset[1], shape_color)
  159. pygame.display.flip()
  160. time.sleep(slp)
  161.  
  162. # Once the application is initiated, execute is in charge of drawing the game and dealing with the game loop
  163. def execute(self, board, pents):
  164. self.initialize(board, pents)
  165.  
  166. pygame.init()
  167. self.displaySurface = pygame.display.set_mode((self.windowWidth, self.windowHeight), pygame.HWSURFACE)
  168. self.displaySurface.fill((255, 255, 255))
  169. self.draw_board()
  170. pygame.display.flip()
  171. pygame.display.set_caption(self.windowTitle)
  172.  
  173. sol_list = solve(board, pents, self)
  174. self.draw_solution_and_sleep(sol_list, 0)
  175. pygame.display.flip()
  176.  
  177. if check_correctness(sol_list, board, pents):
  178. print("PASSED!")
  179. else:
  180. print("FAILED...")
  181.  
  182. clock = pygame.time.Clock()
  183. clock = pygame.time.Clock()
  184.  
  185. while self.running:
  186. pygame.event.pump()
  187. keys = pygame.key.get_pressed()
  188. clock.tick(self.fps)
  189.  
  190. if (keys[K_ESCAPE]):
  191. raise SystemExit
  192.  
  193. for event in pygame.event.get():
  194. if event.type == pygame.QUIT:
  195. raise SystemExit
  196.  
  197. while self.running:
  198. pygame.event.pump()
  199. keys = pygame.key.get_pressed()
  200. clock.tick(self.fps)
  201.  
  202. if (keys[K_ESCAPE]):
  203. raise SystemExit
  204.  
  205. for event in pygame.event.get():
  206. if event.type == pygame.QUIT:
  207. raise SystemExit
  208.  
  209.  
  210. if __name__ == "__main__":
  211. """
  212. Run python Pentomino.py to check your solution. You can replace 'board' and
  213. 'pents' with boards of your own. You can start off easy with simple dominos.
  214.  
  215. We won't gaurantee which tests your code will be run on, however if it runs
  216. well on the pentomino set you should be fine. The TA solution is able to run
  217. in <15 sec for the pentominos on the 6x10 board.
  218. """
  219.  
  220. board = instances.board_3x20
  221. pents = instances.triominos
  222. app = Application(40)
  223. app.execute(board, pents)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement