Minesweeper expects the user to enter properly bounded integers for moves. Should the user enter something unexpected, the resulting exception can be caught and handled in some way other than exiting.
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 | "minesweeper"
from UserDict import UserDict
class Game(UserDict):
def __init__(self, **kwargs):
"initialize board"
d = {"ROWS":8,"COLS":8,"BOMBS":10}
d.update(kwargs)
UserDict.__init__(self,d)
self.reset()
def random_bombs(self):
"returns list of coordinates in tuple form"
from random import choice
coords = []
for i in range(self['BOMBS']):
while 1:
row_idx = choice(range(self['ROWS']))
col_idx = choice(range(self['COLS']))
if not (row_idx,col_idx) in coords:
break
coords.append((row_idx,col_idx))
return coords
def inc_neighbors(self,row_idx,col_idx):
for r, c in [(r,c) for r in (-1,0,1) for c in (-1,0,1)]:
try:
ri = r + row_idx
ci = c + col_idx
if ri < 0 or ci < 0:
raise IndexError, "smaller than 0"
v = self['BOARD'][ri][ci]
self['BOARD'][ri][ci] = v + 1
except:
pass
def reset(self):
"reset board"
self['BOARD'] = map ((lambda x,d=self: [0] * d['ROWS']),
range(self['COLS']))
self['PLAYER'] = map ((lambda x,d=self: ['.'] * d['ROWS']),
range(self['COLS']))
for (row,col) in self.random_bombs():
self['BOARD'][row][col] = 'B'
self.inc_neighbors(row,col)
def to_string(self,board):
str = ''
for r in board:
rstr = ''
for c in r:
rstr = rstr + '%s' % c
str = str + '%s\n' % rstr
return str
def __repr__(self):
board = self['BOARD']
return self.to_string(board)
def find_edges(self,row,col):
"check up down left right"
board = self['BOARD']
player = self['PLAYER']
to_explore = [(row,col)]
try:
if row < 0 or col < 0:
raise IndexError, "smaller than 0"
if player[row][col] is '.':
v = board[row][col]
player[row][col] = v
##print "updated,", row, col
if v is 0:
for (r,c) in zip((0,0,-1,-1,-1,1,1,1),(-1,1,0,-1,1,0,-1,1)):
ri = row + r
ci = col + c
self.find_edges(ri,ci)
except:
pass
def venture(self,row,col):
msg = ''
board = self['BOARD']
player = self['PLAYER']
v = board[row][col]
if v is 'B':
player[row][col] = 'X'
msg = 'You lost!\n'
elif v is 0:
self.find_edges(row,col)
else:
player[row][col] = v
if self.winp():
msg = 'You won!\n'
print msg + self.to_string(player)
def winp(self):
for (cb, cp) in zip(self['BOARD'], self['PLAYER']):
cp = list(cp)
for i in range(len(cp)):
if cp[i] is '.': cp[i] = 'B'
if tuple(cp) != tuple(cb):
return 0
return 1
if __name__ == '__main__':
import string
g = Game(ROWS=8,COLS=8, BOMBS=10)
print '*' * 80
print '*', "solution:"
print '*' * 80
print g
while 1:
try:
r = string.atoi( raw_input('row:'))
c = string.atoi( raw_input('col:'))
g.venture(r,c)
except:
import sys
print sys.exc_type, sys.exc_value
if sys.exc_type is KeyboardInterrupt:
raise KeyboardInterrupt
print '*' * 80
print '*', "solution:"
print '*' * 80
print g
|
Tags: ui
Multiple except:s. A slightly nicer way of doing this is to explicitly catch the exceptions you're not interested in, rather than checking the exception type (for which purpose, by the way, the identity operator seems rather strict). It's also useful to print a debug message when you're testing the code, because the except: can easily mask real problems. For example, if you have a function called load which can raise IOError:
string.atoi()
is deprecated. you should useint()
instead