sautemouton.py

Created by andreanx

Created on July 11, 2020

8.08 KB

A gauche n moutons maigres en bergerie, a droite n moutons gras au pâturage. Rentre les moutons gras en bergerie et sors les moutons maigres au pâturage. Les moutons ne sautent qu’1 mouton a la fois ni reculent.

Appel : sm(n=3)

Touches : [<-][->] : choix du mouton [OK] : avancer ou sauter [clear] : quitter


from kandinsky import *
from math import *
from time import *
from ion import *

sw, sh, fw, fh, cw = 320, 222, 10, 29, 29
mouton_largeur, mouton_hauteur = 30, 22
_mouton_maigre = (25165824, 125829120, 92274688, 260048512, 264353460, 536608764, 478150654, 142606335, 4194302, 4194298, 2097018, 926488, 997494, 983158, 983158, 917556, 655412, 655412, 655460, 1179748, 131264, 131264)
_mouton_gras = (40, 6815932, 65902068, 268435454, 134217726, 1073741823, 536870861, 1073741702, 1073741696, 402652928, 469761920, 200277888, 234339072, 233486848, 468088320, 461649408, 226506240, 226505216, 213922304, 140522240, 106958848, 6303744)
_codes_touche_quitter = (6, 5, 17)
_codes_touche_gauche = (0,)
_codes_touche_droite = (3,)
_codes_touche_action = (12, 13, 4, 52)


def _print_auto_ln(s, n):
  while len(s):
    iln = s.find('\n')
    print(s[0: iln >= 0 and min(n, iln) or n])
    s = s[iln >= 0 and iln < n and iln + 1 or n:]

_print_auto_ln("A gauche n moutons maigres en bergerie, a droite n moutons gras au paturage. Rentre les moutons gras en bergerie et sors les moutons maigres au paturage. Les moutons ne sautent qu'1 mouton a la fois ni reculent.\nAppel: sm(n=3)", cw)

