gameoflife.py

Created by itzrayanis

Created on March 19, 2026

5.91 KB

Jeu de la vie de conway
Flèches pour déplacer le curseur
Ok pour dessiner/effacer
Shift pour changer de mode (Draw/Erase)
Toolbox pour le menu
9 pour passer à la prochaine génération


from ion import *
import kandinsky
import time

SCREEN_W  = 320
SCREEN_H  = 222
TOOLBAR_H = 18
CANVAS_H  = SCREEN_H - TOOLBAR_H  

TAILLE_MIN = 4
TAILLE_MAX = 40
MAX_PTS    = 1000
TTC        = 0.2

CELL_SIZE  = 12 
COL_ALIVE  = (0, 0, 0)
COL_DEAD   = (255, 255, 255)
CURSOR_COL = (255, 220, 0)

state = {
    "running"   : False,
    "cursor_x"  : 8,
    "cursor_y"  : 8,
    "mode"      : "draw", 
}

cells = [] 

def S(k): return state[k]
def SET(k, v): state[k] = v

def draw_canvas():
    kandinsky.fill_rect(0, 0, SCREEN_W, CANVAS_H, COL_DEAD)
    for x, y in cells:
        kandinsky.fill_rect(x, y, CELL_SIZE, CELL_SIZE, COL_ALIVE)

def draw_cursor():
    if S("mode") == "run":
        return
    cx, cy = S("cursor_x"), S("cursor_y")
    kandinsky.fill_rect(cx, cy, CELL_SIZE, 2, CURSOR_COL)
    kandinsky.fill_rect(cx, cy, 2, CELL_SIZE, CURSOR_COL)
    kandinsky.fill_rect(cx+CELL_SIZE-2, cy, 2, CELL_SIZE, CURSOR_COL)
    kandinsky.fill_rect(cx, cy+CELL_SIZE-2, CELL_SIZE, 2, CURSOR_COL)

def draw_toolbar():
    tb_y = CANVAS_H
    mode_label = {"draw":"DESSIN", "erase":"EFFACE", "run":"RUN"}[S("mode")]
    kandinsky.fill_rect(0, tb_y, SCREEN_W, TOOLBAR_H, (40, 40, 40))
    kandinsky.draw_string("Mode:%s   Cells:%d   OK:step  9:step  Toolbox:Menu" % (
        mode_label, len(cells)), 6, tb_y+2, (255,255,0), (40,40,40))

def refresh():
    draw_canvas()
    draw_cursor()
    draw_toolbar()

def info(text):
    kandinsky.fill_rect(0, CANVAS_H - 22, SCREEN_W, 22, (60, 60, 60))
    kandinsky.draw_string(text, 6, CANVAS_H - 18, (255,255,255), (60,60,60))
    kandinsky.draw_string("[OK]", 268, CANVAS_H - 18, (255,220,0), (60,60,60))
    while True:
        if keydown(KEY_OK):
            time.sleep(TTC)
            return

def cell_at_cursor():
    cx, cy = S("cursor_x"), S("cursor_y")
    for c in cells:
        if c[0] == cx and c[1] == cy:
            return c
    return None

def add_cell_at_cursor():
    if len(cells) >= MAX_PTS:
        info("Too many cells !")
        return
    if cell_at_cursor() is None:
        cells.append((S("cursor_x"), S("cursor_y")))

def remove_cell_at_cursor():
    c = cell_at_cursor()
    if c:
        cells.remove(c)

def toggle_mode():
    m = S("mode")
    SET("mode", "erase" if m == "draw" else "draw")

def move_cursor(dx, dy):
    x = max(0, min(S("cursor_x") + dx * CELL_SIZE, SCREEN_W - CELL_SIZE))
    y = max(0, min(S("cursor_y") + dy * CELL_SIZE, CANVAS_H - CELL_SIZE))
    SET("cursor_x", x)
    SET("cursor_y", y)

