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