1
1
# Python Version 2.7.3
2
2
# File: minesweeper.py
3
3
4
- from Tkinter import *
5
- import tkMessageBox
4
+ from tkinter import *
5
+ from tkinter import messagebox as tkMessageBox
6
6
import random
7
+ import platform
7
8
from collections import deque
8
9
10
+ STATE_DEFAULT = 0
11
+ STATE_CLICKED = 1
12
+ STATE_FLAGGED = 2
13
+
14
+ BTN_CLICK = "<Button-1>"
15
+ BTN_FLAG = "<Button-2>" if platform .system () == 'Darwin' else "<Button-3>"
16
+
9
17
class Minesweeper :
10
18
11
19
def __init__ (self , master ):
12
20
13
21
# import images
14
- self .tile_plain = PhotoImage (file = "images/tile_plain.gif" )
15
- self .tile_clicked = PhotoImage (file = "images/tile_clicked.gif" )
16
- self .tile_mine = PhotoImage (file = "images/tile_mine.gif" )
17
- self .tile_flag = PhotoImage (file = "images/tile_flag.gif" )
18
- self .tile_wrong = PhotoImage (file = "images/tile_wrong.gif" )
19
- self .tile_no = []
22
+ self .tiles = {
23
+ "plain" : PhotoImage (file = "images/tile_plain.gif" ),
24
+ "clicked" : PhotoImage (file = "images/tile_clicked.gif" ),
25
+ "mine" : PhotoImage (file = "images/tile_mine.gif" ),
26
+ "flag" : PhotoImage (file = "images/tile_flag.gif" ),
27
+ "wrong" : PhotoImage (file = "images/tile_wrong.gif" ),
28
+ "numbers" : []
29
+ }
20
30
for x in range (1 , 9 ):
21
- self .tile_no .append (PhotoImage (file = "images/tile_" + str (x )+ ".gif" ))
31
+ self .tiles [ "numbers" ] .append (PhotoImage (file = "images/tile_" + str (x )+ ".gif" ))
22
32
23
33
# set up frame
24
34
frame = Frame (master )
@@ -39,37 +49,40 @@ def __init__(self, master):
39
49
x_coord = 1
40
50
y_coord = 0
41
51
for x in range (0 , 100 ):
42
- mine = 0
52
+ isMine = 0
53
+
43
54
# tile image changeable for debug reasons:
44
- gfx = self .tile_plain
55
+ gfx = self .tiles ["plain" ]
56
+
45
57
# currently random amount of mines
46
58
if random .uniform (0.0 , 1.0 ) < 0.1 :
47
- mine = 1
59
+ isMine = 1
48
60
self .mines += 1
49
- # 0 = Button widget
50
- # 1 = if a mine y/n (1/0)
51
- # 2 = state (0 = unclicked, 1 = clicked, 2 = flagged)
52
- # 3 = button id
53
- # 4 = [x, y] coordinates in the grid
54
- # 5 = nearby mines, 0 by default, calculated after placement in grid
55
- self .buttons [x ] = [ Button (frame , image = gfx ),
56
- mine ,
57
- 0 ,
58
- x ,
59
- [x_coord , y_coord ],
60
- 0 ]
61
- self .buttons [x ][0 ].bind ('<Button-1>' , self .lclicked_wrapper (x ))
62
- self .buttons [x ][0 ].bind ('<Button-3>' , self .rclicked_wrapper (x ))
63
-
64
- # calculate coords:
61
+
62
+ self .buttons [x ] = {
63
+ "id" : x ,
64
+ "isMine" : isMine ,
65
+ "state" : STATE_DEFAULT ,
66
+ "coords" : {
67
+ "x" : x_coord ,
68
+ "y" : y_coord
69
+ },
70
+ "widget" : Button (frame , image = gfx ),
71
+ "mines" : 0 # calculated after placement in grid
72
+ }
73
+
74
+ self .buttons [x ]["widget" ].bind (BTN_CLICK , self .lclicked_wrapper (x ))
75
+ self .buttons [x ]["widget" ].bind (BTN_FLAG , self .rclicked_wrapper (x ))
76
+
77
+ # calculate coords for next loop:
65
78
y_coord += 1
66
79
if y_coord == 10 :
67
80
y_coord = 0
68
81
x_coord += 1
69
-
82
+
70
83
# lay buttons in grid
71
84
for key in self .buttons :
72
- self .buttons [key ][0 ].grid ( row = self .buttons [key ][4 ][ 0 ], column = self .buttons [key ][4 ][ 1 ] )
85
+ self .buttons [key ]["widget" ].grid ( row = self .buttons [key ]["coords" ][ "x" ], column = self .buttons [key ]["coords" ][ "y" ] )
73
86
74
87
# find nearby mines and display number on tile
75
88
for key in self .buttons :
@@ -91,10 +104,10 @@ def __init__(self, master):
91
104
if self .check_for_mines (key + 11 ):
92
105
nearby_mines += 1
93
106
# store mine count in button data list
94
- self .buttons [key ][5 ] = nearby_mines
95
- #if self.buttons[key][1 ] != 1:
107
+ self .buttons [key ]["mines" ] = nearby_mines
108
+ #if self.buttons[key]["isMine" ] != 1:
96
109
# if nearby_mines != 0:
97
- # self.buttons[key][0 ].config(image = self.tile_no [nearby_mines-1])
110
+ # self.buttons[key]["widget" ].config(image = self.tiles["numbers"] [nearby_mines-1])
98
111
99
112
#add mine and count at the end
100
113
self .label2 = Label (frame , text = "Mines: " + str (self .mines ))
@@ -107,7 +120,7 @@ def __init__(self, master):
107
120
108
121
def check_for_mines (self , key ):
109
122
try :
110
- if self .buttons [key ][1 ] == 1 :
123
+ if self .buttons [key ]["isMine" ] == 1 :
111
124
return True
112
125
except KeyError :
113
126
pass
@@ -119,60 +132,60 @@ def rclicked_wrapper(self, x):
119
132
return lambda Button : self .rclicked (self .buttons [x ])
120
133
121
134
def lclicked (self , button_data ):
122
- if button_data [1 ] == 1 : #if a mine
135
+ if button_data ["isMine" ] == 1 :
123
136
# show all mines and check for flags
124
137
for key in self .buttons :
125
- if self .buttons [key ][1 ] != 1 and self .buttons [key ][2 ] == 2 :
126
- self .buttons [key ][0 ].config (image = self .tile_wrong )
127
- if self .buttons [key ][1 ] == 1 and self .buttons [key ][2 ] != 2 :
128
- self .buttons [key ][0 ].config (image = self .tile_mine )
138
+ if self .buttons [key ]["isMine" ] == 0 and self .buttons [key ]["state" ] == STATE_FLAGGED :
139
+ self .buttons [key ]["widget" ].config (image = self .tiles [ "wrong" ] )
140
+ if self .buttons [key ]["isMine" ] == 1 and self .buttons [key ]["state" ] != STATE_FLAGGED :
141
+ self .buttons [key ]["widget" ].config (image = self .tiles [ "mine" ] )
129
142
# end game
130
143
self .gameover ()
131
144
else :
132
- #change image
133
- if button_data [5 ] == 0 :
134
- button_data [0 ].config (image = self .tile_clicked )
135
- self .clear_empty_tiles (button_data [3 ])
145
+ # change image
146
+ if button_data ["mines" ] == 0 :
147
+ button_data ["widget" ].config (image = self .tiles [ "clicked" ] )
148
+ self .clear_empty_tiles (button_data ["id" ])
136
149
else :
137
- button_data [0 ].config (image = self .tile_no [ button_data [5 ]- 1 ])
150
+ button_data ["widget" ].config (image = self .tiles [ "numbers" ][ button_data ["mines" ]- 1 ])
138
151
# if not already set as clicked, change state and count
139
- if button_data [2 ] != 1 :
140
- button_data [2 ] = 1
152
+ if button_data ["state" ] != STATE_CLICKED :
153
+ button_data ["state" ] = STATE_CLICKED
141
154
self .clicked += 1
142
155
if self .clicked == 100 - self .mines :
143
156
self .victory ()
144
157
145
158
def rclicked (self , button_data ):
146
159
# if not clicked
147
- if button_data [2 ] == 0 :
148
- button_data [0 ].config (image = self .tile_flag )
149
- button_data [2 ] = 2
150
- button_data [0 ].unbind ('<Button-1>' )
160
+ if button_data ["state" ] == STATE_DEFAULT :
161
+ button_data ["widget" ].config (image = self .tiles [ "flag" ] )
162
+ button_data ["state" ] = STATE_FLAGGED
163
+ button_data ["widget" ].unbind (BTN_CLICK )
151
164
# if a mine
152
- if button_data [1 ] == 1 :
165
+ if button_data ["isMine" ] == 1 :
153
166
self .correct_flags += 1
154
167
self .flags += 1
155
168
self .update_flags ()
156
169
# if flagged, unflag
157
- elif button_data [2 ] == 2 :
158
- button_data [0 ].config (image = self .tile_plain )
159
- button_data [2 ] = 0
160
- button_data [0 ].bind ('<Button-1>' , self .lclicked_wrapper (button_data [3 ]))
170
+ elif button_data ["state" ] == 2 :
171
+ button_data ["widget" ].config (image = self .tiles [ "plain" ] )
172
+ button_data ["state" ] = 0
173
+ button_data ["widget" ].bind (BTN_CLICK , self .lclicked_wrapper (button_data ["id" ]))
161
174
# if a mine
162
- if button_data [1 ] == 1 :
175
+ if button_data ["isMine" ] == 1 :
163
176
self .correct_flags -= 1
164
177
self .flags -= 1
165
178
self .update_flags ()
166
179
167
180
def check_tile (self , key , queue ):
168
181
try :
169
- if self .buttons [key ][2 ] == 0 :
170
- if self .buttons [key ][5 ] == 0 :
171
- self .buttons [key ][0 ].config (image = self .tile_clicked )
182
+ if self .buttons [key ]["state" ] == STATE_DEFAULT :
183
+ if self .buttons [key ]["mines" ] == 0 :
184
+ self .buttons [key ]["widget" ].config (image = self .tiles [ "clicked" ] )
172
185
queue .append (key )
173
186
else :
174
- self .buttons [key ][0 ].config (image = self .tile_no [ self .buttons [key ][5 ]- 1 ])
175
- self .buttons [key ][2 ] = 1
187
+ self .buttons [key ]["widget" ].config (image = self .tiles [ "numbers" ][ self .buttons [key ]["mines" ]- 1 ])
188
+ self .buttons [key ]["state" ] = STATE_CLICKED
176
189
self .clicked += 1
177
190
except KeyError :
178
191
pass
@@ -190,7 +203,7 @@ def clear_empty_tiles(self, main_key):
190
203
self .check_tile (key + 9 , queue ) #bottom right
191
204
self .check_tile (key + 10 , queue ) #bottom middle
192
205
self .check_tile (key + 11 , queue ) #bottom left
193
-
206
+
194
207
def gameover (self ):
195
208
tkMessageBox .showinfo ("Game Over" , "You Lose!" )
196
209
global root
0 commit comments