###############################################################################
## Ce programme permet de construire un niveau Mario de manière interactive.
## L'utilisateur choisit d'abord un niveau de difficulté, puis ajoute des
## blocs à son niveau une ligne à la fois. Certains blocs peuvent être
## générés aléatoirement selon la difficulté choisie.
## À la fin, le niveau final est affiché avec un score de complexité.
## - random (module standard de Python pour les tirages aléatoires)
## Environnement recommandé :
###############################################################################
## Auteur: Louis-Edouard Lafontant
###############################################################################
# Définition des constantes pour chaque type de bloc
BLOC_A = "[#]" # Bloc solide
BLOC_B = "[ ]" # Bloc vide (trou)
BLOC_C = "[^]" # Trampoline
BLOC_D = "[>]" # Accélérateur
BLOC_E = "[<]" # Décélérateur
BLOC_F = "[?]" # Aléatoire (résolu immédiatement)
# Contraintes de dimension du niveau
# Résout un bloc aléatoire selon la difficulté choisie.
# - Difficulté 1 (facile) : majorité de blocs solides [#] (60%). Peu de blocs dangereux.
# - Difficulté 2 (moyen) : répartition plus équilibrée. 30% de solides, plus de vides et de trampolines.
# - Difficulté 3 (difficile) : seulement 10% de blocs solides. 50% de vides [ ].
def resoudre_bloc_aleatoire(difficulte):
choix_alea = random.randint(1, 100)
# 60% solide, 10% trampoline, 10% accélérer, 10% décélérer, 10% vide
# 30% solide, 30% vide, 20% trampoline, 10% accélérer, 10% décélérer
# 10% solide, 50% vide, 10% trampoline, 10% accélérer, 20% décélérer
# Retourne le nombre minimum de blocs aléatoires requis pour la ligne courante.
def min_bloc_aleatoire(nb_lignes):
# Affiche l'état actuel du niveau : les lignes complétées, la ligne en cours de construction, et le compteur d'aléatoires.
def affiche_etat(niveau, ligne, min_aleatoire, nb_aleatoire, nb_ligne):
print("──────────────────────────────────────────────────")
# Afficher les lignes complétées (elles sont empilées du bas vers le haut)
# Afficher la ligne en cours avec le numéro de ligne
print("→ " + ligne + " (" + str(nb_ligne + 1) + ")")
print("→ (ligne vide) (" + str(nb_ligne + 1) + ")")
# Afficher le compteur de blocs aléatoires
print("[?] aléatoires : " + str(nb_aleatoire) + " / " + str(min_aleatoire) + " minimum")
print("──────────────────────────────────────────────────")
# Vérifie si le choix de l'utilisateur est une option reconnue.
def choix_est_valide(choix):
return choix in ["A", "B", "C", "D", "E", "F", "NL", "FIN"]
# Vérifie si le choix correspond à un bloc (nécessite une quantité).
def choix_est_bloc(choix):
return choix in ["A", "B", "C", "D", "E", "F"]
# Affiche le menu et demande à l'utilisateur de choisir une option.
# Retourne le choix valide ou -1 en cas d'erreur.
print(" A) [#] Bloc B) [ ] Vide C) [^] Trampoline")
print(" D) [>] Accélérer E) [<] Décélérer F) [?] Aléatoire")
print(" NL) Nouvelle ligne FIN) Terminer")
choix = input(" Bloc : ").upper().strip()
if not choix_est_valide(choix):
print(" Erreur : choix invalide. Essayez A, B, C, D, E, F, NL ou FIN.")
# Demande combien de blocs l'utilisateur veut ajouter (entre 1 et 10).
# Redemande tant que la valeur n'est pas valide.
quantite_txt = input(" Nombre : ").strip()
if not quantite_txt.isdigit():
print(" Erreur : entre un nombre valide.")
quantite = int(quantite_txt)
if quantite < MIN_QUANTITE or quantite > MAX_QUANTITE:
print(" Erreur : la quantité doit être entre 1 et 10.")
# Calcule un score de complexité basé sur 4 facteurs :
# 1. Blocs vides (× 3) : chaque trou est un danger majeur pour Mario.
# 2. Blocs aléatoires (× 2) : l'imprévisibilité ajoute de la difficulté.
# 3. Nombre de lignes (× 5) : plus le niveau est haut, plus Mario doit
# grimper et risque de tomber.
# 4. Difficulté (× 10) : un multiplicateur global qui reflète le fait
# que les blocs aléatoires en difficulté 3 sont bien plus dangereux
# Formule : score = (vides × 3 + aléatoires × 2 + lignes × 5) × difficulté × 10
def calcul_score_complexite(nb_bloc_A, nb_bloc_B, nb_bloc_C, nb_bloc_D, nb_bloc_E, nb_bloc_F, nb_ligne, difficulte):
score = (nb_bloc_B * 3 + nb_bloc_F * 2 + nb_ligne * 5) * difficulte * 10
###############################################################################
###############################################################################
print("Constructeur de niveaux Mario")
print("═════════════════════════════════")
# Choix du niveau de difficulté (1, 2 ou 3)
difficulte_txt = input("Difficulté (1 = facile, 2 = moyen, 3 = difficile) : ").strip()
if difficulte_txt not in ["1", "2", "3"]:
print("Erreur : choisissez 1, 2 ou 3.")
difficulte = int(difficulte_txt)
# Initialisation des variables
niveau = "" # Chaîne contenant les lignes complétées (séparées par \n)
ligne = "" # Ligne en cours de construction
termine = False # Drapeau de fin de programme
nb_ligne = 0 # Nombre de lignes complétées
nb_bloc = 0 # Nombre de blocs sur la ligne courante
nb_bloc_F = 0 # Nombre de blocs aléatoires sur la ligne courante
# Compteurs globaux pour le score de complexité
# Boucle principale de construction du niveau
# Calculer le minimum d'aléatoires requis pour la ligne courante
min_aleatoire = min_bloc_aleatoire(nb_ligne)
# Afficher l'état actuel du niveau
affiche_etat(niveau, ligne, min_aleatoire, nb_bloc_F, nb_ligne)
# Demander le choix de l'utilisateur
if choix == -1: # Choix invalide, recommencer
# Traitement d'un choix de bloc (A à F)
if choix_est_bloc(choix):
quantite = demande_quantite()
# Vérifier que l'ajout ne dépasse pas la largeur maximale
if nb_bloc + quantite > MAX_COLONNES:
print("Erreur : la ligne dépasserait " + str(MAX_COLONNES) + " colonnes.")
# Ajouter les blocs à la ligne et mettre à jour les compteurs
ligne += BLOC_A * quantite
ligne += BLOC_B * quantite
ligne += BLOC_C * quantite
ligne += BLOC_D * quantite
ligne += BLOC_E * quantite
# Chaque bloc aléatoire est tiré individuellement
for i in range(quantite):
ligne += resoudre_bloc_aleatoire(difficulte)
# Traitement des commandes NL et FIN
# Vérifier que la ligne a au moins 5 blocs
if nb_bloc < MIN_COLONNES:
print("Erreur : la ligne doit contenir au moins " + str(MIN_COLONNES) + " blocs.")
# Vérifier que le minimum de blocs aléatoires est atteint
if nb_bloc_F < min_aleatoire:
print("Erreur : il faut au moins " + str(min_aleatoire) + " bloc(s) aléatoire(s) sur cette ligne.")
# Empiler la ligne complétée au-dessus des précédentes
niveau = ligne + "\n" + niveau
# Vérifier la limite de 8 lignes
if nb_ligne >= MAX_LIGNES:
print(" Le niveau a atteint " + str(MAX_LIGNES) + " lignes. Fin automatique.")
# Réinitialiser pour la nouvelle ligne
# Calcul et affichage du score de complexité
score_complexite = calcul_score_complexite(
nb_total_A, nb_total_B, nb_total_C, nb_total_D, nb_total_E, nb_total_F,
print("Score de complexité : " + str(score_complexite))
print("────────────────────────────────────────────────")
print("────────────────────────────────────────────────")
# Sauvegarde dans un fichier texte (BONUS)
# fichier = open("niveau.txt", "w")
# print(" Niveau sauvegardé dans « niveau.txt »")