Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- """Minesweeper has to swipe the mines."""
- import copy
- def create_minefield(height: int, width: int) -> list:
- """
- Create and return minefield.
- Minefield must be length long and width wide. Each position must contain single space.
- :param height: int
- :param width: int
- :return: list
- """
- return [[b for b in ("." * width)] for x in range(height)]
- def add_mines(minefield: list, mines: list) -> list:
- """
- Add mines to a minefield and return minefield.
- Minefield must be length long and width wide. Each non-mine position must contain single space.
- If a position is empty (" "), then a small mine is added ("x").
- If a position contains small mine ("x"), a large mine is added ("X").
- Mines are in a list.
- Mine is a list. Each mine has 4 integer parameters in the format [N, S, E, W].
- - N is the distance between area of mines and top of the minefield.
- - S ... area of mines and bottom of the minefield.
- - E ... area of mines and right of the minefield.
- - W ... area of mines and left of the minefield.
- :param minefield: list
- :param mines: list
- :return: list
- """
- if mines[0] == []:
- return minefield
- if len(minefield) == 0:
- return []
- height = len(minefield)
- length = len(minefield[0])
- for i in mines:
- column = [i[0], height - i[1]]
- row = [i[3], length - i[2]]
- for x in range(column[0], column[1]):
- for y in range(row[0], row[1]):
- if x > height or x < 0:
- continue
- if y > length or y < 0:
- continue
- elif minefield[x][y] == "x":
- minefield[x][y] = "X"
- elif minefield[x][y].lower() == "x":
- continue
- else:
- minefield[x][y] = "x"
- return minefield
- def get_minefield_string(minefield: list) -> str:
- """
- Return minefield's string representation.
- .....
- .....
- x....
- Xx...
- :param minefield:
- :return:
- """
- return "\n".join(["".join(e) for e in minefield])
- def calculate_mine_count(minefield: list) -> list:
- """
- For each cell in minefield, calculate how many mines are nearby.
- This function cannot modify the original list.
- So, the result should be a new list (or copy of original).
- ....
- ..x.
- X.X.
- x..X
- =>
- 0111
- 12x2
- X3X3
- x32X
- :param minefield:
- :return:
- """
- for i in range(len(minefield)):
- for j in range(len(minefield[i])):
- if minefield[i][j].lower() != "x":
- count = 0
- for k in range(-1, 2):
- for m in range(-1, 2):
- if i + k >= 0 and j + m >= 0 and i + k < len(minefield) and j + m < len(minefield[0]) and \
- minefield[i + k][j + m].lower() == 'x':
- count += 1
- minefield[i][j] = str(count)
- return minefield
- def coordinates(minefield):
- """
- Find cordinates.
- :param minefield: list
- :return: list
- """
- for listy in range(len(minefield)):
- for el in range(len(minefield[listy])):
- if minefield[listy][el] == "#":
- return [listy, el]
- def walk(minefield, moves, lives) -> list:
- """
- Make moves on the minefield.
- Starting position is marked by #.
- There is always exactly one # on the field.
- The position you start is an empty cell (" ").
- Moves is a list of move "orders":
- N - up,
- S - down,
- E - right,
- W - left.
- Example: "NWWES"
- If the position you have to move contains "x" (small mine),
- then the mine is cleared (position becomes " "),
- but you cannot move there.
- If the position where the minesweeper is, has 5 or more mines nearby (see the previous function),
- minesweeper also loses a life. If it has 0 lives left, then clearing is not done and moving stops.
- Example:
- #x
- ..
- moves: ESS
- =>
- 1st step ("E"):
- #.
- ..
- 2nd step ("S"):
- ..
- #.
- 3rd step ("S"):
- ..
- #.
- Example #2
- XXX
- x.x
- .#X
- moves: NWES, lives = 1
- 1) "N"
- XXX
- x#x
- ..X
- 2) "W". the small mine is cleared, but with the cost of one life :'(
- XXX
- .#x
- ..X
- lives = 0
- 3) "E"
- XXX
- .#x
- ..X
- As clearing the mine on the right, he would lose a life (because minesweeper has 5 or more mines nearby).
- But as he has no lives left, he stops there. No more moves will be carried out.
- If the position you have to move contains "X" (huge mine),
- then you move there and lose a life.
- #X
- ..
- moves: ESS
- 1) (lives = lives - 1)
- .#
- ..
- 2)
- ..
- .#
- 3)
- ..
- .#
- If you have to move into a position with a huge mine "X"
- but you don't have any more lives, then you finish your moves.
- lives: 2
- #XXXX
- .....
- moves: EEES
- 1) lives = 1
- .#XXX
- .....
- 2) lives = 0
- ..#XX
- .....
- 3) stop, because you would die
- final result:
- ..#XX
- .....
- :param minefield:
- :param moves:
- :param lives:
- :return:
- """
- cord = coordinates(minefield)
- x = cord[0]
- y = cord[1]
- minefield2 = minefield.copy()
- mines_count = calculate_mine_count(minefield2)
- dicty = {"N": (-1, 0), "S": (1, 0), "E": (0, 1), "W": (0, -1)}
- for i in moves:
- 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(
- minefield[0]) - 1:
- continue
- if lives == 0:
- return minefield
- if mines_count[x][y] == "5":
- lives -= 1
- elif minefield[x + dicty[i][0]][y + dicty[i][1]] == "x":
- minefield[x + dicty[i][0]][y + dicty[i][1]] = "."
- elif minefield[x + dicty[i][0]][y + dicty[i][1]].lower() == "x":
- lives -= 1
- minefield[x][y] = "."
- x = x + dicty[i][0]
- y = y + dicty[i][1]
- minefield[x][y] = "#"
- elif minefield[x + dicty[i][0]][y + dicty[i][1]] == ".":
- minefield[x][y] = "."
- x = x + dicty[i][0]
- y = y + dicty[i][1]
- minefield[x][y] = "#"
- return minefield
- if __name__ == '__main__':
- mf = create_minefield(2, 5)
- mf = add_mines(mf, [[0, 1, 0, 1]])
- mf = add_mines(mf, [[0, 1, 0, 1]])
- print(get_minefield_string(mf))
- mf[0][0] = "#"
- print(walk(mf, "EEES", 2))
- print(get_minefield_string(mf))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement