Table des matières
Bataille navale
Présentation
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é.
Les ingrédients nécessaires
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.
La grille de jeu
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]
Stocker la position d'une flotte
À la bataille navale, chaque joueur dispose des navires suivants :
- 1 porte-avions : 5 cases,
- 1 croiseur : 4 cases,
- 2 contre-torpilleurs : 3 cases
- 1 torpilleur : 2 cases
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.
Lire, écrire
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]
Coulé
On a besoin d'une fonction coulé(grille:list, navire:int) -> bool
grilleest la grille de jeunavireest le numéro de navire, par exemple1pour le porte-avions- la fonction renvoie
Truesi ce navire est coulé, c'est à dire si l'entier identifiant le navire n'est plus présent dans la grille.
Tir
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),
- on précise en entrée la flotte de l'adversaire et la case ciblée,
- la fonction doit renvoyer deux booléens. Le premier indique si un navire est touché et le second indique si un navire est coulé. Par exemple, le retour
True, Falseindique que c'est « touché » mais pas « coulé ». - en cas de « touché », la flotte est modifiée en remplaçant la position par
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]
vide
On veut une fonction vide(grille:list) -> bool qui renvoie True quand la grille est vide.
grille aléatoire
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.
Mémoire des coups tirés
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 :
0pour une case dans laquelle on n'a pas encore tiré,1pour un tir qui a touché,2pour un coup à l'eau
Il 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
Tout mettre ensemble
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 :
- au démarrage du jeu, la machine initialise sa propre grille,
- l'ordinateur ne tire pas,
- à chaque tour, le joueur est invité à entrer une adresse de tir,
- la machine essaie cette adresse sur sa grille et répond au joueur : manqué, touché ou coulé.
- Le joueur recommence jusqu'à avoir coulé la flotte de la machine ou bien on peut décider d'un nombre maximal de coups autorisés.

