aboutsummaryrefslogtreecommitdiffstats
path: root/minesweeper
diff options
context:
space:
mode:
Diffstat (limited to 'minesweeper')
-rwxr-xr-xminesweeper15
-rw-r--r--minesweeper/__init__.py0
-rw-r--r--minesweeper/__main__.py19
-rw-r--r--minesweeper/cell.py50
-rw-r--r--minesweeper/field.py126
-rw-r--r--minesweeper/game.py124
6 files changed, 319 insertions, 15 deletions
diff --git a/minesweeper b/minesweeper
deleted file mode 100755
index 74333b5..0000000
--- a/minesweeper
+++ /dev/null
@@ -1,15 +0,0 @@
1#!/usr/bin/env python3
2
3import game
4
5help = game.Help()
6setup = game.Setup()
7loop = game.Loop()
8end = game.End()
9
10help.setState(loop)
11setup.setState(loop)
12end.setState(setup)
13loop.setStates(setup,help,end)
14
15setup.setup()
diff --git a/minesweeper/__init__.py b/minesweeper/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/minesweeper/__init__.py
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 @@
1from minesweeper import game
2
3
4def main():
5 help = game.Help()
6 setup = game.Setup()
7 loop = game.Loop()
8 end = game.End()
9
10 help.set_state(loop)
11 setup.set_state(loop)
12 end.set_state(setup)
13 loop.set_states(setup, help, end)
14
15 setup.setup()
16
17
18if __name__ == "__main__":
19 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 @@
1from random import randint
2
3
4class Cell:
5 def __init__(self, chance):
6 self._value = None
7
8 if randint(0, 99) < chance:
9 self.is_mine = True
10 else:
11 self.is_mine = False
12
13 self.covered = True
14 self.cover = '#'
15
16 @property
17 def value(self):
18 return self._value
19
20 @value.setter
21 def value(self, value):
22 if value == 0:
23 self._value = ' '
24 else:
25 self._value = str(value)
26
27 @property
28 def visible_value(self):
29 if self.covered:
30 return self.cover
31 else:
32 return self.value
33
34 @property
35 def safe(self):
36 if self.cover == 'F':
37 return True
38 else:
39 return False
40
41 def uncover(self):
42 self.covered = False
43
44 def toggle_flag(self):
45 if self.cover == '#':
46 self.cover = 'F'
47 elif self.cover == 'F':
48 self.cover = '#'
49
50# 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 @@
1from minesweeper.cell import Cell
2
3
4class Field:
5 def __init__(self, width, height, nr_of_mines):
6 self.width = width
7 self.height = height
8
9 self.create_field(nr_of_mines)
10 self.create_hints()
11
12 def create_field(self, nr_of_mines):
13 mines_added = None
14 chance = (nr_of_mines * 100) / (self.width * self.height)
15
16 while mines_added != nr_of_mines:
17 self.field = []
18 mines_added = 0
19
20 for _ in range(self.height):
21 row = []
22 for _ in range(self.width):
23 cell = Cell(chance)
24 row.append(cell)
25
26 if cell.is_mine:
27 mines_added += 1
28
29 self.field.append(row)
30
31 def create_hints(self):
32 for y, row in enumerate(self.field):
33 for x, cell in enumerate(row):
34 if cell.is_mine:
35 cell.value = 'x'
36 else:
37 cell.value = len(list(self.mines_around(x, y)))
38
39 def cells_around(self, x, y):
40 for i in range(-1, 2):
41 for j in range(-1, 2):
42 dx = x + i
43 dy = y + j
44
45 if dx >= 0 and dy >= 0 \
46 and dx < self.width and dy < self.height:
47 yield (dx, dy), self.field[dy][dx]
48
49 def mines_around(self, x, y):
50 for position, cell in self.cells_around(x, y):
51 if cell.is_mine:
52 yield cell
53
54 @property
55 def mines(self):
56 for row in self.field:
57 for cell in row:
58 if cell.is_mine:
59 yield cell
60
61 @property
62 def covered_cells(self):
63 for row in self.field:
64 for cell in row:
65 if cell.covered:
66 yield cell
67
68 def uncover_empty_around(self, x, y):
69 for position, cell in self.cells_around(x, y):
70 if cell.covered:
71 self.guess(*position)
72
73 def print_column_names(self):
74 print("\n\t", end="")
75
76 for char in range(0, self.width):
77 print(chr(char + 65) + " ", end="")
78
79 print("\n")
80
81 def print_row(self, count, row):
82 print(str(count) + "\t", end='')
83
84 for cell in row:
85 print(cell.visible_value + " ", end='')
86
87 print("\t" + str(count))
88
89 def print(self):
90 self.print_column_names()
91
92 for count, row in enumerate(self.field):
93 self.print_row(count + 1, row)
94
95 self.print_column_names()
96
97 @property
98 def cleared(self):
99 all_safe = True
100 for mine in self.mines:
101 all_safe &= mine.safe
102
103 only_mines_covered = True
104 for cell in self.covered_cells:
105 only_mines_covered &= cell.is_mine
106
107 return all_safe or only_mines_covered
108
109 def guess(self, x, y):
110 cell = self.field[y][x]
111 if cell.value == " ":
112 cell.uncover()
113 self.uncover_empty_around(x, y)
114 return False
115 elif cell.value == 'x':
116 cell.uncover()
117 return True
118 else:
119 cell.uncover()
120 return False
121
122 def flag(self, x, y):
123 cell = self.field[y][x]
124 cell.toggle_flag()
125
126# 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 @@
1from minesweeper.field import Field
2
3
4class Help:
5 def set_state(self, loop):
6 self.loop = loop
7
8 def print(self):
9 print("""Listed commands:
10 try <x> <y> Tests for mines
11 flag <x> <y> Places flag
12 restart Starts new game
13 quit or exit Quits game
14 help Prints list of commands
15""")
16 self.loop.command()
17
18
19class Setup:
20 def set_state(self, loop):
21 self.loop = loop
22
23 def setup(self):
24 print("""Select diffeculty:
25 1. Beginner (10 mines, 9x9)
26 2. Intermediate (40 mines, 16x16)
27 3. Expert (99 mines, 30x16)
28 4. Custom"
29""")