code cleanup, added comments, refactoring

master
panki27 7 years ago
parent 2ee705a6ff
commit 7008c6e55a

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
#TODO: highscore #TODO: highscore, monochrome, expect ctrl c, flags red if too many
import random, io, sys, time, os import random, io, sys, time, os
import curses import curses
@ -12,6 +12,8 @@ UNKNOWN = -3
FLAG_MINE = -4 FLAG_MINE = -4
score_x, score_y = 0, 0 score_x, score_y = 0, 0
CURSOR_POSITION=[0,0]
OFFSET = 11 OFFSET = 11
STARTTIME = 0 STARTTIME = 0
@ -21,13 +23,14 @@ SCREEN = 0
firstmove = False firstmove = False
FIELD_GENERATED = False FIELD_GENERATED = False
CURSOR_POSITION=[0,0]
FIELDS_CLEARED = 0 FIELDS_CLEARED = 0
width, height = 9, 9 width, height = 9, 9
MINECOUNT = 10 MINECOUNT = 10
FLAGCOUNT = 0 FLAGCOUNT = 0
clWhite, clRed, clCyan, clBlue, clYellow, clGreen, clInverted = None, None, None, None, None, None, None #can only be setup after curses has loaded
difficulty = 'medium' difficulty = 'medium'
param_error = 'minebash: Invalid parameters. See \'minebash.py ?\' for help ' param_error = 'minebash: Invalid parameters. See \'minebash.py ?\' for help '
@ -81,17 +84,13 @@ if len(sys.argv) > 1:
print(param_error) print(param_error)
sys.exit(0) sys.exit(0)
playfield = [[UNKNOWN for x in range(width)] for y in range(height)] playfield = [[UNKNOWN for x in range(width)] for y in range(height)]
#playfield = 0
#stdscr = curses.initscr()
#curses.noecho()
#curses.cbreak()
headline = '┌' headline = '┌'
midline = '├' midline = '├'
tailline = '└' tailline = '└'
def setup_strings(colcount): def setup_strings(colcount):
#setup lines to print #setup lines to print at the end and start of the matrix, aswell as between rows
global headline, midline, tailline global headline, midline, tailline
for i in range(colcount): for i in range(colcount):
if i == width-1: if i == width-1:
@ -111,25 +110,27 @@ def endgame(msg=''):
def calculate_hint(col, row): def calculate_hint(col, row):
hint = 0 hint = 0
if playfield[row][col] != MINE: if playfield[row][col] != MINE:
#step through the surrounding 8 (or less) fields
for x in range(col-1, col+2): for x in range(col-1, col+2):
if x >= 0 and x < len(playfield): if x >= 0 and x < len(playfield):
for y in range(row-1, row+2): for y in range(row-1, row+2):
if y >= 0 and y < len(playfield[0]): if y >= 0 and y < len(playfield[0]):
if playfield[y][x] == MINE or playfield[y][x] == FLAG_MINE: if playfield[y][x] == MINE or playfield[y][x] == FLAG_MINE:
#add the mines together
hint+=1 hint+=1
else: else:
hint = MINE hint = MINE
return hint return hint
def setup_playfield(w, h, x, y): def setup_playfield(w, h, x, y):
#do this only once [AFTER THE FIRST GUESS] -> Done
#randomly distribute mines across the field
global playfield, FIELD_GENERATED, STARTTIME global playfield, FIELD_GENERATED, STARTTIME
minesleft = MINECOUNT minesleft = MINECOUNT
#randomly distribute mines across the field
while minesleft > 0: while minesleft > 0:
randx = random.randint(0, width-1) randx = random.randint(0, width-1)
randy = random.randint(0, height-1) randy = random.randint(0, height-1)
#make sure the users first guess isn't a mine
if playfield[randy][randx] != MINE and ([randx, randy] != CURSOR_POSITION): if playfield[randy][randx] != MINE and ([randx, randy] != CURSOR_POSITION):
playfield[randy][randx] = MINE playfield[randy][randx] = MINE
minesleft -= 1 minesleft -= 1
@ -183,75 +184,100 @@ def gameover(win):
key = SCREEN.getch() key = SCREEN.getch()
if key == ord('q'): return False if key == ord('q'): return False
elif key == ord('r'): return True elif key == ord('r'): return True
# os.execl(sys.executable, sys.executable, *sys.argv)
def getTileLeft(x, y):
cell = playfield[y][x]
s = ''
if [x, y] == CURSOR_POSITION:
s += '['
color = clGreen
else:
s += ' '
color = clWhite
return s, color
def getTileMiddle(x,y):
cell = playfield[y][x]
s = ''
if cell == 0:
s += ' '
color = clWhite
elif cell == UNKNOWN or cell == MINE:
s += ' '
color = clInverted
elif cell == FLAG_MINE or cell == FLAG:
s += 'P'
color = clRed
else:
# coloring the hints
if cell == 1: color = clCyan #cyan
elif cell == 2: color = clBlue #blue
else: color = clYellow #yellow
s += str(cell)
return s, color
def getTileRight(x, y):
cell = playfield[y][x]
selected = False
s = ''
if [x, y] == CURSOR_POSITION:
s += ']'
color = clGreen
else:
s += ' '
color = clWhite
return s, color
def print_playfield(playfield, screen): def print_playfield(playfield, screen):
global score_x, score_y global score_x, score_y
#print the matrix
currentline = 0 currentline = 0
screen.addstr(currentline, 10, headline, curses.color_pair(1)) screen.addstr(currentline, OFFSET-1, headline, clWhite)
currentline +=1 currentline +=1
#print headline
for rowindex, row in enumerate(playfield): for rowindex, row in enumerate(playfield):
screen.addstr(currentline, 10, '│') screen.addstr(currentline, OFFSET-1, '│')
pos = OFFSET pos = OFFSET
for colindex, cell in enumerate(row): for colindex, cell in enumerate(row):
# is the cell selected? part, color = getTileLeft(colindex, rowindex)
selected = False screen.addstr(currentline, pos, part, color)
if [colindex, rowindex] == CURSOR_POSITION:
screen.addstr(currentline, pos, '[')
selected = True
else:
screen.addstr(currentline, pos, ' ')
pos += 1 pos += 1
# did we find a hint? part, color = getTileMiddle(colindex, rowindex)
if cell > 0: screen.addstr(currentline, pos, part, color)
if cell == 1: color = curses.color_pair(3) #cyan pos += 1
elif cell == 2: color = curses.color_pair(4) #blue part, color = getTileRight(colindex, rowindex)
else: color = curses.color_pair(5) #yellow screen.addstr(currentline, pos, part, color)
screen.addstr(currentline, pos, str(cell), color)
elif cell == 0:
screen.addstr(currentline, pos, ' ')
elif cell == UNKNOWN or cell == MINE:
screen.addstr(currentline, pos, '#', curses.color_pair(7)) #rowstring+= '#'
elif cell == FLAG_MINE or cell == FLAG:
screen.addstr(currentline, pos, 'P', curses.color_pair(2)) #rowstring += 'P'
#elif cell == MINE:
# rowstring += 'X'
pos += 1 pos += 1
if selected:
screen.addstr(currentline, pos, ']│')
else:
screen.addstr(currentline, pos, '│') screen.addstr(currentline, pos, '│')
pos += 2 pos += 1
currentline +=1 currentline +=1
if(rowindex < len(row)-1): if(rowindex < len(row)-1):
screen.addstr(currentline, 10, midline) screen.addstr(currentline, 10, midline)
currentline +=1 currentline +=1
screen.addstr(currentline, 10, tailline) screen.addstr(currentline, 10, tailline)
currentline +=1 currentline +=1
#get a centered position below the playfield:
score_y = currentline score_y = currentline
score_x = int(pos/2) score_x = int(pos/2)
#print tailline
def hit(x, y, recursive_call=False): def hit(x, y):
global playfield, FIELDS_CLEARED global playfield, FIELDS_CLEARED
if playfield[y][x] == UNKNOWN: if playfield[y][x] == UNKNOWN:
#get the number that should be printed in the cell
hint = calculate_hint(x, y) hint = calculate_hint(x, y)
playfield[y][x] = hint playfield[y][x] = hint
FIELDS_CLEARED += 1 FIELDS_CLEARED += 1
if not recursive_call and hint == NOTHING: if hint == NOTHING:
#we hit a 0 or empty field, so we need to hit all the fields around it
#first, step through the 8 or less surrounding fields
for i in range(x-1, x+2): for i in range(x-1, x+2):
for j in range(y-1, y+2): for j in range(y-1, y+2):
if i >= 0 and i < width: if i >= 0 and i < width:
if j >= 0 and j< height: if j >= 0 and j< height:
if playfield[j][i] == UNKNOWN: if playfield[j][i] == UNKNOWN:
hint = calculate_hint(i, j) #player has not opened this field yet
if hint > 0 and hint<3:
hit(i,j, True)
if hint == 0:
hit(i,j) hit(i,j)
elif playfield[y][x] == MINE: elif playfield[y][x] == MINE:
#gameover(False)
return True return True
def check_score(): def check_score():
@ -260,7 +286,6 @@ def check_score():
def place_flag(x, y): def place_flag(x, y):
global playfield, FLAGCOUNT global playfield, FLAGCOUNT
#playfield[y][x] = playfield[y][x]
if playfield[y][x] == MINE: if playfield[y][x] == MINE:
playfield[y][x] = FLAG_MINE playfield[y][x] = FLAG_MINE
FLAGCOUNT += 1 FLAGCOUNT += 1
@ -297,6 +322,7 @@ def handle_input(k):
else: else:
CURSOR_POSITION[1] = 0 CURSOR_POSITION[1] = 0
elif k == ord('f'): elif k == ord('f'):
# only place flags after placing mines
if FIELD_GENERATED: if FIELD_GENERATED:
place_flag(CURSOR_POSITION[0], CURSOR_POSITION[1]) place_flag(CURSOR_POSITION[0], CURSOR_POSITION[1])
elif k == ord(' '): elif k == ord(' '):
@ -306,26 +332,33 @@ def handle_input(k):
return hit(CURSOR_POSITION[0], CURSOR_POSITION[1]) return hit(CURSOR_POSITION[0], CURSOR_POSITION[1])
return False return False
def print_score(screen): def print_footer(screen):
scorestr = 'Mines: {} Flags: {} Difficulty: {}'.format(MINECOUNT, FLAGCOUNT, difficulty) scorestr = 'Mines: {} Flags: {} Difficulty: {}'.format(MINECOUNT, FLAGCOUNT, difficulty)
xpos = int((score_x) - (len(scorestr)/2)) + int(OFFSET/2)
if xpos < 0: xpos = 0
screen.addstr(score_y, xpos, scorestr)
def print_controls(screen):
controlstr = 'Arrow Keys: Move F: Place flag Space: Open field' controlstr = 'Arrow Keys: Move F: Place flag Space: Open field'
xpos = int((score_x) - len(controlstr)/2) + int(OFFSET/2) score_xpos = int((score_x) - (len(scorestr)/2)) + int(OFFSET/2)
if xpos < 0: xpos = 0 control_xpos = int((score_x) - len(controlstr)/2) + int(OFFSET/2)
screen.addstr(score_y +1, xpos, controlstr) if score_xpos < 0: score_xpos = 0
if control_xpos < 0: control_xpos = 0
screen.addstr(score_y, score_xpos, scorestr)
screen.addstr(score_y+1, control_xpos, controlstr)
def setup_colors(): def setup_colors():
global clWhite, clRed, clCyan, clBlue, clYellow, clGreen, clInverted
curses.start_color() curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) #curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK)
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK)
curses.init_pair(3, curses.COLOR_CYAN, curses.COLOR_BLACK) curses.init_pair(3, curses.COLOR_CYAN, curses.COLOR_BLACK)
curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLACK) curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLACK)
curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK) curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK)
curses.init_pair(6, curses.COLOR_GREEN, curses.COLOR_BLACK)
curses.init_pair(7, curses.COLOR_WHITE, curses.COLOR_WHITE) curses.init_pair(7, curses.COLOR_WHITE, curses.COLOR_WHITE)
clWhite = curses.color_pair(0) #hardwired
clRed = curses.color_pair(2)
clCyan = curses.color_pair(3)
clBlue = curses.color_pair(4)
clYellow = curses.color_pair(5)
clGreen = curses.color_pair(6)
clInverted = curses.color_pair(7)
def reset(): def reset():
global firstmove, playfield, FIELD_GENERATED, FIELDS_CLEARED, CURSOR_POSITION global firstmove, playfield, FIELD_GENERATED, FIELDS_CLEARED, CURSOR_POSITION
@ -335,15 +368,12 @@ def reset():
FIELDS_CLEARED = 0 FIELDS_CLEARED = 0
CURSOR_POSITION = [0,0] CURSOR_POSITION = [0,0]
def main(stdscr): def main(stdscr):
global SCREEN, firstmove, FIELD_GENERATED, FIELDS_CLEARED, playfield, CURSOR_POSITION global SCREEN, firstmove, FIELD_GENERATED, FIELDS_CLEARED, playfield, CURSOR_POSITION
SCREEN = stdscr SCREEN = stdscr
stdscr.clear() stdscr.clear()
setup_strings(width) setup_strings(width)
setup_colors() setup_colors()
#generate mines:
#TODO: user input
while(True): while(True):
reset() reset()
while(True): #game loop while(True): #game loop
@ -356,18 +386,19 @@ def main(stdscr):
break break
else: endgame() else: endgame()
if (firstmove) and not (FIELD_GENERATED): if (firstmove) and not (FIELD_GENERATED):
#generate the field
setup_playfield(width, height, CURSOR_POSITION[0], CURSOR_POSITION[1]) setup_playfield(width, height, CURSOR_POSITION[0], CURSOR_POSITION[1])
#do this a second time, because we didn't know what the field would be the first time
handle_input(key) handle_input(key)
STARTTIME = time.time() STARTTIME = time.time()
if check_score(): if check_score():
#player wins!
restart = gameover(True) # does user want restart? restart = gameover(True) # does user want restart?
if restart: if restart:
stdscr.clear() stdscr.clear()
break break
else: endgame() else: endgame()
print_score(stdscr) print_footer(stdscr)
print_controls(stdscr)
stdscr.refresh() stdscr.refresh()
#stdscr.getkey()
if __name__ == "__main__": if __name__ == "__main__":
wrapper(main) wrapper(main)
Loading…
Cancel
Save