-
Notifications
You must be signed in to change notification settings - Fork 0
/
minesweeper.py
204 lines (184 loc) · 7.42 KB
/
minesweeper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# Python Class 1011
# Lesson 10 Problem 1
# Author: cinamon (172094)
from tkinter import *
import random
import sys
sys.setrecursionlimit(56000)
class MinesweeperCell(Label):
'''represents a Minesweeper cell'''
def __init__(self,master,coord):
'''MinesweeperCell(master,coord) -> MinesweeperCell
creates a new blank MinesweeperCell with (row,column) coord'''
Label.__init__(self,master,height=1,width=2,text='',\
bg='white',font=('Arial',18), relief='raised')
self.grid(row=coord[0], column=coord[1])
# create starting variables
self.master = master
self.coord = coord
self.colormap = ['gray','blue','darkgreen','red','purple',\
'maroon','cyan','black','yellow']
self.num = 0
self.isBomb = False
self.isRevealed = False
self.isFlagged = False
# set up listeners
self.bind('<Button-1>',self.reveal)
self.bind('<Button-3>',self.flag)
def get_num(self):
'''MinesweeperCell.get_num() -> int
returns the number of bombs near cell and sets that to self.num'''
self.num = 0
# get the list of cells that surround self
self.surrounding = self.master.get_surrounding(self.coord)
for cell in self.surrounding:
# add 1 if the cell is a bomb
if cell.is_bomb():
self.num += 1
return self.num
def make_bomb(self):
'''MinesweeperCell.make_bomb()
turns cell into a bomb'''
self.isBomb = True
def flag(self, coord):
'''MinesweeperCell.flag()
if cell is not revealed
will add a * if cell does not have one
will take away * if cell does have one'''
# will only allow you to flag if it isn't revealed
if not self.isRevealed:
# if it is already flagged
if self['text']=='*':
# unflag and add 1 back to bomb count
self['text'] = ''
self.master.bomb_count(1)
self.isFlagged = False
else:
# flag and subtract 1 from bomb count
self['text'] = '*'
self.master.bomb_count(-1)
self.isFlagged = True
def reveal(self,coord='place holder'):
'''MinesweeperCell.reveal(coord='place holder')
if not a bomb
reveals its number
if its number is 0
reveals surrounding cells'''
# if the player has clicked a bomb the player loses
if self.isBomb:
self.master.lose()
# if the cell is valid to reveal
elif not self.isRevealed and not self.isFlagged:
self['text'] = self.num # show the number of bombs near it
self['relief'] = 'sunken'
self['fg'] = self.colormap[self.num]
self['bg'] = 'gray'
self.isRevealed = True
self.master.check_win()
if self.num == 0:
self.reveal_surrounding()
def reveal_surrounding(self):
'''MinesweeperCell.reveal_surrounding()
reveals the numbers on surrounding cells'''
for cell in self.surrounding:
cell.reveal()
def get_coord(self):
'''MinesweeperCell.get_coord() -> tuple
returns cell's coordinates in the grid'''
return self.coord
def is_bomb(self):
'''MinesweeperCell.is_bomb() -> boolean
returns True if cell is a bomb, False if not'''
return self.isBomb
def is_flagged(self):
'''MinesweeperCell.is_flagged() -> boolean
returns True if cell is flagged, False if not'''
return self.isFlagged
def is_revealed(self):
'''MinesweeperCell.is_revealed() -> boolean
returns True if cell is revealed, False if not'''
return self.isRevealed
class MinesweeperGrid(Frame):
'''object for a Minesweeper grid'''
def __init__(self,master,width,height,numBombs):
'''MinesweeperGrid(self,master,width,height,numBombs) -> MinesweeperGrid
creates a width by height window for Minesweeper with numBombs hidden bombs'''
Frame.__init__(self,master,bg='black')
# set up variables
self.grid()
self.width = width
self.height = height
self.numBombs = numBombs
self.bombsLeft = numBombs
# make label for bomb count
self.countLabel = Label(self,text=self.numBombs,font=('Arial',24))
self.countLabel.grid(row=height+1,column=0, columnspan=width)
# create cells
self.cells = []
for row in range(self.height):
for column in range(self.width):
coord = (row,column)
self.cells.append(MinesweeperCell(self,coord))
# make some of them bombs
toBeBombs = random.sample(self.cells, numBombs)
for cell in toBeBombs:
cell.make_bomb()
# now that there are bombs, calculate each cells number
for cell in self.cells:
cell.get_num()
def get_surrounding(self,coord):
'''MinesweeperGrid.get_surrounding(coord) -> list
returns a list of surrounding MinesweeperCells'''
surrounding = []
# get the row and column separately
r = coord[0]
c = coord[1]
# create a match list, a list of coordinates that surround the cell,
# including the cell's coordinates
matchList = []
for row in [r-1,r,r+1]:
for column in [c-1,c,c+1]:
matchList.append((row,column))
# check each cell to see if its coordinates match that in matchList
for cell in self.cells:
# if it does, add it to surrounding list
if cell.get_coord() in matchList:
surrounding.append(cell)
return surrounding
def bomb_count(self,num):
'''MinesweeperGrid.bomb_count(num)
adds num to bombsLeft and displays'''
self.bombsLeft += num # add num
self.countLabel['text'] = str(self.bombsLeft) # display
def check_win(self):
'''MinesweeperGrid.check_win()
checks for win, if player has won, shows winning window'''
# used to have if bombsleft=0
revealed = 0
# count the number of revealed cells
for cell in self.cells:
if cell.is_revealed():
revealed += 1
# if that is equall to the number of cells that are not bombs
if revealed == self.width*self.height-self.numBombs:
self.win() # show winning message
def lose(self):
'''MinesweeperGrid.lose()
shows losing window and shows bombs in red'''
# show losing message window
messagebox.showerror('Minesweeper','KABOOM! You lose.',parent=self)
# show bombs in red
for cell in self.cells:
if cell.is_bomb():
cell['text'] = '*'
cell['bg'] = 'red'
def win(self):
'''MinesweeperGrid.win()
shows winningwindow'''
messagebox.showinfo('Minesweeper','Congratulations -- you won!',parent=self)
def play_minesweeper(width, height, numBombs):
root = Tk()
root.title('Minesweeper')
mg = MinesweeperGrid(root,width,height,numBombs)
root.mainloop()
play_minesweeper(12,10,15)