# -*- coding:utf-8 -*- __projet__ = "Algorithmique_Corrections" __nom_fichier__ = "flipper_v1" __author__ = "A-J. Tinet" __date__ = "octobre 2025" """ ======================================================================================================================== LE FLIPPER / LE BILLARD avec 1 obstacle horizontal ======================================================================================================================== """ # Import de bibliothèques import turtle as tu import math as mt def dessin_flipper(lmin, lmax, Lmin, Lmax): """ Dessine le flipper. :param lmin: type float - abscisse gauche du flipper :param lmax: type float - abscisse droite du flipper :param Lmin: type float - ordonnée basse du flipper :param Lmax: type float - ordonnée haute du flipper :return: None """ tu.up() tu.goto(lmin, Lmin) tu.down() for _ in range(2): tu.forward(lmax - lmin) tu.left(90) tu.forward(Lmax - Lmin) tu.left(90) tu.up() def dessin_obstacle(omin, omax, oy): """ Dessine l'obstacle. :param omin: type float - abscisse gauche de l'obstacle :param omax: type float - abscisse droite de l'obstacle :param oy: type float - ordonnée de l'obstacle :return: None """ tu.goto(omin, oy) tu.down() tu.goto(omax, oy) tu.up() # Définition des fonctions def appartient(xmin, xmax, ymin, ymax, x, y): """ Indique si le point (x, y) appartient au segment défini par les points (xmin, ymin) et (xmax, ymax) :param xmin: type float - abscisse d'une extrémité du segment :param xmax: type float - abscisse d'une extrémité du segment :param ymin: type float - ordonnée d'une extrémité du segment :param ymax: type float - ordonnée d'une extrémité du segment :param x: type float - abscisse du point :param y: type float - ordonnée du point :return: type bool """ return xmin <= x <= xmax and ymin <= y <= ymax def intersection(xmin, xmax, ymin, ymax, a, b): """ Recherche l'intersection entre la droite y = ax + b et le segment défini par ses extrémités. les segments sont soit horizontaux, soit verticaux. :param xmin: type float - abscisse d'une extrémité du segment :param xmax: type float - abscisse d'une extrémité du segment :param ymin: type float - ordonnée d'une extrémité du segment :param ymax: type float - ordonnée d'une extrémité du segment :param a: type float - pente de la droite :param b: type float - ordonnée à l'origine de la pente :return: le point d'intersection (x, y) et le nombre de points à compter s'il existe, sinon False """ # Cas d'un segment vertical if xmin == xmax: y = a * xmin + b if ymin <= y <= ymax: return xmin, y, 1 # Cas d'un segment horizontal if ymin == ymax: x = (ymin - b) / a if xmin <= x <= xmax: return x, ymin, 0 return False def prochain_rebond(lmin, lmax, Lmin, Lmax, x, y, a, b, sens, omin, omax, oy): """ Recherche la position du prochain rebond. :param lmin: type float - abscisse gauche du flipper :param lmax: type float - abscisse droite du flipper :param Lmin: type float - ordonnée basse du flipper :param Lmax: type float - ordonnée haute du flipper :param x: type float - abscisse du point :param y: type float - ordonnée du point :param a: type float - pente de la droite :param b: type float - ordonnée à l'origine de la pente :param sens : type int - sens du déplacement (-1 vers le bas, +1 vers le haut) :return: position (xnew, ynew) du prochain rebond """ segments = [(omin, omax, oy, oy), (lmin, lmax, Lmin, Lmin), (lmax, lmax, Lmin, Lmax), (lmin, lmax, Lmax, Lmax), (lmin, lmin, Lmin, Lmax)] for xmin, xmax, ymin, ymax in segments: if not appartient(xmin, xmax, ymin, ymax, x, y): result = intersection(xmin, xmax, ymin, ymax, a, b) if result is not False: #print("sens", sens, "nv_y", result[1],"y", y) #print ("result[2]",result[2]) if sens * (result[1] - y) >= 0: #necessaire car risque de traverser l'obstacle.. return result def update_position(x, y, a, sens, indicateur): """ Déplacement de la bille à sa nouvelle position. Mise à jour de la trajectoire (pente et ordonnée à l'origine) :param x: type float - nouvelle abscisse :param y: type float - nouvelle ordonnée :param a: type float - pente de la trajectoire actuelle :return: nouvelle trajectoire (pente et ordonnée à l'origine) """ tu.down() tu.goto(x, y) a = -a b = y - a * x if indicateur == 0: # Bord horizontal sens = -sens return a, b, sens def jeu_flipper(lmin, lmax, Lmin, Lmax, omin, omax, oy, x0, angle, n): """ Fait rebondir une bille sur les bords d'un flipper. Le score augmente d'un point à chaque bord vertical touché. :param lmin: type float - abscisse gauche du flipper :param lmax: type float - abscisse droite du flipper :param Lmin: type float - ordonnée basse du flipper :param Lmax: type float - ordonnée haute du flipper :param x0: type float - abscisse de départ sur le bord bas :param angle: type float - angle de départ (entre 0 et 90° exclus) :param n: type int - nombre de rebonds de la bille :return: None """ # Initialisation de la bille x, y = x0, Lmin tu.goto(x, y) tu.shape('turtle') tu.down() a = mt.tan(angle * mt.pi / 180) b = y - a * x sens = 1 npts = 0 # On trace n vecteurs for i in range(n): nv_x, nv_y, pts = prochain_rebond(lmin, lmax, Lmin, Lmax, x, y, a, b, sens, omin, omax, oy) a, b, sens = update_position(nv_x, nv_y, a, sens, pts) x=nv_x y=nv_y npts += pts return npts # Programme principal lmin = 0 lmax = 150 Lmin = 0 Lmax = 300 omin = 40 omax= 150 oy = 200 nb_rebonds = 7 #Dessin du flipper dessin_flipper(lmin, lmax, Lmin, Lmax) dessin_obstacle(omin, omax, oy) rep="o" while rep != "n": x0 = int( input("A quelle position x voulez-vous lancer la bille ?" )) angle = int(input("Avec quel angle (entre 0 et 90 degres) ?")) nbpts = jeu_flipper(lmin, lmax, Lmin, Lmax, omin, omax, oy, x0, angle, nb_rebonds) print("Vous avez marqué ", nbpts, " points.") rep=input("Voulez-vous rejouer ? (o/n)") if rep=="o": tu.up() tu.reset() dessin_flipper(lmin, lmax, Lmin, Lmax) dessin_obstacle(omin, omax, oy) tu.exitonclick()