aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--README.rst4
-rw-r--r--cell.py50
-rw-r--r--field.py116
-rw-r--r--game.py126
-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
-rw-r--r--setup.py20
12 files changed, 343 insertions, 311 deletions
diff --git a/README.md b/README.md
deleted file mode 100644
index 7d77f0b..0000000
--- a/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
1minesweeper-py
2==============
3
4A commandline minesweeper game I made, because I was bored.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..f0e7a78
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,4 @@
1minesweeper-py
2==============
3
4A commandline minesweeper game I made, because I was bored.
diff --git a/cell.py b/cell.py
deleted file mode 100644
index 18968a2..0000000
--- a/cell.py
+++ /dev/null
@@ -1,50 +0,0 @@
1#!/usr/bin/python
2
3from random import randint
4
5class Cell:
6 def __init__(self,chance):
7 if randint(0,99) < chance:
8 self.isMine = True
9 else:
10 self.isMine = False
11 self.covered = True
12 self.cover = '#'
13
14 def getIsMine(self):
15 return self.isMine
16
17 def getValue(self):
18 return self.value
19
20 def setValue(self,value):
21 if value == '0':
22 self.value = ' '
23 else:
24 self.value = value
25 return
26
27 def isCovered(self):
28 return self.covered
29
30 def printCell(self):
31 if self.covered:
32 return self.cover
33 else:
34 return self.value
35
36 def isSafe(self):
37 if self.cover == 'F':
38 return True
39 else:
40 return False
41
42 def uncover(self):
43 self.covered = False
44 return
45
46 def toggleFlag(self):
47 if self.cover == '#':
48 self.cover = 'F'
49 elif self.cover == 'F':
50 self.cover = '#' \ No newline at end of file
diff --git a/field.py b/field.py
deleted file mode 100644
index f7a2544..0000000
--- a/field.py
+++ /dev/null
@@ -1,116 +0,0 @@
1#!/usr/bin/python
2
3from __future__ import print_function
4from cell import Cell
5
6class Field:
7 def __init__(self,width,height,mines):
8 self.width = width
9 self.height = height
10 self.mines = mines
11 self.createField()
12 self.createHints()
13 return
14
15 def createField(self):
16 minesAdded = 0
17 chance = (self.mines * 100) / (self.width * self.height)
18
19 while minesAdded != self.mines:
20 self.field = []
21 minesAdded = 0
22 for y in range(self.height):
23 row = []
24 for x in range(self.width):
25 row.append(Cell(chance))
26 if row[x].getIsMine():
27 minesAdded += 1
28 self.field.append(row)
29 return
30
31 def createHints(self):
32 for y in range(len(self.field)):
33 for x in range(len(self.field[y])):
34 cell = self.field[y][x]
35 if cell.getIsMine():
36 cell.setValue('x')
37 else:
38 m = str(self.getMinesAround(x,y))
39 cell.setValue(m)
40 return
41
42 def getMinesAround(self,x,y):
43 mines = 0
44 for i in range(-1,2):
45 for j in range(-1,2):
46 xi = x+i
47 yj = y+j
48 if xi >= 0 and yj >= 0 and xi < self.width and yj < self.height:
49 if self.field[yj][xi].getIsMine():
50 mines += 1
51 return mines
52
53 def uncoverEmptyAround(self,x,y):
54 for i in range(-1,2):
55 for j in range(-1,2):
56 xi = x+i
57 yj = y+j
58 if xi >= 0 and yj >= 0 and xi < self.width and yj < self.height:
59 cell = self.field[yj][xi]
60 if cell.isCovered():
61 self.guess(xi,yj)
62 return
63
64 def printField(self):
65 i = 1
66
67 print("\n\t", end="")
68 for char in range(0,self.width):
69 print(chr(char+65) + " ", end="")
70 print("\n")
71
72 for list in self.field:
73 print(str(i) + "\t", end = '')
74 for item in list:
75 print(item.printCell() + " ", end='')
76 print("\t" + str(i))
77 i += 1
78
79 print("\n\t", end="")
80 for char in range(0,self.width):
81 print(chr(char+65) + " ", end="")
82 print("\n")
83
84 def cleared(self):
85 safe = 0
86 for y in range(len(self.field)):
87 for x in range(len(self.field[y])):
88 cell = self.field[y][x]
89 if cell.getIsMine() and cell.isSafe():
90 safe += 1
91
92 if safe == self.mines:
93 cleared = True
94 else:
95 cleared = False
96
97 return cleared
98
99
100
101 def guess(self,x,y):
102 cell = self.field[y][x]
103 if cell.getValue() == " ":
104 cell.uncover()
105 self.uncoverEmptyAround(x,y)
106 return False
107 elif cell.getValue() == 'x':
108 cell.uncover()
109 return True
110 else:
111 cell.uncover()
112 return False
113
114 def flag(self,x,y):
115 cell = self.field[y][x]
116 cell.toggleFlag() \ No newline at end of file
diff --git a/game.py b/game.py
deleted file mode 100644
index c8927b5..0000000
--- a/game.py
+++ /dev/null
@@ -1,126 +0,0 @@
1#!/usr/bin/python
2
3try:
4 input = raw_input
5except NameError:
6 pass
7
8from field import Field
9
10class Help:
11 def setState(self,l):
12 self.loop = l
13
14 def printHelp(self):
15 print("")
16 print("Listed commands:")
17 print(" try\t<x>\t<y>\tTests for mines")
18 print(" flag\t<x>\t<y>\tPlaces flag")
19 print(" ?\t<x>\t<y>\tPlaces questionmark")
20 print(" restart\t\tStarts new game")
21 print(" quit or exit\t\tQuits game")
22 print(" help\t\t\tPrints list of commands")
23 self.loop.command()
24
25class Setup:
26 def setState(self,l):
27 self.loop = l
28
29 def setup(self):
30 print("")
31 print("Select diffeculty:")
32 print(" 1. Beginner\t\t(10 mines, 9x9)")
33 print(" 2. Intermediate\t(40 mines, 16x16)")
34 print(" 3. Expert\t\t(99 mines, 30x16)")
35 print(" 4. Custom")
36 print("")
37
38 n = input("Choice: ")
39 n = n.split()
40 choice = int(n[0])
41
42 if choice == 1:
43 w = 9
44 h = 9
45 m = 10
46 elif choice == 2:
47 w = 16
48 h = 16
49 m = 40
50 elif choice == 3:
51 w = 30
52 h = 16
53 m = 99
54 elif choice == 4:
55 w = int(input("Width: "))
56 h = int(input("Heigt: "))
57 m = int(input("Mines: "))
58 else:
59 print(str(choice) + " is not a option.")
60 self.setup()
61
62 minefield = Field(w,h,m)
63 self.loop.setMinefield(minefield)
64 self.loop.command()
65
66class Loop:
67 def setStates(self,s,h,e):
68 self.setup = s
69 self.end = e
70 self.help = h
71
72 def setMinefield(self,m):
73 self.minefield = m
74
75 def command(self):
76 self.minefield.printField()
77 if(self.minefield.cleared()):
78 self.end.endGame(False)
79
80 command = input("Command >> ")
81 c = command.split(' ')
82
83 if c[0] == "try":
84 if self.minefield.guess(ord(c[1])-65,int(c[2])-1):
85 self.minefield.printField()
86 self.end.endGame(True)
87 self.command()
88 elif c[0] == "flag":
89 self.minefield.flag(ord(c[1])-65,int(c[2])-1)
90 self.command()
91 elif c[0] == "?":
92 self.minefield.question(ord(c[1])-65,int(c[2])-1)
93 self.command()
94 elif c[0] == "restart":
95 self.setup.setup()
96 elif c[0] == "quit" or c[0] == "exit":
97 exit()
98 elif c[0] == "help":
99 self.help.printHelp()
100 else:
101 print(c[0] + " is not a recognized command")
102 self.help.printHelp()
103
104class End:
105 def setState(self,s):
106 self.setup = s
107
108 def restart(self):
109 choice = input("Do you want to start again? [y/n] ")
110 choice = choice.split()
111 choice = choice[0]
112 if choice == "y":
113 self.setup.setup()
114 elif choice == "n":
115 exit()
116 else:
117 print(str(choice) + " is not a valid choice")
118 self.restart()
119
120 def endGame(self,m):
121 print("")
122 if m:
123 print("You hit a mine :o")
124 else:
125 print("You won :D")
126 self.restart() \ No newline at end of file
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""")
30
31 choice = int(
32 input("Choice: ").split()[0])
33
34 if choice == 1:
35 width = 9
36 height = 9
37 mines = 10
38 elif choice == 2:
39 width = 16
40 height = 16
41 mines = 40
42 elif choice == 3:
43 width = 30
44 height = 16
45 mines = 99
46 elif choice == 4:
47 width = int(input("Width: "))
48 height = int(input("Height: "))
49 mines = int(input("Mines: "))
50 else:
51 print(str(choice) + " is not a option.")
52 self.setup()
53
54 minefield = Field(width, height, mines)
55 self.loop.set_minefield(minefield)
56 self.loop.command()
57
58
59class Loop:
60 def set_states(self, setup, help, end):
61 self.setup = setup
62 self.end = end
63 self.help = help
64
65 def set_minefield(self, minefield):
66 self.minefield = minefield
67
68 def command(self):
69 self.minefield.print()
70 if self.minefield.cleared:
71 self.end.end_game(False)
72
73 command = input("Command >> ").split(' ')
74
75 if len(command) == 3:
76 coordinate = (ord(command[1]) - 65, int(command[2]) - 1)
77
78 if command[0] == "try":
79 if self.minefield.guess(*coordinate):
80 self.minefield.print()
81 self.end.end_game(dead=True)
82 return
83 self.command()
84 elif command[0] == "flag":
85 self.minefield.flag(*coordinate)
86 self.command()
87 # elif command[0] == "?":
88 # self.minefield.question(coordinate)
89 # self.command()
90 elif command[0] == "restart":
91 self.setup.setup()
92 elif command[0] == "quit" or command[0] == "exit":
93 exit()
94 elif command[0] == "help":
95 self.help.print()
96 else:
97 print(command[0] + " is not a recognized command")
98 self.help.print()
99
100
101class End:
102 def set_state(self, setup):
103 self.setup = setup
104
105 def restart(self):
106 choice = input("Do you want to start again? [y/n] ").split()[0]
107
108 if choice == "y":
109 self.setup.setup()
110 elif choice == "n":
111 exit()
112 else:
113 print(str(choice) + " is not a valid choice")
114 self.restart()
115
116 def end_game(self, dead):
117 print("")
118
119 if dead:
120 print("You hit a mine :o")
121 else:
122 print("You won :D")
123
124 self.restart()
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..8ac1344
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,20 @@
1#!/usr/bin/env python3
2
3from setuptools import setup, find_packages
4
5setup(
6 name='minesweeper-py',
7 version='1.0.0',
8 description=u'A command line minesweeper game',
9 long_description=open('README.rst').read(),
10 license='GPLv3',
11 author=u'Ton van der Lee',
12 author_email='t0m.vd.l33@gmail.com',
13 url='http://github.com/tomvanderlee/minesweeper-py',
14 packages= find_packages(),
15 entry_points={
16 'console_scripts': [
17 'minesweeper-py = minesweeper.__main__:main',
18 ]
19 }
20)