Exercice 3 Centres étrangers – Bac NSI 2026 – Jour 1
La mise en forme de l´exercice a été légèrement remaniée, les codes sont présentés de manière très confuse dans l'original.
mots clés: POO, récursivité, BDD, SQL
🔎 Voir les exercices similaires ↓
Centres étrangers – Bac NSI 2026 – Jour 1 Énoncé de l'exercice 3
Cet exercice porte sur la programmation orientée objet, la récursivité et les bases de données relationnelles.
Le champ de mines du démineur est représenté par une grille.
Chaque case de cette grille peut cacher une mine, ou être vide.
Le déroulement du jeu :
Si on choisit sur une case libre qui a au moins une mine dans une case voisine, un chiffre apparaît. Ce chiffre indique combien de mines se trouvent dans les cases voisines. Une case a au maximum 8 cases voisines.
Si on choisit une case vide dont toutes les cases voisines sont vides, la case s’affiche vide. Ensuite, le jeu dévoile automatiquement toutes les cases vides voisines, et ainsi de suite, jusqu’à ce qu’il rencontre des cases avec des chiffres.
La fin de la partie : Si on choisit sur une mine, la partie est perdue. Si on découvre toutes les cases libres, la partie est gagnée.

Figure 1. Une grille 6x7 du démineur avec les informations du jeu.
La figure 1 représente une grille du jeu du démineur de 6 lignes : hauteur et de 7 colonnes : largeur, où l’on a dévoilé la position des 8 mines de la grille représentées par l’entier relatif -1 ainsi que les informations utiles au joueur qui lui seront dévoilées au fur et à mesure du jeu.
La case de coordonnées (1, 2) contient le chiffre 3 car elle a trois de ses cases voisines qui contiennent une mine : les cases (0, 1), (2, 2) et (1, 3).
La case (3, 6) contient le chiffre 0 car aucune case qui lui est voisine ne contient de mine.
Partie A : La classe Demineur
On propose de programmer le jeu du démineur à l’aide du langage de programmation Python. On utilise alors le paradigme de programmation orienté objet.
On donne un extrait de la classe Demineur suivante.
class Demineur :
def __init__(self, hauteur, largeur, pourcentage_mines):
'''
Pour un pourcentage de 15,6 on donnera au paramètre
pourcentage_mines la valeur de 0.156.
'''
assert ..., 'Le pourcentage de mines doit être compris entre 10% et 30%.' # ligne 7
...hauteur = hauteur # ligne 8
...largeur = largeur # ligne 9
...pourcentage_mines = pourcentage_mines # ligne 10
Recopier et compléter la ligne 7 de l’assertion pour que le pourcentage de mines respecte la précondition recommandée.
Recopier et compléter les lignes 8, 9 et 10 et compléter les pointillés avec le code manquant.
On donne les pourcentages suivants, conçus pour offrir un bon équilibre entre challenge et jouabilité.
Débutant : Grille de 8x8 avec ce qui représente 10 mines, environ 15,6% de mines.
Intermédiaire : Grille de 16x16 cases avec 40 mines, ce qui représente environ 15,6% de mines.
Expert : Grille de 30x16 cases avec 99 mines, ce qui représente environ 20,6% de mines.
3. Créer une instance demineur_intermediaire, de la classe Demineur en respectant les recommandations pour le niveau de jeu intermédiaire pour le jeu du démineur.
Partie B : Création de la grille du démineur
La grille du jeu du démineur peut être modélisée par un objet Python de type list. Par exemple une grille vide d’un démineur de hauteur 3 et de largeur 5 peut-être représentée par l’objet Python suivant :
grille_vide = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
4. Recopier et compléter la méthode grille_demineur_vide de la classe Demineur qui permet d’initialiser une grille vide du jeu.
def grille_demineur_vide(self): return [[0 for _ in range(...)] for _ in range(...)]
On ajoute dans le constructeur de la classe Demineur l’attribut grille_demineur qui va permettre d’initialiser une grille vide.
self.grille_demineur = self.grille_demineur_vide()
Les mines doivent être placées de façon aléatoire dans la grille et seront représentées par l’entier relatif -1.
On donne alors une méthode placer_mines, incomplète, de la classe Demineur.
def placer_mines(self):
'''
Cette fonction doit placer de façon aléatoire les mines dans la
grille.
Une mine sera représentée par le nombre -1.
La méthode permet de mettre à jour l'attribut grille_demineur
'''
compteur_mines = 0 # Nombre de mines placées dans la grille.
# nombre_bombes contient le nombre de mines à placer dans la grille.
nombre_bombes = self.largeur*self.hauteur*self.pourcentage_mines
while compteur_mines < nombre_bombes:
ligne = randint(0, self.hauteur - 1)
colonne = randint(0, ...) # ligne 14
if self.grille_demineur[...][...] == 0: # ligne 15
self.grille_demineur[...][...] = -1 # ligne 16
compteur_mines = ... # ligne 17
La documentation Python donne les informations suivantes :
>>> from random import randint
>>> help(randint)
Help on method randint in module random:
randint(a, b) method of random.Random instance
Return random integer in range [a, b], including both end points.
5. Recopier et compléter les lignes 14, 15, 16 et 17 de la méthode placer_mines de la classe demineur.
On dispose des deux méthodes suivantes.
def voisines(self, coordonnees_case):
'''
La méthode voisines renvoie les coordonnées des cases voisines de la case de la grille
dont les coordonnées sont données par le tuple coordonnees_case passé en paramètre.
Cette méthode renvoie une liste de tuple.
>>> demineur_1 = Demineur(3, 5,0.20)
>>> demineur_1.voisines((0, 0))
[(1, 1), (1, 0), (0, 1)]
>>> demineur_1.voisines((1, 2))
[(0, 1), (0, 3), (0, 2), (2, 1), (2, 3), (2, 2), (1, 1), (1, 3)]
'''
def nombre_voisines_avec_mines(self, coordonnees_case):
'''
La méthode nombre_voisine_avec_mines renvoie le nombre de cases voisines contenant une mine
à la case dont les coordonnées sont passés en paramètre(coordonnees_case) à la fonction.
'''
Écrire le code Python de la méthode nombre_voisines_avec_mines. On ne demande pas d’écrire le code de la méthode voisines.
Écrire une méthode generer_demineur qui permet de mettre à jour l’attribut grille_demineur pour que chaque cellule ne contenant pas de mine, contienne le nombre de mines qui lui sont voisines.
Par exemple :
>>> demineur_nsi = demineur(6, 6, 0.278) >>> demineur_nsi.generer_demineur() >>> demineur_nsi.grille_demineur [[2, -1, 2, 1, 2, 1], [2, -1, 4, -1, 2, -1], [2, 3, -1, 2, 2, 1], [2, -1, 2, 2, 1, 1], [-1, 3, 2, 2, -1, 2], [1, 2, -1, 2, 2, -1]]

Partie C : L’interface utilisateur du jeu du démineur
Les parties précédentes ont permis la création d’une grille du démineur. L’utilisateur se verra afficher une grille où les informations de la grille ne seront pas apparentes. Le joueur fait le choix d’une case et en fonction de ce choix des cases seront découvertes.
Si la case contient une mine toutes les cases sont alors dévoilées.
Dans le cas contraire une ou plusieurs cases seront dévoilées.

Sur la figure 3 on peut lire:
sur la grille de gauche, les informations du démineur.
sur la grille au centre, le visuel présenté au joueur, aucune information n’est visible au départ du jeu.
sur la grille de droite, les informations révélées quand le joueur a choisi la case de coordonnées (0, 3).
On propose de modéliser la visibilité des cellules pour l’utilisateur de la façon suivante.

Une grille est utilisée pour connaître l’état de visibilité de l’information des cases.
False : L’information de la case n’est pas visible par l’utilisateur.
True : L’information de la case est visible à l’utilisateur.
Si on considère la figure 4, le constructeur de la classe Demineur initialisera l’attribut
grille_visibilite avec [[False for_ in range(6)] for _ in range(6)].
8. Écrire une méthode visibilite de la classe Demineur qui permettrait de mettre à jour l’attribut grille_visibilite en fonction du choix de l’utilisateur d’une case du démineur. On pourra utiliser la récursivité.
Partie D : Jouer en ligne au démineur
Dans cette partie, on pourra utiliser les clauses du langage SQL pour :
construire des requêtes d’interrogation à l’aide de SELECT, FROM, WHERE
(avec les opérateurs logiques AND, OR) et JOIN ... ON ;
construire des requêtes d’insertion et de mise à jour à l’aide de UPDATE, INSERT et DELETE
affiner les recherches à l’aide de DISTINCT et ORDER BY.
On donne la possibilité aux joueurs d’enregistrer les scores en ligne pour le jeu du démineur.
On dispose d’une base de données relationnelles avec les tables suivantes.
Joueur : enregistrement du pseudo et du mot de passe de connexion du joueur.
|
||
|---|---|---|
|
pseudo | mot_de_passe |
| 1 | Grimdal | EgxGB6a3bRinllon |
| 2 | Raptor | J17NtfMS3Dudjjln |
| 3 | PetiteFée | UuukBSvj01VrGoGD |
| 4 | Kirna | 7NcDFPNl0Xy1MEPb |
Meilleur_score : enregistrement du meilleur score d’un joueur pour chaque niveau joué.
|
|||
|---|---|---|---|
| joueur | niveau | score | temps |
| 1 | facile | 1200 | 72 |
| 2 | expert | 1196 | 366 |
| 3 | intermédiaire | 997 | 230 |
| 2 | intermédiaire | 997 | 200 |
| 4 | expert | 1097 | 400 |
Demineur : enregistrement des caractéristiques de chaque niveau du démineur.
|
||
|---|---|---|
| niveau |
|
pourcentage mines |
| facile | 8x8 | ⟦CODE⟧ 15.6 |
| intermédiaire | 16x16 | ⟦CODE⟧ 15.6 |
| expert | 30x16 | ⟦CODE⟧ 20.6 |
Donner les clés étrangères de la table Meilleur_score en précisant pour chacune d’elle à quelle clé primaire elle fait référence.
Une requête envoyée à la base de données a renvoyé la réponse suivante.
| niveau | score |
|---|---|
| expert | 1196 |
| intermédiaire | 997 |
Donner une requête qui permet d’obtenir les informations du tableau précédent.
Kirna change son mot de passe par cGhhxDE4 en place de 7NcDFPNl0Xy1MEPb.
Écrire la requête qui permet de mettre à jour la table Joueur.
On donne la requête suivante.
SELECT pseudo FROM Joueur
JOIN Meilleur_score
ON Joueur.id_joueur = Meilleur_score.joueur
WHERE niveau = 'expert' AND score > 1000 AND temps < 400;
Donner le résultat de cette requête.
Une erreur a été faite à la création de la table Demineur. Le niveau facile doit être désigné par le mot débutant.
Écrire les requêtes qui permettent de corriger la base de données
Centres étrangers – Bac NSI 2026 – Jour 1 Correction de l'exercice 3
Partie A : La classe Demineur
1. Compléter l'assertion
assert 0.10 <= pourcentage_mines <= 0.30, \
'Le pourcentage de mines doit être compris entre 10% et 30%.'
2. Compléter les lignes 8, 9 et 10
self.hauteur = hauteur
self.largeur = largeur
self.pourcentage_mines = pourcentage_mines
3. Créer l'instance demineur_intermediaire
demineur_intermediaire = Demineur(16, 16, 0.156)
Partie B : Création de la grille du démineur
4. Compléter la méthode grille_demineur_vide
def grille_demineur_vide(self):
return [[0 for _ in range(self.largeur)] for _ in range(self.hauteur)]
5. Compléter la méthode placer_mines
def placer_mines(self):
compteur_mines = 0 # Nombre de mines placées dans la grille.
# nombre_bombes contient le nombre de mines à placer dans la grille.
nombre_bombes = self.largeur*self.hauteur*self.pourcentage_mines
while compteur_mines < nombre_bombes:
ligne = randint(0, self.hauteur - 1)
colonne = randint(0, self.largeur - 1) # ligne 14
if self.grille_demineur[ligne][colonne] == 0: # ligne 15
self.grille_demineur[ligne][colonne] = -1 # ligne 16
compteur_mines = compteur_mines + 1 # ligne 17
6. Écrire la méthode nombre_voisines_avec_mines
def nombre_voisines_avec_mines(self, coordonnees_case):
compteur = 0
for ligne, colonne in self.voisines(coordonnees_case):
if self.grille_demineur[ligne][colonne] == -1:
compteur += 1
return compteur
7. Écrire la méthode generer_demineur
def generer_demineur(self):
for i in range(self.hauteur):
for j in range(self.largeur):
if self.grille_demineur[i][j] != -1:
self.grille_demineur[i][j] = \
self.nombre_voisines_avec_mines((i, j))
Partie C : Interface utilisateur
8. Écrire la méthode visibilite
def visibilite(self, coordonnees):
ligne, colonne = coordonnees
if self.grille_visibilite[ligne][colonne]: # déjà dévoilée
return
if self.grille_demineur[ligne][colonne] == -1: # mine : partie perdue,
for i in range(self.hauteur): # on dévoile tout
for j in range(self.largeur):
self.grille_visibilite[i][j] = True
return
self.grille_visibilite[ligne][colonne] = True
if self.grille_demineur[ligne][colonne] == 0: # aucune mine autour :
for voisine in self.voisines(coordonnees): # on dévoile les voisines
self.visibilite(voisine)
Partie D : Jouer en ligne au démineur
9. Clés étrangères de la table Meilleur_score
| Clé étrangère | Référence |
|---|---|
| joueur | Joueur(id_joueur) |
| niveau | Demineur(niveau) |
10. Requête SQL
SELECT niveau, score
FROM Meilleur_score
WHERE joueur = 2;
Résultat obtenu :
| niveau | Score |
|---|---|
| expert | 1196 |
| intermédiaire | 997 |
11. Mise à jour du mot de passe de Kirna
UPDATE Joueur
SET mot_de_passe = 'cGhhxDE4'
WHERE pseudo = 'Kirna';
12. Résultat de la requête
SELECT pseudo
FROM Joueur
JOIN Meilleur_score
ON Joueur.id_joueur = Meilleur_score.joueur
WHERE niveau = 'expert'
AND score > 1000
AND temps < 400;
Analyse :
| Joueur | Niveau | Score | Temps |
|---|---|---|---|
| Raptor | expert | 1196 | 366 |
| Kirna | expert | 1097 | 400 |
Kirna est exclu car la condition est : temps < 400
et non : temps <= 400
Résultat :
| pseudo |
|---|
| Raptor |
13. Corriger la table Demineur
INSERT INTO Demineur
VALUES ('débutant', '8x8', 15.6);
Le niveau facile est utilisé dans Meilleur_score (joueur 1) : on y remplace facile par débutant, puis on supprime l’ancien niveau.
UPDATE Meilleur_score
SET niveau = 'débutant'
WHERE niveau = 'facile';
DELETE FROM Demineur
WHERE niveau = 'facile';
Une erreur, un oubli ? Écrivez-moi : frederic.peuriere@lfcl.pt
🔎 Exercices sur des thèmes similaires
-
Polynésie 2025 – jour 2 – exercice 2
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2024 – jour 1 – exercice 3
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 1 – exercice 3
programmation, POO, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2025 – jour 2 – exercice 3
POO, BDD, SQL, arbres binaires — Difficulté : 🔥🔥🔥🔥🔥 -
Nouvelle Calédonie 2025 – jour 1 – exercice 2
BDD, SQL , POO — Difficulté : 🔥🔥🔥🔥🔥 -
Amérique du Nord 2026 – jour 1 – exercice 3
récursivité, programmation dynamique, BDD, SQL — Difficulté : 🔥🔥🔥🔥🔥