Python

Les Listes
Pour aller plus loin...

On souhaite à présent poursuivre les exercices réalisés précédemment pour améliorer notre chasse au trésor.

Chasse au trésor (2)

Cet exercice est la suite de celui-ci !

Pour cette deuxième partie, le programme doit :

  1. reprendre les éléments de la partie précédente.
  2. faire en sorte que l'utilisateur ne puisse pas faire de proposition en-dehors des indices possibles.
  3. faire jouer l'utilisateur jusqu'à ce que celui-ci découvre l'indice d'emplacement du trésor. Il faudra faire appel à une (ou plusieurs) fonction(s).
  4. afficher le nombre de coups qu'il a fallu au jour pour déterminer cet emplacement (et afficher la liste pour vérification).

On redonne ci-dessous le programme trouvé lors de la partie précédente :


                    
                    
  • Une piste ?
  • Une autre piste ?
Il faut créer une première fonction pour vérifier que la proposition de l'utilisateur ne sort pas de la liste.
Une seconde fonction paraît nécessaire (mais n'est pas indispensable) pour la réponse du programme à la proposition de l'utilisateur.

##----- Importation des modules -----##
from random import *

##----- Définition des fonctions -----##
def demande(n):
    """ Entrees : l'entier n est la longueur d'une liste
        Sorties : un entier saisi par l'utilisateur et compris entre 0 et n-1 """
    while True:
        try:
            prop = int(input('Donner un indice entre {} et {} : '.format(0, n-1)))
            if 0 <= prop <= n-1:
                break
        except:
            print('Un entier entre {} et {}, merci : '.format(0, n-1))
    return prop


def test(prop, indice):
    """ Entrees : indice est la position du tresor, prop est la proposition du joueur
        Sorties : une chaine de caracteres affichee par le programme principal """
    if prop == indice:
        reponse = 'Bravo !'
    elif prop > indice:
        reponse = 'Cherche a gauche'
    else:
        reponse = 'Cherche a droite'
    return reponse

##----- Initialisation des variables -----##
n = int(input("Entrez la valeur d'un entier : "))
liste = [0]*n						# Liste de n zéros

indice = randint(0, n-1)			# Indice de "1" dans la liste
liste[indice] = 1


##----- Programme principal -----##
prop = demande(n)
reponse = test(prop, indice)
print(reponse)
nb_coups = 1

while reponse != 'Bravo !':
    prop = demande(n)
    reponse = test(prop, indice)
    print(reponse)
    nb_coups += 1

print(liste)
print('Vous avez reussi en {} coups.'.format(nb_coups))
						

Chasse au trésor (3)

Puisque le joueur doit indiquer dans quelle case il cherche, il faudra qu'un affichage correct du plateau de jeu lui permette de visualiser les numéros des lignes et des colonnes.

Voici l'affichage attendu après exécution du programme à ce stade :

[' ', '1', '2', '3', '4', '5', '6', '7', '8', '9']
['1', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['2', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['3', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['4', ' ', ' ', ' ', ' ', ' ', ' ', 'X', ' ', ' ']
['5', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['6', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['7', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['8', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
['9', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']

Les conventions d'affichages et le travail demandé sont :

  1. Concevoir le plateau comme une liste de 10 listes ayant chacune 10 éléments ;
  2. Pour que l'affichage final soit plus agréable, les éléments seront forcément des caractères uniques :
    • Les caractères de '1' à '9' indique le numéro de ligne et/ou de colonne d'une case ;
    • Le caractère espace ' ' indique une case «vide» non encore visitée par le joueur ;
    • Le caractère 'X' représente l'emplacement du trésor. Dans la version finale du programme, le trésor n'apparaîtra plus mais, pour vérifier le bon fonctionnement du programme à chaque nouvelle étape, il est utile de le visualiser pour l'instant ;
    • Enfin, le caractère '0' représentera les cases déjà visitées par l'utilisateur (à voir dans une prochaine étape).
    Insérez les numéros de lignes et de colonnes dans la première ligne et la première colonne puis remplissez toutes les autres cases par des caractères espace ' '.
  3. Placez aléatoirement le caractère 'X' qui représente le trésor dans le plateau.

                    
                    
  • Une piste ?
  • Une autre piste ?
  • Le plateau ?
  • Le trésor ?

Commencez par créer un plateau «vide», remplit de caractères espaces ' ' et sans faire de copier/coller inutile.

En ce qui concerne l'affichage, il faut le réaliser ligne par ligne, c'est-à-dire liste par liste...

Pour compléter la 1ère ligne et la 1ère colonne, il peut être utile d'utiliser la fonction de conversion de type str().

Il existe plusieurs moyens pour générer le plateau. Voici un nouvel exemple d'automatisation par rapport à d'autres solutions déjà données dans ce site :


##----- Variables et constantes -----##
taille = 10                     	# Plateau carré de taille lignes et taille colonnes
plateau = []
for i in range(taille):
    ligne = [' ']*taille
    plateau.append(ligne)
						

On importe le module random et on génère les coordonnées du trésor sous la forme d'une liste :


##----- Importation des Modules -----##
from random import *

##----- Variables et constantes -----##
ligne_tresor = randint(1, taille-1)
col_tresor = randint(1, taille-1)
						

On termine le programme en remplissant et affichant la grille.


##----- Importation des Modules -----##
from random import *

##----- Variables et constantes -----##
taille = 10                     	# Plateau carré de taille lignes et taille colonnes
plateau = []
for i in range(taille):
    ligne = [' ']*taille
    plateau.append(ligne)

ligne_tresor = randint(1, taille-1)
col_tresor = randint(1, taille-1)



##----- Programme principal -----##
for i in range(1, taille):          # On remplit la grille des coordonnées
    plateau[0][i] = str(i)
    plateau[i][0] = str(i)

plateau[ligne_tresor][col_tresor] = 'X'

for ligne in plateau:
    print(ligne)
						

Chasse au trésor (4)

On rappelle : un trésor est caché dans le plateau de jeu et l'utilisateur donne un couple de coordonnées [ligne, colonne] afin de découvrir où se cache le trésor. Le programme doit vérifier que la proposition est valide puis afficher la case correspondante sous forme du caractère 'O' dans la grille.

Concevoir une fonction demander() qui répond à ce principe.


                    
                    
  • Une piste ?
  • Une autre piste ?
Pour chaque coordonnée saisie, il faut vérifier qu'elle se situe bien entre deux valeurs autorisée. La fonction demander() doit donc nécessiter deux arguments.
Grâce à la fonction demander(), on vérifie que la 1ère coordonnée est correcte, puis on recommence pour la 2nde coordonnée. Enfin, l'affichage de cette position dans la grille sera assuré par le programme principal.

##----- Définition des Fonctions -----##
def demander(a, b):
    """ Entrees : a et b sont deux entiers tels que a < b
        Sorties : renvoie un entier saisi par l'utilisateur et compris entre a et b."""
    while True:                                         # Attention, boucle infinie !
        try:
            valeur = int(input('Saisir un entier entre {} et {} : '.format(a, b)))
            if a <= valeur <= b:
                break                                   # On sort
            else:
                print('Un entier entre {} et {}, merci !'.format(a, b))
        except:                                         # Il y a une erreur
            print('Un entier entre {} et {}, merci !'.format(a, b))
    return valeur

##----- Programme principal -----##
print('Entrez un numero de ligne.')
ligne = demander(1, taille-1)
print('Entrez un numero de colonne.')
colonne = demander(1, taille-1)
						

On termine le programme en affichant le plateau après la proposition de l'utilisateur.


##----- Importation des Modules -----##
from random import *

##----- Définition des Fonctions -----##
def demander(a, b):
    """ Entrees : a et b sont deux entiers tels que a < b
        Sorties : renvoie un entier saisi par l'utilisateur et compris entre a et b."""
    while True:                                         # Attention, boucle infinie !
        try:
            valeur = int(input('Saisir un entier entre {} et {} : '.format(a, b)))
            if a <= valeur <= b:
                break                                   # On sort
            else:
                print('Un entier entre {} et {}, merci !'.format(a, b))
        except:                                         # Il y a une erreur
            print('Un entier entre {} et {}, merci !'.format(a, b))
    return valeur

##----- Variables et constantes -----##
taille = 10                     	# Plateau carré de taille lignes et taille colonnes
plateau = []
for i in range(taille):
    ligne = [' ']*taille
    plateau.append(ligne)

ligne_tresor = randint(1, taille-1)
col_tresor = randint(1, taille-1)

##----- Programme principal -----##
for i in range(1, taille):          # On remplit la grille des coordonnées
    plateau[0][i] = str(i)
    plateau[i][0] = str(i)

plateau[ligne_tresor][col_tresor] = 'X'

print('Entrez un numero de ligne.')
ligne = demander(1, taille-1)
print('Entrez un numero de colonne.')
colonne = demander(1, taille-1)

plateau[ligne][colonne] = 'O'

##----- Tracé de la grille -----##
for ligne in plateau:
    print(ligne)
						

Chasse au trésor (5)

On récapitule : un trésor est caché dans le plateau de jeu et l'utilisateur donne un couple de coordonnées [ligne, colonne] afin de découvrir où se cache le trésor. Le programme doit lui répondre «droite» si le trésor est à droite de cette proposition, «gauche» s'il est à gauche, «haut» si le trésor se trouve au-dessus et «bas» pour en-dessous, en accolant éventuellement deux de ces informations.

Concevoir une fonction position() qui répond à ce principe. Bien évidemment, la fonction renvoie 'Bravo !' dans le cas où le trésor est découvert.


                    
                    
  • Une piste ?
  • Une étape ?

Concevoir d'un coup et en totalité cette fonction risque d'être difficile. Au lieu de traiter les quatre positions en une fois, pourquoi ne pas commencer par vérifier les positions «gauche» et «droite» ?

Pour cela, on peut définir une fonction gauche_droite() en raisonnant sur les colonnes, c'est-à-dire sur la 2nde coordonnée.
Quels sont les numéros de colonnes possibles pour que le trésor se situe à gauche de la proposition du joueur ? et à droite ?


##----- Définition des Fonctions -----##
def gauche_droite(col_jouee, col_tresor):
    """ Entrees : col_jouee est l'ordonnee a tester, col_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en colonne """
    if col_jouee < col_tresor:
        return ' a droite'
    elif col_jouee > col_tresor:
        return ' a gauche'
    else:
        return ''

##----- Programme principal -----##
print('Le tresor est a {}'.format(gauche_droite(colonne, col_tresor)))
						

Une fois le principe compris, on peut définir une fonction haut_bas() équivalente qui servira à définir la fonction position().


##----- Définition des Fonctions -----##
def gauche_droite(col_jouee, col_tresor):
    """ Entrees : col_jouee est l'ordonnee a tester, col_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en colonne """
    if col_jouee < col_tresor:
        return ' a droite'
    elif col_jouee > col_tresor:
        return ' a gauche'
    else:
        return ''


def haut_bas(ligne_jouee, ligne_tresor):
    """ Entrees : ligne_jouee est l'abscisse a tester, ligne_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en ligne """
    if ligne_jouee < ligne_tresor:
        return ' en bas'
    elif ligne_jouee > ligne_tresor:
        return ' en haut'
    else:
        return ''


def position(ligne_jouee, ligne_tresor, col_jouee, col_tresor):
    """ Entrees : les arguments sont des entiers strictement positifs
        Sorties : renvoie une chaine de caractere sur la position du tresor """
    vertical = haut_bas(ligne_jouee, ligne_tresor)
    horizontal = gauche_droite(col_jouee, col_tresor)

    if vertical == '' and horizontal == '':
        return 'Bravo, le tresor est decouvert !'
    else:
        return 'Cherchez{}{}.'.format(vertical, horizontal)
						

On termine le programme en affichant le plateau après la proposition de l'utilisateur puis on affiche l'indication.


##----- Importation des Modules -----##
from random import *

##----- Définition des Fonctions -----##
def demander(a, b):
    """ Entrees : a et b sont deux entiers tels que a < b
        Sorties : renvoie un entier saisi par l'utilisateur et compris entre a et b."""
    while True:                                         # Attention, boucle infinie !
        try:
            valeur = int(input('Saisir un entier entre {} et {} : '.format(a, b)))
            if a <= valeur <= b:
                break                                   # On sort
            else:
                print('Un entier entre {} et {}, merci !'.format(a, b))
        except:                                         # Il y a une erreur
            print('Un entier entre {} et {}, merci !'.format(a, b))
    return valeur

def gauche_droite(col_jouee, col_tresor):
    """ Entrees : col_jouee est l'ordonnee a tester, col_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en colonne """
    if col_jouee < col_tresor:
        return ' a droite'
    elif col_jouee > col_tresor:
        return ' a gauche'
    else:
        return ''

def haut_bas(ligne_jouee, ligne_tresor):
    """ Entrees : ligne_jouee est l'abscisse a tester, ligne_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en ligne """
    if ligne_jouee < ligne_tresor:
        return ' en bas'
    elif ligne_jouee > ligne_tresor:
        return ' en haut'
    else:
        return ''

def position(ligne_jouee, ligne_tresor, col_jouee, col_tresor):
    """ Entrees : les arguments sont des entiers strictement positifs
        Sorties : renvoie une chaine de caractere sur la position du tresor """
    vertical = haut_bas(ligne_jouee, ligne_tresor)
    horizontal = gauche_droite(col_jouee, col_tresor)

    if vertical == '' and horizontal == '':
        return 'Bravo, le tresor est decouvert !'
    else:
        return 'Cherchez{}{}.'.format(vertical, horizontal)

##----- Variables et constantes -----##
taille = 10                     	# Plateau carré de taille lignes et taille colonnes
plateau = []
for i in range(taille):
    ligne = [' ']*taille
    plateau.append(ligne)

ligne_tresor = randint(1, taille-1)
col_tresor = randint(1, taille-1)

##----- Programme principal -----##
for i in range(1, taille):          # On remplit la grille des coordonnées
    plateau[0][i] = str(i)
    plateau[i][0] = str(i)

plateau[ligne_tresor][col_tresor] = 'X'

print('Entrez un numero de ligne.')
ligne = demander(1, taille-1)
print('Entrez un numero de colonne.')
colonne = demander(1, taille-1)

plateau[ligne][colonne] = 'O'

##----- Tracé de la grille -----##
for ligne in plateau:
    print(ligne)

print(position(ligne, ligne_tresor, colonne, col_tresor))
						

Chasse au trésor (6)

Il ne reste qu'à mettre les éléments ensemble. Le joueur doit faire des propositions jusqu'à découvrir le trésor. Lorsqu'il l'obtient, il est content. Bien évidemment, le trésor reste affiché dans la grille pour tester le fonctionnement du programme. On masquera ensuite le 'X' pour obtenir un jeu fonctionnel.

On n'oublie pas non plus l'affichage du score...


                    
                    
  • Une piste ?
  • Une autre piste ?
On définit une nouvelle fonction qui reprend une grande partie du programme principal tant que...
Si vous avez besoin d'une autre piste maintenant, c'est que vous n'avez pas travaillé assez consciencieusement dans les étapes précédentes. Recommencez-les !

##----- Importation des Modules -----##
from random import *

##----- Définition des Fonctions -----##
def demander(texte, a, b):
    """ Entrees : a et b sont deux entiers tels que a < b, texte est une chaine de caracteres
        Sorties : renvoie un entier saisi par l'utilisateur et compris entre a et b."""
    while True:                                         # Attention, boucle infinie !
        try:
            valeur = int(input('{} - saisir un entier entre {} et {} : '.format(texte, a, b)))
            if a <= valeur <= b:
                break                                   # On sort
            else:
                print('Un entier entre {} et {}, merci !'.format(a, b))
        except:                                         # Il y a une erreur
            print('Un entier entre {} et {}, merci !'.format(a, b))
    return valeur

def gauche_droite(col_jouee, col_tresor):
    """ Entrees : col_jouee est l'ordonnee a tester, col_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en colonne """
    if col_jouee < col_tresor:
        return ' a droite'
    elif col_jouee > col_tresor:
        return ' a gauche'
    else:
        return ''

def haut_bas(ligne_jouee, ligne_tresor):
    """ Entrees : ligne_jouee est l'abscisse a tester, ligne_tresor est celle du tresor
        Sorties : renvoie une chaine de caracteres qui indique la position en ligne """
    if ligne_jouee < ligne_tresor:
        return ' en bas'
    elif ligne_jouee > ligne_tresor:
        return ' en haut'
    else:
        return ''

def position(ligne_jouee, ligne_tresor, col_jouee, col_tresor):
    """ Entrees : les arguments sont des entiers strictement positifs
        Sorties : renvoie une chaine de caractere sur la position du tresor """
    vertical = haut_bas(ligne_jouee, ligne_tresor)
    horizontal = gauche_droite(col_jouee, col_tresor)

    if vertical == '' and horizontal == '':
        return 'Bravo, le tresor est decouvert !'
    else:
        return 'Cherchez{}{}.'.format(vertical, horizontal)

def afficher(grille):
    """ Entrees : grille est une liste de listes
        Sorties : affiche cette grille sous-liste par sous-liste """
    for liste in grille:
        print(liste)
    print('')						# Pour sauter une ligne...

def jouer(grille, ligne_tresor, col_tresor):
    """ Entrees : grille de jeu et coordonnees du tresor
        Sorties : renvoie le score du joueur """
    taille = len(grille)
    ligne, colonne = -1, -1         # Premières coordonnées fictives, hors de la grille
    score = 0

    while ligne != ligne_tresor or colonne != col_tresor:
        ligne = demander('Ligne', 1, taille-1)
        colonne = demander('Colonne', 1, taille-1)
        grille[ligne][colonne] = 'O'
        afficher(grille)
        print(position(ligne, ligne_tresor, colonne, col_tresor))
        score += 1

    print('Vous avez reussi en {} coups.'.format(score))

##----- Variables et constantes -----##
taille = 10                     	# Plateau carré de taille lignes et taille colonnes
plateau = []
for i in range(taille):
    ligne = [' ']*taille
    plateau.append(ligne)

ligne_tresor = randint(1, taille-1)
col_tresor = randint(1, taille-1)

##----- Programme principal -----##
for i in range(1, taille):          # On remplit la grille des coordonnées
    plateau[0][i] = str(i)
    plateau[i][0] = str(i)

# Affichage pour les test
# plateau[ligne_tresor][col_tresor] = 'X'

afficher(plateau)
jouer(plateau, ligne_tresor, col_tresor)