Skip to content

Instantly share code, notes, and snippets.

@hanss314
Last active March 2, 2018 01:51
Show Gist options
  • Save hanss314/13f08d8ee684c6be45d871656b35ceef to your computer and use it in GitHub Desktop.
Save hanss314/13f08d8ee684c6be45d871656b35ceef to your computer and use it in GitHub Desktop.
import curses
import time
from minesweeper import MineSweeper
def main(size=(10, 10), mines=10):
screen = curses.initscr()
height, width = screen.getmaxyx()
init_curses()
game = MineSweeper(*size, mines)
game_win = curses.newwin(
game.height + 2, 2 * game.width + 1, (height - game.height - 2) // 2, (width - 2 * game.width - 1) // 2
)
game_win.nodelay(True)
x = y = 0
start = end = None
while True:
draw_game(game, game_win, x, y)
if start is None:
screen.addstr((height - game.height - 4) // 2, (width - 5) // 2, "00.00")
elif end is None:
t = f"{time.time()-start:.2f}"
screen.addstr((height - game.height - 4) // 2, (width - len(t)) // 2, t)
else:
t = f"{end-start:.2f}"
screen.addstr((height - game.height - 4) // 2, (width - len(t)) // 2, t)
screen.refresh()
game_win.refresh()
pressed = game_win.getch()
if pressed == 113:
break
elif pressed == 107 and y < game.height - 1:
y += 1
elif pressed == 105 and y > 0:
y -= 1
elif pressed == 106 and x > 0:
x -= 1
elif pressed == 108 and x < game.width - 1:
x += 1
elif pressed == 32:
status = game.uncover(x, y)
if start == None: start = time.time()
if status != 0: end = time.time()
elif pressed == 102:
game.flag(x, y)
elif pressed == 114:
start = end = None
game = MineSweeper(*size, mines)
def init_curses():
curses.start_color()
curses.use_default_colors()
curses.curs_set(0)
curses.init_color(1, 0, 0, 0)
curses.init_color(1, 999, 999, 999)
curses.init_pair(1, 0, 255)
def draw_game(game: MineSweeper, window, i, j):
window.border()
for x, row in enumerate(game.to_string()):
for y, tile in enumerate(row):
if x == i and y == j:
window.addstr(y + 1, 2 * x + 1, tile, curses.color_pair(1))
else:
window.addstr(y + 1, 2 * x + 1, tile)
if __name__ == '__main__':
try:
main(size=(9, 9))
finally:
curses.endwin()
import random
class MineSweeper:
def __init__(self, width, height, mines):
self.width = width
self.height = height
self.mine_count = mines
self.mines_chosen = False
self.board = [
[
Tile(self, x, y) for y in range(self.height)
]for x in range(self.width)
]
def get_neighbors(self, x, y):
neighbors = [(x+dx, y+dy) for dx in range(-1, 2) for dy in range(-1, 2)]
neighbors.remove((x, y))
neighbors = [n for n in neighbors if 0 <= n[0] < self.width and 0 <= n[1] < self.height]
return [self.board[x][y] for x, y in neighbors]
def choose_mines(self, i, j):
self.mines_chosen = True
squares = [(x, y) for x in range(self.width) for y in range(self.height)]
if (i, j) in squares: squares.remove((i, j))
for x, y in random.sample(squares, self.mine_count):
self.board[x][y].mine = True
for x, row in enumerate(self.board):
for y, tile in enumerate(row):
tile.set_neighbors(self.get_neighbors(x, y))
def flag(self, x, y):
self.board[x][y].flag()
def uncover(self, x, y):
if not self.mines_chosen:
self.choose_mines(x, y)
self.board[x][y].uncover()
if self.board[x][y].mine:
self.uncover_all()
return -1
return self.checkwin()
def checkwin(self):
for row in self.board:
for tile in row:
if not tile.uncovered and not tile.mine:
return 0
return 1
def uncover_all(self):
for row in self.board:
for tile in row:
if not tile.uncovered:
tile.uncovered = True
def to_string(self):
return [
[tile.to_char() for tile in row]
for row in self.board
]
class Tile:
def __init__(self, ms: MineSweeper, x, y, mine=False):
self.ms = ms
self.x, self.y = x, y
self.mine = mine
self.flagged = False
self.uncovered = False
self.neighbor_count = 0
def flag(self):
if self.uncovered: return
self.flagged = not self.flagged
def uncover(self):
if self.flagged:
return
if not self.uncovered:
self.uncovered = True
if self.neighbor_count == 0 and not self.mine:
for neighbor in self.ms.get_neighbors(self.x, self.y):
neighbor.uncover()
else:
flagged = len([tile for tile in self.ms.get_neighbors(self.x, self.y) if tile.flagged])
if flagged == self.neighbor_count:
for neighbor in self.ms.get_neighbors(self.x, self.y):
if not neighbor.uncovered: neighbor.uncover()
def set_neighbors(self, neighbors):
self.neighbor_count = 0
for neighbor in neighbors:
if neighbor.mine:
self.neighbor_count += 1
def to_char(self):
if self.uncovered:
return '*' if self.mine else str(self.neighbor_count)
else:
return 'F' if self.flagged else 'N'
if __name__ == '__main__':
minesweeper_board = MineSweeper(10, 10, 10)
# print(minesweeper_board.to_string())
while True:
print('\n'.join(' '.join(x) for x in minesweeper_board.to_string()))
coords = input('> ')
flag = 'f' in coords
coords = list(map(int, coords.split(' ')[:2]))
if not flag:
state = minesweeper_board.uncover(*coords)
print(state)
if state != 0: break
else:
minesweeper_board.flag(*coords)
print('\n'.join(' '.join(x) for x in minesweeper_board.to_string()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment