Skip to content

Instantly share code, notes, and snippets.

@ZhanruiLiang
Created June 3, 2012 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZhanruiLiang/2862177 to your computer and use it in GitHub Desktop.
Save ZhanruiLiang/2862177 to your computer and use it in GitHub Desktop.
hjkl mine sweeper
#!/usr/bin/env python
import pygame as pg
from collections import deque
import random
W, H = 1200, 1000
BarW = 100
gw, gh = 30, 20
gs = min((W - BarW)/gw, H/gh)
sep = 1
FPS = 20
MINE = 'm'
MARK = 'f'
DIR = [(-1, 0), (0, -1), (1, 0), (0, 1), (-1, -1), (-1, 1), (1, -1), (1, 1)]
class Sweeper:
def __init__(self):
self.ri, self.rj = 0, 0
self.si, self.sj = 0, 0
self.image = pg.Surface((gs, gs)).convert_alpha()
self.image.fill((0x55, 0x22, 0, 0x55))
self.rect = pg.Rect((0, 0), (gs, gs))
self.imager = pg.Surface((gs, gs)).convert_alpha()
self.imager.fill((0xff, 0x00, 0, 0x85))
self.rectr = pg.Rect((0, 0), (gs, gs))
def go((di, dj)):
def goo(self):
i1 = self.ri + di
j1 = self.rj + dj
if (i1, j1) in cover:
self.ri = i1
self.rj = j1
self.update()
return goo
go_left = go((0, -1))
go_down = go((1, 0))
go_right= go((0, 1))
go_up = go((-1, 0))
def motion(self, p):
x, y = p
x -= BarW
self.ri = y / gs
self.rj = x / gs
if (self.ri, self.rj) in cover:
self.update()
def update(self):
self.si = self.ri
self.sj = self.rj
while self.si < gh:
for self.sj in xrange(self.rj, gw):
if cover.get((self.si, self.sj), 0) != 0:
break
else:
self.si += 1
continue
break
self.rect.topleft = BarW + gs * self.sj, gs * self.si
self.rectr.topleft = BarW + gs * self.rj, gs * self.ri
def do_uncover(self):
uncover((self.si, self.sj))
def do_mark(self):
p = self.si, self.sj
if cover[p] == 1:
cover[p] = MARK
elif cover[p] == MARK:
cover[p] = 1
under = {}
cover = {}
rects = {}
over = False
bar = None
pool = None
time = 0.
def pg_init():
global screen, nums
pg.display.init()
pg.font.init()
screen = pg.display.set_mode((W, H), 0, 32)
font = pg.font.SysFont('monospace', 16);
nums = [pg.transform.smoothscale(font.render(str(i), 1, (0, 0, 0, 0xff)),
(max(1, gs-4*sep),)*2) for i in [' ']+range(1, 9)]
pg.key.set_repeat(200, 20)
def reset():
global bar, pool, sw, CONTROL
under.clear()
cover.clear()
for i in xrange(gh):
for j in xrange(gw):
under[i, j] = 0
cover[i, j] = 1
rects[i, j] = pg.Rect((j * gs + sep, i * gs + sep), (gs - 2 * sep, gs - 2 * sep))
sw = Sweeper()
CONTROL = {pg.K_j: sw.go_down,
pg.K_k: sw.go_up,
pg.K_h: sw.go_left,
pg.K_l: sw.go_right,
pg.K_SPACE: sw.do_uncover, pg.K_m: sw.do_mark}
bar = pg.Surface((BarW, H)).convert_alpha()
pool = pg.Surface((gw * gs, gh * gs)).convert_alpha()
def put(x):
cs = under.keys()
for k in xrange(x):
p = random.choice(cs)
under[p] = MINE
def init_neig():
for i, j in under:
if under[i, j] != MINE:
under[i, j] = 0
for di, dj in DIR:
i1 = i + di
j1 = j + dj
under[i, j] += int(under.get((i1, j1), 0) == MINE)
def click(pos):
for p in rects:
if rects[p].collidepoint(pos):
uncover(p)
break
def mark(pos):
for p in rects:
if rects[p].collidepoint(pos):
if cover[p] == 1:
cover[p] = MARK
elif cover[p] == MARK:
cover[p] = 1
def game_over():
global over
for p in cover:
cover[p] = 0
over = True
print 'Game Over'
def uncover(p):
if not cover[p]: return
if under[p] == MINE:
game_over()
else:
que = deque()
que.append(p)
while len(que):
p = i, j = que[0]
cover[p] = 0
que.popleft()
for di, dj in DIR:
p1 = i + di, j + dj
if p1 in under and cover[p1]:
if under[p1] == 0:
que.append(p1)
cover[p1] = 0
elif under[p1] != MINE:
cover[p1] = 0
def update_bar():
bar.fill((0, 0x33, 0, 0xff))
#TODO
def update_pool():
pool.fill((0x55, 0x55, 0x55, 0xff))
for p in rects:
if cover[p] == 1:
pg.draw.rect(pool, (0xff, 0xff, 0xff, 0xff), rects[p], 0)
elif cover[p] == MARK:
pg.draw.rect(pool, (0, 0, 0xff, 0xff), rects[p], 0)
elif under[p] == MINE:
pg.draw.circle(pool, (0x0, 0, 0, 0xff), rects[p].center, gs/2-sep, 0)
else:
rect = pg.Rect(rects[p])
rect.size = nums[under[p]].get_size()
rect.center = rects[p].center
pool.blit(nums[under[p]], rect)
def render():
screen.fill((0, 0, 0, 0xff))
screen.blit(bar, (0, 0))
screen.blit(pool, (BarW, 0))
screen.blit(sw.image, sw.rect)
screen.blit(sw.imager, sw.rectr)
pg.display.flip()
def start():
global time
reset()
put(40)
init_neig()
time = 0.
print 'Game start'
update_bar()
update_pool()
def main_loop():
global time
pg_init()
tm = pg.time.Clock()
quit = 0
start()
while not quit:
for e in pg.event.get():
if e.type == pg.KEYDOWN:
if e.key == pg.K_q:
quit = 1
break
elif e.key == pg.K_RETURN:
start()
elif e.key in CONTROL:
CONTROL[e.key]()
update_pool()
elif e.type == pg.MOUSEBUTTONDOWN:
mx, my = e.pos
mx -= BarW
pos = mx, my
if e.button == 1:
click(pos)
elif e.button == 3:
mark(pos)
update_pool()
elif e.type == pg.MOUSEMOTION:
sw.motion(e.pos)
render()
dt = tm.tick(FPS) / 1000.
time += dt
update_bar()
if __name__ == '__main__':
main_loop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment