[Python] Pourquoi mon while str in list: ne fonctionne pas avec liste imbriquée ?

Répondre
Partager Rechercher
Salut les codeurs,

je m'initie à Python depuis peu, et en tentant de faire un jeu de bataille navale, je bute sur un truc.

Je fais construire un tableau de jeu qui est de la forme tableau[['O','O','O'],['O','O','O'],['O','O','O']], et je change des O en X là où je mets des bateaux.

Pour faire une boucle de jeu tant que tous les bateaux n'ont pas été touché, je pensais naïvement faire une vérification après chaque tour de jeu avec le test suivant :

Code:
while "X" in tableau:
    faire jouer

print("Gagné")
Sauf que au final, il ne me trouve jamais de "X". D'ailleurs si je fais un :
Code:
if "O" in tableau:
    test
Pareil, ça ne me retourne rien. Pas d'erreur, il trouve juste pas la donnée dans ma liste.

J'ai compris que ça venait du fait que j'ai des listes dans ma liste. Si je fais un
Code:
if "X" in tableau[cpteur] 
    print("X est dans la ligne ", cpteur)
cpteur += 1
Ça fonctionne. Mais c'est moins satisfaisant, car je dois faire du coup une boucle supplémentaire (pour checker chaque index du tableau).

Il n'y a pas d'autre solution ?

Merci.
Sinon tu geres ton tableau de ligne en un seul tableau ['O','O','O','O','O','O','O','O','O'].

Pour trouver les lignes au sein du tableau tu sais que l'indice de la nouvelle ligne commence a i*l, i etant le n° de la ligne et l la longueur de la ligne (avec l=3 dans l'exemple). Et pour avoir les colonnes ca fait i*l+j, j etant le n° de la colonne.
Ton tableau, c'est une liste de listes. Quand tu le parcours, tu reçois une liste, et non une chaîne de caractères.

Si tu veux garder ce schéma de données, il faut que tu fasses deux boucles.
Citation :
Publié par Drachen
Une possibilité serait de concaténer toutes les sous-listes pour n'en faire qu'une seule liste.

while 'X' in sum(tableau,[]):
___faire jouer
Ah génial, effectivement, du coup, ça fonctionne ! Merci. En plus je n'avais jamais utilisé sum(), je n'aurais donc jamais pensé que ça pouvait s'utiliser sur une liste de str.

Citation :
Publié par -Interfector-
Sinon tu geres ton tableau de ligne en un seul tableau ['O','O','O','O','O','O','O','O','O'].

Pour trouver les lignes au sein du tableau tu sais que l'indice de la nouvelle ligne commence a i*l, i etant le n° de la ligne et l la longueur de la ligne (avec l=3 dans l'exemple). Et pour avoir les colonnes ca fait i*l+j, j etant le n° de la colonne.
C'est une solution en effet, mais c'est moins pratique pour moi : je vais demander au joueur des coordonnées pour placer un bateau ou tenter un tir, un format [x][y] est donc plus logique à manier.

Citation :
Publié par Adau
Ton tableau, c'est une liste de listes. Quand tu le parcours, tu reçois une liste, et non une chaîne de caractères.

Si tu veux garder ce schéma de données, il faut que tu fasses deux boucles.
Je voulais éviter les deux boucles, donc la première solution donnée me convient à merveilles.
Cela dit, je comprends mieux la logique, pour python, le premier élément de ma liste est une liste, pas un élément unique, et donc il ne va pas chercher les valeurs dans cette sous-liste.

Merci pour vos réponses !
Citation :
Publié par Pitit Flo -TMP
C'est une solution en effet, mais c'est moins pratique pour moi : je vais demander au joueur des coordonnées pour placer un bateau ou tenter un tir, un format [x][y] est donc plus logique à manier.
Si tu veux rester sur une dimension tu peux aussi utiliser un hash où tes clefs sont la concaténation de x et y
Je dis peut être une connerie vu que je connais pas beaucoup le python, mais pour faire ce que tu veux, j'aurai fait deux boucles imbriquées :

Code:
while ligne in tableau
    while x in ligne
       do something
edit : pwned depuis longtemps, ça m'apprendra à lire en diagonale
Dans la boucle for, le x prend toutes les valeurs du tableau.

Dans la boucle while, x est fixé, et on effectue la boucle tant que x appartient au tableau.

For x in tableau -> Pour tout x appartenant au tableau.
While x in tableau -> Tant que x (fixé) appartient au tableau

Edit : la solution de Metalovichinkov ne fonctionne donc pas. Il faudrait remplacer les deux While par deux For.

Dernière modification par Melchiorus ; 27/10/2016 à 10h27.
Citation :
Publié par Pitit Flo -TMP
Tiens, petit up.
Quelqu'un peut m'expliquer pourquoi la forme
"while x in tableau" ne fonctionne pas, alors qu'en revanche ceci fonctionne ?
Car tu ne vérifie pas la même variable.
Dans ce code là :
Code:
while "X" in tableau:
    faire jouer
tu vas boucler sur le tableau, et vérifier si il y a encore un "X" dans les valeurs retournées. Sauf que les valeurs retournées sont des listes elles aussi, comme tu disais.

Alors que dans :
Code:
for x in tableau:
    if "X" in x:
        print("Il reste des bateaux")
tu fais deux choses : d'abord tu boucles sur le tableau, comme précédemment, et tu récupères chaque valeur x (donc chaque liste). Ensuite tu vérifie dans cette liste récupérée si "X" y est présent.