def clear_cells():
    cells.clear()

def neighbors(cell):
    x, y = cell
    nbs = []
    for dx in (-CELL_SIZE, 0, CELL_SIZE):
        for dy in (-CELL_SIZE, 0, CELL_SIZE):
            if dx == 0 and dy == 0: continue
            nx, ny = x+dx, y+dy
            if 0 <= nx < SCREEN_W and 0 <= ny < CANVAS_H:
                nbs.append((nx, ny))
    return nbs

def conway_step():
    count = {}
    for c in cells:
        for n in neighbors(c):
            count[n] = count.get(n, 0) + 1
    new_cells = []
    checked = set()
    for pos, cnt in count.items():
        if cnt == 3 or (cnt == 2 and pos in cells):
            if pos not in checked and 0 <= pos[0] < SCREEN_W and 0 <= pos[1] < CANVAS_H:
                new_cells.append(pos)
                checked.add(pos)
    cells.clear()
    for c in new_cells:
        if len(cells) < MAX_PTS:
            cells.append(c)

def menu():
    options = ["Play/Stop", "Clean", "Quit"]
    sel = 0
    n = len(options)
    menu_y = [50 + i * 36 for i in range(n)]
    while True:
        kandinsky.fill_rect(0, 0, SCREEN_W, SCREEN_H, (30,30,30))
        kandinsky.fill_rect(0,0,165,SCREEN_H, (50,50,50))
        kandinsky.draw_string("OPTIONS", 18, 14, (255,220,0), (50,50,50))
        for i, opt in enumerate(options):
            active = (i==sel)
            bg = (0,120,220) if active else (50,50,50)
            kandinsky.fill_rect(8, menu_y[i] - 4, 148, 26, bg)
            kandinsky.draw_string(opt, 16, menu_y[i], (255,255,255), bg)
        while True:
            if keydown(KEY_DOWN): sel = (sel+1)%n; time.sleep(TTC); break
            if keydown(KEY_UP): sel = (sel-1)%n; time.sleep(TTC); break
            if keydown(KEY_OK):
                time.sleep(TTC); return sel
            if keydown(KEY_BACKSPACE) or keydown(KEY_TOOLBOX):
                time.sleep(TTC); return None
            time.sleep(0.05)

refresh()
time.sleep(0.1)

while True:
    refresh()
    if S("mode") == "run" or S("running") is True:
        conway_step()
        time.sleep(0.14)
        if keydown(KEY_TOOLBOX):
            SET("mode","draw")
            S("running") and SET("running", False)
            menu()
            continue
    else:
        if keydown(KEY_RIGHT): move_cursor(1,0); refresh(); time.sleep(TTC)
        if keydown(KEY_LEFT): move_cursor(-1,0); refresh(); time.sleep(TTC)
        if keydown(KEY_UP): move_cursor(0,-1); refresh(); time.sleep(TTC)
        if keydown(KEY_DOWN): move_cursor(0,1); refresh(); time.sleep(TTC)

        if keydown(KEY_OK):
            if S("mode")=="draw": add_cell_at_cursor()
            elif S("mode")=="erase": remove_cell_at_cursor()
            refresh()
            time.sleep(TTC)

        if keydown(KEY_NINE):
            conway_step()
            refresh()
            time.sleep(TTC)

        if keydown(KEY_SHIFT):
            toggle_mode()
            refresh()
            time.sleep(TTC)

        if keydown(KEY_TOOLBOX):
            time.sleep(TTC)
            op = menu()
            if op == 0:
                m = S("mode")
                if m == "run":
                    SET("mode","draw")
                    SET("running",False)
                else:
                    SET("mode","run")
                    SET("running",True)
            elif op == 1:
                if len(cells) > 0:
                    clear_cells()
                    info("Effacé!")
            elif op == 2:
                info("Au revoir!")
                break
            refresh()
            time.sleep(TTC)

    time.sleep(0.02)

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.