11# Python Version 2.7.3
22# File: minesweeper.py
33
4- from Tkinter import *
5- import tkMessageBox
4+ from tkinter import *
5+ from tkinter import messagebox as tkMessageBox
66import random
7+ import platform
78from collections import deque
89
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+
917class Minesweeper :
1018
1119 def __init__ (self , master ):
1220
1321 # 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+ }
2030 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" ))
2232
2333 # set up frame
2434 frame = Frame (master )
@@ -39,37 +49,40 @@ def __init__(self, master):
3949 x_coord = 1
4050 y_coord = 0
4151 for x in range (0 , 100 ):
42- mine = 0
52+ isMine = 0
53+
4354 # tile image changeable for debug reasons:
44- gfx = self .tile_plain
55+ gfx = self .tiles ["plain" ]
56+
4557 # currently random amount of mines
4658 if random .uniform (0.0 , 1.0 ) < 0.1 :
47- mine = 1
59+ isMine = 1
4860 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:
6578 y_coord += 1
6679 if y_coord == 10 :
6780 y_coord = 0
6881 x_coord += 1
69-
82+
7083 # lay buttons in grid
7184 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" ] )
7386
7487 # find nearby mines and display number on tile
7588 for key in self .buttons :
@@ -91,10 +104,10 @@ def __init__(self, master):
91104 if self .check_for_mines (key + 11 ):
92105 nearby_mines += 1
93106 # 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:
96109 # 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])
98111
99112 #add mine and count at the end
100113 self .label2 = Label (frame , text = "Mines: " + str (self .mines ))
@@ -107,7 +120,7 @@ def __init__(self, master):
107120
108121 def check_for_mines (self , key ):
109122 try :
110- if self .buttons [key ][1 ] == 1 :
123+ if self .buttons [key ]["isMine" ] == 1 :
111124 return True
112125 except KeyError :
113126 pass
@@ -119,60 +132,60 @@ def rclicked_wrapper(self, x):
119132 return lambda Button : self .rclicked (self .buttons [x ])
120133
121134 def lclicked (self , button_data ):
122- if button_data [1 ] == 1 : #if a mine
135+ if button_data ["isMine" ] == 1 :
123136 # show all mines and check for flags
124137 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" ] )
129142 # end game
130143 self .gameover ()
131144 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" ])
136149 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 ])
138151 # 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
141154 self .clicked += 1
142155 if self .clicked == 100 - self .mines :
143156 self .victory ()
144157
145158 def rclicked (self , button_data ):
146159 # 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 )
151164 # if a mine
152- if button_data [1 ] == 1 :
165+ if button_data ["isMine" ] == 1 :
153166 self .correct_flags += 1
154167 self .flags += 1
155168 self .update_flags ()
156169 # 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" ]))
161174 # if a mine
162- if button_data [1 ] == 1 :
175+ if button_data ["isMine" ] == 1 :
163176 self .correct_flags -= 1
164177 self .flags -= 1
165178 self .update_flags ()
166179
167180 def check_tile (self , key , queue ):
168181 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" ] )
172185 queue .append (key )
173186 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
176189 self .clicked += 1
177190 except KeyError :
178191 pass
@@ -190,7 +203,7 @@ def clear_empty_tiles(self, main_key):
190203 self .check_tile (key + 9 , queue ) #bottom right
191204 self .check_tile (key + 10 , queue ) #bottom middle
192205 self .check_tile (key + 11 , queue ) #bottom left
193-
206+
194207 def gameover (self ):
195208 tkMessageBox .showinfo ("Game Over" , "You Lose!" )
196209 global root
0 commit comments