Ceci est la version complète (non-optimisée) de mon démineur. Vous trouverez la version optimisée ici.
from time import * from math import floor, sqrt from random import randint from kandinsky import * from ion import * GRASS_COLORS = [(142, 204, 57), (167, 217, 72)] DIRT_COLORS = [(215, 184, 153), (229, 194, 159)] CURSOR_COLOR = (0, 0, 0) MINE_BG_COLOR = (255, 0, 0) MINE_COLORS = [(0, 0, 0), (255, 255, 255)] FLAG_COLORS = [(255, 0, 0), (220, 0, 0)] TIME_COLORS = [(255, 255, 255), (255, 190, 0), (221, 160, 17), (0, 0, 0)] TEXT_COLOR = (255, 255, 255) BAR_COLOR = ((73, 117, 43)) NUMBER_COLORS = [ (255, 255, 255), (25, 118, 210), (56, 142, 60), (255, 0, 0), (0, 0, 132), (132, 0, 0), (123, 31, 162), (132, 0, 132), (0, 0, 0) ] FLAG_BITMAP = """ _____11 _____1100 _____110000 _____11000000 _____1100000000 _____110000000000 _____1100000000 _____11000000 _____110000 _____1100 _____11 _____11 _____11 ____1111""" MINE_BITMAP = """ _________00 _________00 _____0_000000_0 ______00000000 _____0011000000 _____0011000000 ___00000000000000 ___00000000000000 _____0000000000 _____0000000000 ____0_00000000_0 _______000000 _________00 _________00""" X_BITMAP = """00________________00 _00______________00 __00____________00 ___00__________00 ____00________00 _____00______00 ______00____00 _______00__00 ________0000 _________00 _________00 ________0000 _______00__00 ______00____00 _____00______00 ____00________00 ___00__________00 __00____________00 _00______________00 00________________00""" TIME_BITMAP = """ _______11111 ________222 _______11111 _____111222111 ____11222222211 ___1122000002211 ___1220003000221 __112000030030211 __122000030300221 __122000033000221 __122000030000221 __112000000000211 ___1220000000221 ___1122000002211 ____11222222211 _____111222111 _______11111""" MINE_COUNT=20 SQUARE_SIZE=20 SCREEN_W=320 SCREEN_H=200 GRID_W=SCREEN_W//SQUARE_SIZE GRID_H=SCREEN_H//SQUARE_SIZE mines = [] digged = [] flagged = [] cursor = [GRID_W//2, GRID_H//2] origin = [0, 0] start_time = monotonic() last_moved = monotonic() def draw_grid_square(xy, color, fill=True, thick=1): x = xy[0]*SQUARE_SIZE y = xy[1]*SQUARE_SIZE + (222-SCREEN_H) if(fill): fill_rect(x, y, SQUARE_SIZE, SQUARE_SIZE, color) else: draw_rect(x, y, SQUARE_SIZE, SQUARE_SIZE, color, thick) def draw_rect(x, y, w, h, color, thick=1): fill_rect(x, y, w, thick, color) fill_rect(x, y, thick, h, color) fill_rect(x, y+h, w, -thick, color) fill_rect(x+w, y, -thick, h, color) def draw_bitmap(bitmap, xy, colors): bitmap = bitmap.split("\n") for y, row in enumerate(bitmap): for x, pixel in enumerate(row): if pixel != "_": set_pixel(xy[0]*SQUARE_SIZE+x, xy[1]*SQUARE_SIZE+(222-SCREEN_H)+y, colors[int(pixel)]) def adjacent(xy, list): n = 0 for y_off in [-1, 0, 1]: for x_off in [-1, 0, 1]: if [x_off, y_off] == [0, 0]: continue if [xy[0]+x_off, xy[1]+y_off] in list: n += 1 return n def dist_to_origin(xy): return sqrt((origin[0] - xy[0])**2 + (origin[1] - xy[1])**2) def dig(xy): if xy in flagged: flagged.pop(flagged.index(xy)) draw_flag_counter() digged.append(xy.copy()) if adjacent(xy, mines) > 0: draw_cell(xy) draw_cursor() return search_digged = [] search_digged.append(xy.copy()) search(xy, search_digged) origin[0] = xy[0] origin[1] = xy[1] search_digged.sort(key=dist_to_origin) for pos in search_digged: draw_cell(pos) if pos == cursor: draw_cursor() draw_flag_counter() def search(xy, search_digged): for y_off in [-1, 0, 1]: for x_off in [-1, 0, 1]: pos = [xy[0]+x_off, xy[1]+y_off] if [x_off, y_off] == [0, 0] or pos in digged or pos[0]>GRID_W-1 or pos[0]<0 or pos[1]>GRID_H-1 or pos[1]<0: continue if pos in flagged: flagged.pop(flagged.index(pos)) digged.append(pos.copy()) search_digged.append(pos.copy()) if adjacent(pos, mines) == 0: search(pos, search_digged) def draw_cell(xy): color_i = int(xy[0]%2==0 and xy[1]%2==0 or xy[0]%2!=0 and xy[1]%2!=0) if xy in digged: draw_grid_square(xy, DIRT_COLORS[color_i], True) n = adjacent(xy, mines) if(n>0): draw_string(str(n), xy[0]*SQUARE_SIZE+5, (222-SCREEN_H)+xy[1]*SQUARE_SIZE+1, NUMBER_COLORS[n], DIRT_COLORS[color_i]) return draw_grid_square(xy, GRASS_COLORS[color_i], True) if xy in flagged: draw_bitmap(FLAG_BITMAP, xy, FLAG_COLORS) def draw_cursor(): draw_grid_square(cursor, CURSOR_COLOR, False, 2) def draw_grid(): for y in range(GRID_H): for x in range(GRID_W): draw_cell([x, y]) def draw_flag_counter(): fill_rect(260, 0, 60, 222-SCREEN_H, BAR_COLOR) draw_string(str(MINE_COUNT-len(flagged))+"/"+str(MINE_COUNT),260,3,TEXT_COLOR,BAR_COLOR) def get_time(): return "{:.1f}".format(monotonic()-start_time) def draw_time(): fill_rect(50, 0, 40, 222-SCREEN_H, BAR_COLOR) draw_string(str(get_time()),42,3,TEXT_COLOR,BAR_COLOR) def game_over(detonated): fill_rect(105, 0, 120, 222-SCREEN_H, BAR_COLOR) draw_string("YOU LOST !",110,3,TEXT_COLOR,BAR_COLOR) origin[0] = cursor[0] origin[1] = cursor[1] flagged.sort(key=dist_to_origin) mines.sort(key=dist_to_origin) for xy in flagged: if not xy in mines: draw_bitmap(X_BITMAP, xy, [(0, 0, 0)]) for xy in detonated: draw_grid_square(xy, MINE_BG_COLOR) if xy == cursor: draw_cursor() for xy in mines: if not xy in flagged: draw_bitmap(MINE_BITMAP, xy, MINE_COLORS) def place_mines(): for i in range(MINE_COUNT): pos = [randint(0, GRID_W-1), randint(0, GRID_H-1)] while pos in mines or (abs(pos[0]-cursor[0]) <= 1 and abs(pos[1]-cursor[1]) <= 1): pos = [randint(0, GRID_W-1), randint(0, GRID_H-1)] mines.append(pos) def chording(xy): detonated = [] for y_off in [-1, 0, 1]: for x_off in [-1, 0, 1]: pos = [xy[0]+x_off, xy[1]+y_off] if [x_off, y_off] == [0, 0] or pos in digged or pos in flagged or pos[0]>GRID_W-1 or pos[0]<0 or pos[1]>GRID_H-1 or pos[1]<0: continue if pos in mines: detonated.append(pos) continue dig(pos) return detonated fill_rect(0,0,320,222-SCREEN_H,BAR_COLOR) draw_string("Select mines count:",5,3,TEXT_COLOR,BAR_COLOR) draw_string(str(MINE_COUNT),215,3,TEXT_COLOR,BAR_COLOR) draw_string("OK →",275,3,TEXT_COLOR,BAR_COLOR) draw_grid() last_changed = monotonic() while keydown(KEY_OK) or keydown(KEY_EXE): pass while not (keydown(KEY_OK) or keydown(KEY_EXE)): if floor(monotonic()*2)%2 == 0: fill_rect(200,0,10,222-SCREEN_H,BAR_COLOR) fill_rect(240,0,10,222-SCREEN_H,BAR_COLOR) else: draw_string("<",200,3,TEXT_COLOR,BAR_COLOR) draw_string(">",240,3,TEXT_COLOR,BAR_COLOR) if monotonic() - last_changed < 0.15: continue if keydown(KEY_LEFT) or keydown(KEY_RIGHT): if keydown(KEY_LEFT) and MINE_COUNT>15: MINE_COUNT -= 1 if keydown(KEY_RIGHT) and MINE_COUNT<99: MINE_COUNT += 1 fill_rect(215,0,25,222-SCREEN_H,BAR_COLOR) draw_string(str(MINE_COUNT),215,3,TEXT_COLOR,BAR_COLOR) last_changed = monotonic() while True: fill_rect(0,0,320,222-SCREEN_H,BAR_COLOR) draw_bitmap(FLAG_BITMAP, [12, -1], FLAG_COLORS) draw_bitmap(TIME_BITMAP, [1, -1], TIME_COLORS) mines = [] digged = [] flagged = [] cursor = [GRID_W//2, GRID_H//2] start_time = monotonic() draw_time() draw_flag_counter() draw_grid() for i in range(11): draw_string("MINESWEEPER"[:i+1],105,3,TEXT_COLOR,BAR_COLOR) sleep(0.05) draw_cursor() start_time = monotonic() last_time = get_time() first_dig = True while True: if get_time() != last_time: draw_time() last_time = get_time() # moving cursor if monotonic() - last_moved > 0.15: pressed = None for k in [KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN]: if keydown(k): pressed = k break if not pressed == None: last_cursor = cursor.copy() if pressed == KEY_RIGHT: cursor[0] += 1 if cursor[0] > GRID_W-1: cursor[0] = 0 elif pressed == KEY_LEFT: cursor[0] -= 1 if cursor[0] < 0: cursor[0] = GRID_W-1 elif pressed == KEY_DOWN: cursor[1] += 1 if cursor[1] > GRID_H-1: cursor[1] = 0 elif pressed == KEY_UP: cursor[1] -= 1 if cursor[1] < 0: cursor[1] = GRID_H-1 draw_cursor() draw_cell(last_cursor) last_moved = monotonic() # digging if (keydown(KEY_OK) or keydown(KEY_EXE)) and not cursor in flagged: if first_dig: place_mines() first_dig = False if cursor in mines: game_over([cursor]) break if cursor in digged and adjacent(cursor, flagged) == adjacent(cursor, mines): detonated = chording(cursor) if detonated: game_over(detonated) break elif not cursor in digged: dig(cursor) if len(digged)+MINE_COUNT == GRID_W*GRID_H: fill_rect(105, 0, 120, 222-SCREEN_H, BAR_COLOR) draw_string("YOU WON !",115,3,TEXT_COLOR,BAR_COLOR) break while keydown(KEY_OK) or keydown(KEY_EXE): pass # flagging if keydown(KEY_BACKSPACE): if cursor in flagged: flagged.pop(flagged.index(cursor)) elif not cursor in digged: flagged.append(cursor.copy()) draw_cell(cursor) draw_cursor() draw_flag_counter() while keydown(KEY_BACKSPACE): pass while keydown(KEY_OK) or keydown(KEY_EXE): pass while not (keydown(KEY_OK) or keydown(KEY_EXE)): pass