def sm(n=3):
  global univers
  if not isinstance(n, int) or n < 1 :
    raise ValueError("n must be a strictly positive integer")
  univers = [[1 for k in range(n)] + [0] + [-1 for k in range(n)]]
  etat_gagnant = list(univers[0])
  etat_gagnant.reverse()
  univers.extend([-1, sw // len(univers[0]), (0, 158, 0)])
  case_ancienne = -1
  touche_pressee = -1
  coups = 0
  mouton_y = _dessine_decor()
  couleur_fond = (0, 255, 255)
  while not _keydownin(_codes_touche_quitter) and univers[0] != etat_gagnant:
    rafraichissement_necessaire = False
    if _keydownin(_codes_touche_gauche + _codes_touche_droite):
      case_ancienne = univers[1]
      _change_case_courante( _keydownin(_codes_touche_gauche) and -1 or 1)
      rafraichissement_necessaire = True
    elif univers[1]>=0 and _keydownin(_codes_touche_action):
      case_ancienne = univers[1]
      if _bouge_de(1) or _bouge_de(2):
        coups += 1
        rafraichissement_necessaire = True
    if rafraichissement_necessaire:
      _dessine_moi_un_mouton(case_ancienne, univers[2], mouton_y)
      _dessine_moi_un_mouton(univers[1], univers[2], mouton_y)
      sleep(0.1)
  if univers[0] == etat_gagnant:
    print("Gagne en " + str(coups) + " coups !")
  return (univers[0] == etat_gagnant, coups)

def _keydownin(l):
  for v in l:
    if keydown(v): return True
  return False

def _bouge_de(pas):
  global univers
  case_courante = univers[1]
  case_ciblee = case_courante + univers[0][case_courante]*pas
  if case_ciblee >=0 and case_ciblee < len(univers[0]) and not univers[0][case_ciblee]:
    _echange_cases(case_courante, case_ciblee)
    univers[1] = case_ciblee
    return True
  return False

def _echange_cases(case1, case2):
  global univers
  univers[0][case2], univers[0][case1] = univers[0][case1], univers[0][case2]

def _change_case_courante(sens):
  global univers
  case_courante = univers[1]
  while not univers[0][univers[1]] or univers[1] == case_courante:
    univers[1] = (univers[1] + sens) % len(univers[0])

def _draw_horiz_line(x1, x2, y, c):
  fill_rect(x1, y, x2 - x1 + 1, 1, c)

def _draw_line(x1, y1, x2, y2, c):
  x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
  if (x2 - x1) ** 2 >= (y2 - y1) ** 2:
    if min(x1, x2) != x1: x1, y1, x2, y2 = x2, y2, x1, y1
    for k in range(x2 - x1 + 1):
      x = x1 + k
      y = int(y1 + (y2 - y1)*k/(x2 - x1))
      set_pixel(x, y, c)
  else:
    if min(y1, y2) != y1: x1, y1, x2, y2 = x2, y2, x1, y1
    for k in range(y2 - y1 + 1):
      y = y1 + k
      x = int(x1 + (x2 - x1)*k/(y2 - y1))
      set_pixel(x, y, c)

def _draw_poly_line(l, c):
  for k in range(len(l) - 1):
    _draw_line(l[k][0], l[k][1], l[k + 1][0], l[k + 1][1], c)
  return

def _fillBottomFlatTriangle(p1, p2, p3, c):
  p2, p3 = sorted([p2, p3], key=lambda x: x[0])
  invslope1 = (p2[0] - p1[0]) / (p2[1] - p1[1])
  invslope2 = (p3[0] - p1[0]) / (p3[1] - p1[1])
  curx1 = p1[0]
  curx2 = p1[0]
  for scanlineY in range(p1[1], p2[1]+1):
    _draw_horiz_line(int(curx1), int(curx2), scanlineY, c)
    curx1 += invslope1
    curx2 += invslope2

def _fillTopFlatTriangle(p1, p2, p3, c):
  p1, p2 = sorted([p1, p2], key=lambda x: x[0])
  invslope1 = (p3[0] - p1[0]) / (p3[1] - p1[1]);
  invslope2 = (p3[0] - p2[0]) / (p3[1] - p2[1]);
  curx1 = p3[0];
  curx2 = p3[0];
  for scanlineY in range(p3[1], p1[1], -1):
    _draw_horiz_line(int(curx1), int(curx2), scanlineY, c)
    curx1 -= invslope1;
    curx2 -= invslope2;

def _fill_triangle(p1, p2, p3, c):
  p1, p2, p3 = sorted([p1, p2, p3], key=lambda x: x[1])
  if p2[1] == p3[1]:
    _fillBottomFlatTriangle(p1, p2, p3, c)
  elif p1[1] == p2[1]:
    _fillTopFlatTriangle(p1, p2, p3, c)
  else:
    p4 = (int(p1[0] + ((p2[1] - p1[1]) / (p3[1] - p1[1])) * (p3[0] - p1[0])), p2[1]);
    _fillBottomFlatTriangle(p1, p2, p4, c)
    _fillTopFlatTriangle(p2, p4, p3, c)

def _fill_polygon_convex(l, c):
  for k in range(1, len(l) - 1):
    _fill_triangle(l[0], l[k], l[k + 1], c)
  return

def _draw_image_1bpp(img, x, y, c):
  for j in range(len(img)):
    v = img[j]
    i = 0
    while v:
      if v&1:
        set_pixel(x + i, y + j, c)
      v = v >> 1
      i += 1

def _dessine_moi_un_mouton(case_numero, case_largeur, y):
  global univers
  if univers[0][case_numero]:
    _draw_image_1bpp((univers[0][case_numero] > 0) and _mouton_maigre or _mouton_gras, case_numero*case_largeur + (case_largeur - mouton_largeur)//2, y, (case_numero == univers[1]) and (255, 0, 255) or (255,)*3)
  else:
    fill_rect(case_numero * case_largeur, y, case_largeur, mouton_hauteur, univers[3])

def _fillRectHorizGradientRGB(x, y, w, h, col1, col2):
  for k in range(h):
    _draw_line(x, y + k, x + w - 1, y + k, [col1[i]+(col2[i] - col1[i])*k//(h-1) for i in range(3)])

def _dessine_decor():
  global univers
  _print_auto_ln("Plantons d'abord le decor !", cw)
  d, l = int(sh // 3.125), 14
  cloture_h, m = d // 8, (sh - 2 * d) // l
  cloture_w, maison_w, porte_d = cloture_h // 4, d * 3 // 4, d // 4
  maison_h, fenetre_w = maison_w // 2, d // 8
  maison_x, maison_y, cloture_y = d*7//8, sh - 2*d - 7*d//64, sh - d - cloture_h
  couleur_fond1, couleur_fond2 = univers[3], (0, 255, 255)
  _fillRectHorizGradientRGB(0, 0, sw, sh - 2*d, couleur_fond2, (255,)*3)
  _fillRectHorizGradientRGB(0, sh - 2*d, sw, d, (0, 255, 0), couleur_fond1)
  fill_rect(0, sh - d, sw, d, couleur_fond1)
  for i in range(m):
    draw_string("*" * (i<3 and i+2 or 5), 0, l * (m - i - 1), univers[3])
  fill_rect(maison_x, maison_y, maison_w, maison_h, (255, 255, 0))
  fill_rect(maison_x + maison_w//2 - porte_d//2, maison_y + maison_h - porte_d, porte_d, porte_d, (0,)*3)
  fill_rect(0, m*l + 2, fw, sh - 5*d//4 - m*l - l, (181, 32, 0))
  for i in range(0, sw, cloture_h):
    cloture_x = i + (cloture_h - cloture_w)//2
    fill_rect(cloture_x, cloture_y, cloture_w, cloture_h, (181, 32, 0))
    if i//cloture_h % 2:
      _fill_polygon_convex(((cloture_x, cloture_y), (cloture_x - (cloture_h - cloture_w)//2, cloture_y - 3*d//64), (cloture_x, cloture_y - 7*d//64), (cloture_x + cloture_w - 1, cloture_y - 7*d//64), (cloture_x + cloture_w - 1 + (cloture_h - cloture_w)//2, cloture_y - 3*d//64), (cloture_x + cloture_w - 1, cloture_y)), (181, 32, 0))
  _fill_polygon_convex(((maison_x - 1, maison_y), (maison_x + d//4, maison_y - d//4 - 1), (maison_x + maison_w - d//4 - 1, maison_y - d//4 - 1), (maison_x + maison_w, maison_y)), (255, 0, 0))
  lst = ((sw // 2, sh - 2*d), (3 * sw // 4, sh - 2*d - d//4), (33 * sw // 40, sh - 2*d - d//8), (31 * sw // 40, sh - 2*d), (15 * sw // 16, sh - 2*d - 3*d//8), (sw, sh - 2*d - d//4), (sw, sh - 2*d))
  _fill_polygon_convex(lst[0:4], (0, 146, 255))
  _fill_polygon_convex(lst[3:7], (0, 146, 255))
  for i in range(-1, 2, 2):
    fill_rect(maison_x + maison_w//2 +i*porte_d//2 - (i<0 and fenetre_w), maison_y + d*5//64, fenetre_w, d * 3 // 32, (0, 146, 255))
  _draw_poly_line(lst, (255, 0, 255))
  mouton_y = sh - d + (d - mouton_hauteur) // 2
  for case_numero in range(len(univers[0])):
    if univers[0][case_numero]:
      _dessine_moi_un_mouton(case_numero, univers[2], mouton_y)
  return mouton_y

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 <a href="https://www.numworks.com/legal/cookies-policy/">cookies policy</a>.