wythoff.py

Created by schraf

Created on April 07, 2022

2.59 KB

Il existe plusieurs versions du jeu des allumettes :

  • Celle où il n’y a qu’une ligne et chaque joueur peut enlever 1, 2 ou 3 allumettes. Le perdant est celui qui prend la dernière allumette

  • Celle appelée Jeu de Nim qui utilise plusieurs rangées et dont la stratégie gagnante utilise le “ou exclusif, j’ai fait une vidéo à ce sujet

  • La version proposée ici n’utilise que 2 rangées. Vous pouvez enlever autant d’allumettes que vous voulez sur UNE des 2 rangées, ou alors enlever le même nombre d’allumettes sur les DEUX rangées en même temps. Le gagnant est celui qui enlève la (ou les) dernière(s) allumette(s).

Utilisation avec la NUMWORKS : Flèche du haut pour enlever des allumettes sur la rangée du haut, flèche du bas pour la rangée du bas, flèche de gauche pour les 2 rangées à la fois, OK pour valider et touche Backspace pour annuler votre coup.

L’intervention du nombre d’Or dans la redoutable stratégie de la calculatrice parait tout à fait étonnante ! Si vous voulez en savoir plus, regardez par ici.

Ma chaine Youtube


from math import sqrt
from kandinsky import fill_rect, draw_string
from ion import *
from time import sleep
from random import randint

def draw(nb, color, top, y):
  for i in range(20):
    if i >= nb: color, top = white, white
    fill_rect(i*15+10,y,5,50,color)
    fill_rect(i*15+9,y - 10,7,10,top)

def jeu(haut, bas):
    draw(haut, brown, red, 30)
    draw(bas, brown, red, 140)

def touche():
  while True:
    for (i, k) in enumerate([KEY_UP, KEY_DOWN, KEY_LEFT, KEY_BACKSPACE, KEY_OK]):
      if keydown(k):
        sleep(.2)
        return i
        
def anim(a, b, ra, rb):
  for i in range(max(ra, rb)):
    if i < ra: a -= 1
    if i < rb: b -= 1
    jeu(a, b)
    sleep(.2)

def IA(a, b):
    phi = (1 + sqrt(5)) / 2
    t1 = min(haut, bas)
    n = abs(max(a, b) - t1)
    if int(n * phi) <= t1:
        r1 = t1 - int(n * phi)
        r2 = r1
        if r1 == 0: (r1, r2) = (1, 0) if a == max(a, b) else (0, 1)
        anim(a, b, r1, r2)
        (a, b) = (a - r1, b - r2)        
    else:
        n = 0
        while t1 not in [int(n * phi), int(n * phi * phi)]: n += 1
        (r1, r2) = (int(n * phi), int(n * phi * phi))
        r = a + b - r1 - r2
        if r == 0:
          (r1, r2) = (a - 1, b) if a == max(a, b) else (a, b - 1)
        if a == r1 or a == r2:
            anim(a, b, 0, r)
            b = r2 + r1 - a
        else:
            anim(a, b, r, 0)
            a = r2 + r1 - b
    return (a, b)


brown = (255, 204, 153)
red = (255, 0, 0)
white = (255, 255, 255)
haut = randint(5, 20)
bas = randint(5, 20)
allumettes = haut + bas
while allumettes > 1:
    (nextHaut, nextBas) = (haut, bas)
    choix = 0
    while True:
        jeu(nextHaut, nextBas)
        t = touche()
        if t == 0:
            if choix == 0:
                choix = 1
            if choix == 1:
                nextHaut = max(0, nextHaut - 1)
        elif t == 1:
            if choix == 0:
                choix = 2
            if choix == 2:
                nextBas = max(0, nextBas - 1)
        elif t == 2:
            if choix == 0:
                choix = 3
            if choix == 3:
                nextBas = max(0, nextBas - 1)
                nextHaut = max(0, nextHaut - 1)
        elif t == 3:
            choix = 0
            nextHaut = haut
            nextBas = bas
        elif t == 4 and (haut, bas) != (nextHaut, nextBas):
            (haut, bas) = (nextHaut, nextBas)
            break
    if haut + bas == 0:
      draw_string("TU GAGNES !",115,100,white,red)    
      break  
    haut, bas = IA(haut, bas)
    allumettes = haut + bas
    if allumettes == 0:
      draw_string("JE GAGNE !",115,100,white,red)