Advertisement
Guest User

Untitled

a guest
Oct 19th, 2019
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.71 KB | None | 0 0
  1. """Minesweeper has to swipe the mines."""
  2. import copy
  3.  
  4.  
  5. def create_minefield(height: int, width: int) -> list:
  6. """
  7. Create and return minefield.
  8.  
  9. Minefield must be length long and width wide. Each position must contain single space.
  10. :param height: int
  11. :param width: int
  12. :return: list
  13. """
  14. return [[b for b in ("." * width)] for x in range(height)]
  15.  
  16.  
  17. def add_mines(minefield: list, mines: list) -> list:
  18. """
  19. Add mines to a minefield and return minefield.
  20.  
  21. Minefield must be length long and width wide. Each non-mine position must contain single space.
  22. If a position is empty (" "), then a small mine is added ("x").
  23. If a position contains small mine ("x"), a large mine is added ("X").
  24. Mines are in a list.
  25. Mine is a list. Each mine has 4 integer parameters in the format [N, S, E, W].
  26. - N is the distance between area of mines and top of the minefield.
  27. - S ... area of mines and bottom of the minefield.
  28. - E ... area of mines and right of the minefield.
  29. - W ... area of mines and left of the minefield.
  30. :param minefield: list
  31. :param mines: list
  32. :return: list
  33. """
  34. if mines[0] == []:
  35. return minefield
  36. if len(minefield) == 0:
  37. return []
  38. height = len(minefield)
  39. length = len(minefield[0])
  40.  
  41. for i in mines:
  42. column = [i[0], height - i[1]]
  43. row = [i[3], length - i[2]]
  44. for x in range(column[0], column[1]):
  45. for y in range(row[0], row[1]):
  46. if x > height or x < 0:
  47. continue
  48. if y > length or y < 0:
  49. continue
  50. elif minefield[x][y] == "x":
  51. minefield[x][y] = "X"
  52. elif minefield[x][y].lower() == "x":
  53. continue
  54. else:
  55. minefield[x][y] = "x"
  56. return minefield
  57.  
  58.  
  59. def get_minefield_string(minefield: list) -> str:
  60. """
  61. Return minefield's string representation.
  62.  
  63. .....
  64. .....
  65. x....
  66. Xx...
  67.  
  68. :param minefield:
  69. :return:
  70. """
  71. return "\n".join(["".join(e) for e in minefield])
  72.  
  73.  
  74. def calculate_mine_count(minefield: list) -> list:
  75. """
  76. For each cell in minefield, calculate how many mines are nearby.
  77.  
  78. This function cannot modify the original list.
  79. So, the result should be a new list (or copy of original).
  80.  
  81. ....
  82. ..x.
  83. X.X.
  84. x..X
  85.  
  86. =>
  87.  
  88. 0111
  89. 12x2
  90. X3X3
  91. x32X
  92.  
  93. :param minefield:
  94. :return:
  95. """
  96. for i in range(len(minefield)):
  97. for j in range(len(minefield[i])):
  98. if minefield[i][j].lower() != "x":
  99. count = 0
  100. for k in range(-1, 2):
  101. for m in range(-1, 2):
  102. if i + k >= 0 and j + m >= 0 and i + k < len(minefield) and j + m < len(minefield[0]) and \
  103. minefield[i + k][j + m].lower() == 'x':
  104. count += 1
  105. minefield[i][j] = str(count)
  106. return minefield
  107.  
  108.  
  109. def coordinates(minefield):
  110. """
  111. Find cordinates.
  112.  
  113. :param minefield: list
  114. :return: list
  115. """
  116. for listy in range(len(minefield)):
  117. for el in range(len(minefield[listy])):
  118. if minefield[listy][el] == "#":
  119. return [listy, el]
  120.  
  121.  
  122. def walk(minefield, moves, lives) -> list:
  123. """
  124. Make moves on the minefield.
  125.  
  126. Starting position is marked by #.
  127. There is always exactly one # on the field.
  128. The position you start is an empty cell (" ").
  129.  
  130. Moves is a list of move "orders":
  131. N - up,
  132. S - down,
  133. E - right,
  134. W - left.
  135.  
  136. Example: "NWWES"
  137.  
  138. If the position you have to move contains "x" (small mine),
  139. then the mine is cleared (position becomes " "),
  140. but you cannot move there.
  141. If the position where the minesweeper is, has 5 or more mines nearby (see the previous function),
  142. minesweeper also loses a life. If it has 0 lives left, then clearing is not done and moving stops.
  143.  
  144. Example:
  145. #x
  146. ..
  147. moves: ESS
  148.  
  149. =>
  150.  
  151. 1st step ("E"):
  152. #.
  153. ..
  154.  
  155. 2nd step ("S"):
  156. ..
  157. #.
  158.  
  159. 3rd step ("S"):
  160. ..
  161. #.
  162.  
  163. Example #2
  164. XXX
  165. x.x
  166. .#X
  167. moves: NWES, lives = 1
  168.  
  169. 1) "N"
  170. XXX
  171. x#x
  172. ..X
  173.  
  174. 2) "W". the small mine is cleared, but with the cost of one life :'(
  175. XXX
  176. .#x
  177. ..X
  178. lives = 0
  179.  
  180. 3) "E"
  181. XXX
  182. .#x
  183. ..X
  184. As clearing the mine on the right, he would lose a life (because minesweeper has 5 or more mines nearby).
  185. But as he has no lives left, he stops there. No more moves will be carried out.
  186.  
  187. If the position you have to move contains "X" (huge mine),
  188. then you move there and lose a life.
  189.  
  190. #X
  191. ..
  192. moves: ESS
  193.  
  194. 1) (lives = lives - 1)
  195. .#
  196. ..
  197. 2)
  198. ..
  199. .#
  200. 3)
  201. ..
  202. .#
  203.  
  204. If you have to move into a position with a huge mine "X"
  205. but you don't have any more lives, then you finish your moves.
  206.  
  207. lives: 2
  208.  
  209. #XXXX
  210. .....
  211. moves: EEES
  212.  
  213. 1) lives = 1
  214. .#XXX
  215. .....
  216. 2) lives = 0
  217. ..#XX
  218. .....
  219. 3) stop, because you would die
  220. final result:
  221. ..#XX
  222. .....
  223.  
  224. :param minefield:
  225. :param moves:
  226. :param lives:
  227. :return:
  228. """
  229. cord = coordinates(minefield)
  230. x = cord[0]
  231. y = cord[1]
  232. minefield2 = minefield.copy()
  233. mines_count = calculate_mine_count(minefield2)
  234. dicty = {"N": (-1, 0), "S": (1, 0), "E": (0, 1), "W": (0, -1)}
  235. for i in moves:
  236. if x + dicty[i][0] < 0 or x + dicty[i][0] > len(minefield) - 1 or y + dicty[i][1] < 0 or y + dicty[i][1] > len(
  237. minefield[0]) - 1:
  238. continue
  239. if lives == 0:
  240. return minefield
  241. if mines_count[x][y] == "5":
  242. lives -= 1
  243. elif minefield[x + dicty[i][0]][y + dicty[i][1]] == "x":
  244. minefield[x + dicty[i][0]][y + dicty[i][1]] = "."
  245. elif minefield[x + dicty[i][0]][y + dicty[i][1]].lower() == "x":
  246. lives -= 1
  247. minefield[x][y] = "."
  248. x = x + dicty[i][0]
  249. y = y + dicty[i][1]
  250. minefield[x][y] = "#"
  251. elif minefield[x + dicty[i][0]][y + dicty[i][1]] == ".":
  252. minefield[x][y] = "."
  253. x = x + dicty[i][0]
  254. y = y + dicty[i][1]
  255. minefield[x][y] = "#"
  256. return minefield
  257.  
  258.  
  259. if __name__ == '__main__':
  260. mf = create_minefield(2, 5)
  261. mf = add_mines(mf, [[0, 1, 0, 1]])
  262. mf = add_mines(mf, [[0, 1, 0, 1]])
  263. print(get_minefield_string(mf))
  264.  
  265. mf[0][0] = "#"
  266. print(walk(mf, "EEES", 2))
  267. print(get_minefield_string(mf))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement