Chaque joueur dispose d'une grille quadrillée horizontalement de 1 à 10 et verticalement de A à J. Les joueurs placent leur bateaux comme ils le souhaitent sur leur propre grille, en se cachant de leur adversaire.
Ensuite les joueurs font un tir chacun leur tour.
Quand vient son tour, un joueur annonce où il tire. Par exemple B7. L'adversaire réponde À l'eau si le tir n'a rien touché ou bien Touché quand le tir a touché un bateau et si toutes les cases du bateau ont été touchées, l'adversaire doit même annoncer Coulé.
Le premier à couler la flotte de son adversaire à gagné.
Tout d'abord, il est toujours préférable de placer dans des constantes les grands paramètres de jeu. Par exemple, ici, la grille a une largeur de 10 cases. Plutôt que d'écrire 10 un peut partout dans le programme, il est préférable d'écrire quelque chose comme TAILLE = 10 et d'écrire TAILLE un peut partout dans le programme.
Bien que la grille soit une grille à 2 dimensions, on va procéder un peu différemment. On choisit de numéroter chaque case selon son ordre sa position dans l'ordre de lecture.
Ainsi la case F5 correspond au numéro 54.
Il faudra donc prévoir une fonction…
def adresse_to_coords(adresse:str) -> int,int:
"""
adresse: chaine comme "F5"
renvoie la ligne et la colonne.
Pour "F5", renvoie 5, 4
"""
On décide qu'une case vide contiendra 0. La grille entièrement vide sera donc :
grille_vide = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
À la bataille navale, chaque joueur dispose des navires suivants :
Le nom des navires n'a pas d'importance. On décide d'allouer à chaque bateau un numéro pour les identifier. 1 pour le porte-avions, 2 pour le croiseur, 3 et 4 pour les contre-torpilleurs et 5 pour le torpilleur.
Voici une grille de jeu possible :
grille = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 2, 2, 2, 2, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 5, 5, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 4, 0, 0, 1, 0,
0, 0, 0, 0, 0, 4, 0, 0, 0, 0,
0, 3, 3, 3, 0, 4, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Par exemple ici, le croiseur est au indices 13 à 16, c'est à dire aux positions B4 à B7.
On veut une fonction lire(grille:list, line:int, col:int) -> int qui pour une grille de jeu et une position donnée par sa ligne et sa colonne, renvoie le contenu de la case.
Avec la grille précédente, il faut que lire(grille, 1, 3) renvoie 2.
On veut une fonction ecrire(grille:list, line:int, col:int, valeur:int) permettant d'écrire la valeur indiquée à la position demandée dans la grille.
Par exemple, si avec la grille précédente, on exécute ecrire(grille, 1, 3, 0), la grille devient :
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 5, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
On a besoin d'une fonction coulé(grille:list, navire:int) -> bool
grille est la grille de jeunavire est le numéro de navire, par exemple 1 pour le porte-avionsTrue si ce navire est coulé, c'est à dire si l'entier identifiant le navire n'est plus présent dans la grille.Quand on tire sur une flotte, on veut savoir si on a touché et éventuellement si on a coulé.
Il faut donc une fonction tir(flotte:list, line:int, col:int) -> (bool,bool),
True, False indique que c'est « touché » mais pas « coulé ».0.Par exemple, avec la grille précédente :
touché, coulé = tir(grille, 1, 7) # touché est True # coulé est False # la grille devient : [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 5, 5, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 3, 3, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
On veut une fonction vide(grille:list) -> bool qui renvoie True quand la grille est vide.
Dans le but de pouvoir jouer avec la machine on voudrait pouvoir remplir une grille aléatoirement.
C'est un problème difficile. Dans un premier temps vous pouvez vous contenter d'imposer une grille fixe à la machine. Dans un deuxième temps, vous pouvez fournir à la machine une quantité raisonnable de grille prédéfinies et lui faire choisir aléatoirement parmi ces grilles. Et puis si vous avez une bonne idée, vous pouvez lui faire placer aléatoirement ses navires.
Pas obligatoire dans la version la plus simple !
Il est plus confortable pour le joueur de garder la trace des tentatives qu'il a effectuées. On pourrait alors entretenir une grille de même format que la précédente mais qui contiendrait :
0 pour une case dans laquelle on n'a pas encore tiré,1 pour un tir qui a touché,2 pour un coup à l'eauIl faudrait donc maintenir cette grille à jour au cours de la partie. De plus, pour qu'elle ait un intérêt, il faudrait prévoir une fonction d'affichage. Un affichage texte en console est tout à fait possible. Voici un exemple :
def affichage_cible(cible):
SYMBOLES = " XO"
result =" "
for i in range(TAILLE):
result += f"{i+1:02d}"
for i, item in enumerate(cible):
if i%TAILLE == 0:
line = i//TAILLE
result += "\n\n"
result += chr(line + 65)
result += " " + SYMBOLES[item]
return result
Ces fonctions étant définies, vous avez les ingrédients pour lancer le jeu. À vous de les assembler !
Vous pouvez créer une version de jeu simplifiée ou l'humain est le seul à tirer :