En exemple :
Code:
for x in tableau:
    print x
retournera par exemple [0, 0, 0], puis [0, "X", 0], puis [0, 0, 0].

Dans cette boucle,
Code:
if "X" in x:
    print "ok"
vérifiera si dans [0, 0, 0] il y a "X", puis à l'itération suivante si dans [0, "X", 0] il y a X et printera donc "ok", puis si dans la dernière valeur x [0, 0, 0] il y a "X".

Dernière modification par Selty ; 27/10/2016 à 10h26.
Citation :
Publié par Pitit Flo -TMP
C'est une solution en effet, mais c'est moins pratique pour moi : je vais demander au joueur des coordonnées pour placer un bateau ou tenter un tir, un format [x][y] est donc plus logique à manier.

Si tes lignes de tableau ont une taille fixe alors tableau[x][y] == tableau[y * taille_ligne + x] en une seule dimension.

D'une maniere generale c'est plus propre de bosser avec le moins de dimension possible (avec un tableau de tableau, chaque acces a une nouvelle ligne = un potentiel acces memoire. Une seule ligne = tout le tableau est charge dans le cache du CPU)
Citation :
Publié par Pitit Flo -TMP
Tiens, petit up.
Quelqu'un peut m'expliquer pourquoi la forme
"while x in tableau" ne fonctionne pas, alors qu'en revanche ceci fonctionne ?
Code:
for x in tableau:
    if "X" in x:
        print("Il reste des bateaux")
Le for en python consiste à itérer sur une variable. Par exemple ici tu peut itérer sur une liste et en afficher le contenu.
Code:
for element in liste:
   print(element)
Le while est un if qui se répète tant que la condition à l'intérieur est vrai :
Code:
while true :
  print("infini")
Partant de là :
Code:
 while 'X' in liste
signifie que tu va effectuer ce qui dans la boucle tant que 'X' est dans la liste.

Tu rencontres le même problème que tout à l'heure les éléments de ta liste sont des listes.
Une solution :
Code:
while 'X' in sum(liste,[]) :
Marrant en cours de programmation je leur fais faire un bataille navale
Si ton test (X dans tableau) sert à vérifier si la partie est terminée, plutôt que reparcourir le tableau à chaque fois (pourquoi un X d'ailleurs ?) tu peux aussi mettre en place un compteur qui indique le nombre de cases correspondant à des bateaux (ou partie de bateaux) encore en vie. Il suffit de le décrémenter à chaque tir réussi.
Merci pour ces retours, je crois que je comprends mieux.

Kermo : un X parce que mon tableau de base est rempli de O, et lorsqu'un bateau est positionné au départ, je change les O de la zone en X, chaque X représentant un bout de bateau pas encore coulé. Les bouts touchés sont des = et les tirs ratés sont des *. Donc tant qu'il reste des X dans la liste, c'est qu'il reste du bateau touché.
L'avantage c'est que comme j'ai choisi de demander en début de partie aux joueurs la taille du terrain (de 3*3 à 10*10), en vérifiant la présence de X plutôt qu'un compteur, je n'ai pas besoin de complexifier : quelque soit la taille du terrain, mon « while » est valable.
Cela dit, je pourrai compter au départ de la partie le nombre de "X" et donner cette valeur au compteur et avoir un while compteur > 0, en décrémentant le compteur à chaque fois qu'un bateau est touché.
Je trouve plus simple de checker les X, mais peut-être que dans l'absolu, si on pouvait avoir des tableaux immenses, ça serait moins rapide, c'est ça ?

En tout cas, là où je commence à me casser la tête, c'est sur l'option que j'avais prévue de mettre, à savoir pouvoir jouer contre l'ordi et donc faire des placements automatiques de bateau par l'ordi. Ce qui nécessite tout un tas de vérifications pour que les placements respectent les règles de base.
Ce que je pige pas c'est comment tu différencies les bateaux si tu ne peux avoir que des X ou des O dans la grille.

Pour les placer, on peut faire une boucle sur les bateaux. À l'intérieur de cette boucle on génère une position aléatoire (la direction d'abord, puis la position de la première case qui dépend de la direction pour pouvoir passer dans la grille). On regarde si toutes les cases sont dispo, et si oui c'est bon pour ce bateau, dans le cas contraire on recommence avec une autre position aléatoire.
C'est l'idée pour le placement, oui, tout en checkant si les cases autour sont également libres (par le droit de coller 2 bateaux) et en vérifiant également qu'on sort pas de la bordure du jeu.
Mais je dois avant ça définir dans un fichier externe des listes de bateaux en fonction de leur taille, et prévoir un système qui défini combien de bateau de chaque type sera placé sur le terrain, en fonction de la taille du terrain.

Je ne comprends pas le problème pour différencier les bateaux. Mais pour être bien au clair, j'ai 2 tableaux, celui du joueur 1 et celui du joueur 2, chacun ayant 2 tableaux :*un tableau qui recense là sont ses bateaux (il ne le voit qu'au départ, pas ensuite), et un qui montre là où il a tiré et éventuellement touché les bateaux de l'adversaire (qu'il voit donc après chaque coup joué).
Du coup, chaque joueur a sur son tableau propre (là où il place ses bateaux), sur lequel il a des O là où la case est vide et des X là où son bateau est présent.
Ok, pour mon exercice l'ordi devait afficher le type de bateau, donc O et X ne suffisent pas dans la grille. On passait par une grille d'entiers qui indiquent ce qui se trouve là (rien, coup dans l'eau, bateau touché ou pas touché).
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés