From a850cd967ca10938d21753d6bdbaac2fe2a913e9 Mon Sep 17 00:00:00 2001 From: Tom van der Lee Date: Sun, 1 Jan 2017 15:15:47 +0100 Subject: Fixed all weird things I did 3 years ago --- minesweeper | 15 ------ minesweeper/__init__.py | 0 minesweeper/__main__.py | 19 ++++++++ minesweeper/cell.py | 50 +++++++++++++++++++ minesweeper/field.py | 126 ++++++++++++++++++++++++++++++++++++++++++++++++ minesweeper/game.py | 124 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 319 insertions(+), 15 deletions(-) delete mode 100755 minesweeper create mode 100644 minesweeper/__init__.py create mode 100644 minesweeper/__main__.py create mode 100644 minesweeper/cell.py create mode 100644 minesweeper/field.py create mode 100644 minesweeper/game.py (limited to 'minesweeper') diff --git a/minesweeper b/minesweeper deleted file mode 100755 index 74333b5..0000000 --- a/minesweeper +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python3 - -import game - -help = game.Help() -setup = game.Setup() -loop = game.Loop() -end = game.End() - -help.setState(loop) -setup.setState(loop) -end.setState(setup) -loop.setStates(setup,help,end) - -setup.setup() diff --git a/minesweeper/__init__.py b/minesweeper/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/minesweeper/__main__.py b/minesweeper/__main__.py new file mode 100644 index 0000000..aec3fcc --- /dev/null +++ b/minesweeper/__main__.py @@ -0,0 +1,19 @@ +from minesweeper import game + + +def main(): + help = game.Help() + setup = game.Setup() + loop = game.Loop() + end = game.End() + + help.set_state(loop) + setup.set_state(loop) + end.set_state(setup) + loop.set_states(setup, help, end) + + setup.setup() + + +if __name__ == "__main__": + main() diff --git a/minesweeper/cell.py b/minesweeper/cell.py new file mode 100644 index 0000000..8c7481b --- /dev/null +++ b/minesweeper/cell.py @@ -0,0 +1,50 @@ +from random import randint + + +class Cell: + def __init__(self, chance): + self._value = None + + if randint(0, 99) < chance: + self.is_mine = True + else: + self.is_mine = False + + self.covered = True + self.cover = '#' + + @property + def value(self): + return self._value + + @value.setter + def value(self, value): + if value == 0: + self._value = ' ' + else: + self._value = str(value) + + @property + def visible_value(self): + if self.covered: + return self.cover + else: + return self.value + + @property + def safe(self): + if self.cover == 'F': + return True + else: + return False + + def uncover(self): + self.covered = False + + def toggle_flag(self): + if self.cover == '#': + self.cover = 'F' + elif self.cover == 'F': + self.cover = '#' + +# vim: set ts=8 sw=4 tw=0 et : diff --git a/minesweeper/field.py b/minesweeper/field.py new file mode 100644 index 0000000..e6d1cd3 --- /dev/null +++ b/minesweeper/field.py @@ -0,0 +1,126 @@ +from minesweeper.cell import Cell + + +class Field: + def __init__(self, width, height, nr_of_mines): + self.width = width + self.height = height + + self.create_field(nr_of_mines) + self.create_hints() + + def create_field(self, nr_of_mines): + mines_added = None + chance = (nr_of_mines * 100) / (self.width * self.height) + + while mines_added != nr_of_mines: + self.field = [] + mines_added = 0 + + for _ in range(self.height): + row = [] + for _ in range(self.width): + cell = Cell(chance) + row.append(cell) + + if cell.is_mine: + mines_added += 1 + + self.field.append(row) + + def create_hints(self): + for y, row in enumerate(self.field): + for x, cell in enumerate(row): + if cell.is_mine: + cell.value = 'x' + else: + cell.value = len(list(self.mines_around(x, y))) + + def cells_around(self, x, y): + for i in range(-1, 2): + for j in range(-1, 2): + dx = x + i + dy = y + j + + if dx >= 0 and dy >= 0 \ + and dx < self.width and dy < self.height: + yield (dx, dy), self.field[dy][dx] + + def mines_around(self, x, y): + for position, cell in self.cells_around(x, y): + if cell.is_mine: + yield cell + + @property + def mines(self): + for row in self.field: + for cell in row: + if cell.is_mine: + yield cell + + @property + def covered_cells(self): + for row in self.field: + for cell in row: + if cell.covered: + yield cell + + def uncover_empty_around(self, x, y): + for position, cell in self.cells_around(x, y): + if cell.covered: + self.guess(*position) + + def print_column_names(self): + print("\n\t", end="") + + for char in range(0, self.width): + print(chr(char + 65) + " ", end="") + + print("\n") + + def print_row(self, count, row): + print(str(count) + "\t", end='') + + for cell in row: + print(cell.visible_value + " ", end='') + + print("\t" + str(count)) + + def print(self): + self.print_column_names() + + for count, row in enumerate(self.field): + self.print_row(count + 1, row) + + self.print_column_names() + + @property + def cleared(self): + all_safe = True + for mine in self.mines: + all_safe &= mine.safe + + only_mines_covered = True + for cell in self.covered_cells: + only_mines_covered &= cell.is_mine + + return all_safe or only_mines_covered + + def guess(self, x, y): + cell = self.field[y][x] + if cell.value == " ": + cell.uncover() + self.uncover_empty_around(x, y) + return False + elif cell.value == 'x': + cell.uncover() + return True + else: + cell.uncover() + return False + + def flag(self, x, y): + cell = self.field[y][x] + cell.toggle_flag() + +# vim: set ts=8 sw=4 tw=0 et : diff --git a/minesweeper/game.py b/minesweeper/game.py new file mode 100644 index 0000000..9ef7b16 --- /dev/null +++ b/minesweeper/game.py @@ -0,0 +1,124 @@ +from minesweeper.field import Field + + +class Help: + def set_state(self, loop): + self.loop = loop + + def print(self): + print("""Listed commands: + try Tests for mines + flag Places flag + restart Starts new game + quit or exit Quits game + help Prints list of commands +""") + self.loop.command() + + +class Setup: + def set_state(self, loop): + self.loop = loop + + def setup(self): + print("""Select diffeculty: + 1. Beginner (10 mines, 9x9) + 2. Intermediate (40 mines, 16x16) + 3. Expert (99 mines, 30x16) + 4. Custom" +""") + + choice = int( + input("Choice: ").split()[0]) + + if choice == 1: + width = 9 + height = 9 + mines = 10 + elif choice == 2: + width = 16 + height = 16 + mines = 40 + elif choice == 3: + width = 30 + height = 16 + mines = 99 + elif choice == 4: + width = int(input("Width: ")) + height = int(input("Height: ")) + mines = int(input("Mines: ")) + else: + print(str(choice) + " is not a option.") + self.setup() + + minefield = Field(width, height, mines) + self.loop.set_minefield(minefield) + self.loop.command() + + +class Loop: + def set_states(self, setup, help, end): + self.setup = setup + self.end = end + self.help = help + + def set_minefield(self, minefield): + self.minefield = minefield + + def command(self): + self.minefield.print() + if self.minefield.cleared: + self.end.end_game(False) + + command = input("Command >> ").split(' ') + + if len(command) == 3: + coordinate = (ord(command[1]) - 65, int(command[2]) - 1) + + if command[0] == "try": + if self.minefield.guess(*coordinate): + self.minefield.print() + self.end.end_game(dead=True) + return + self.command() + elif command[0] == "flag": + self.minefield.flag(*coordinate) + self.command() + # elif command[0] == "?": + # self.minefield.question(coordinate) + # self.command() + elif command[0] == "restart": + self.setup.setup() + elif command[0] == "quit" or command[0] == "exit": + exit() + elif command[0] == "help": + self.help.print() + else: + print(command[0] + " is not a recognized command") + self.help.print() + + +class End: + def set_state(self, setup): + self.setup = setup + + def restart(self): + choice = input("Do you want to start again? [y/n] ").split()[0] + + if choice == "y": + self.setup.setup() + elif choice == "n": + exit() + else: + print(str(choice) + " is not a valid choice") + self.restart() + + def end_game(self, dead): + print("") + + if dead: + print("You hit a mine :o") + else: + print("You won :D") + + self.restart() -- cgit v1.2.3