Développement d'un jeu de Sudoku avec Python et Pygame

PythonPythonBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Dans ce projet, nous allons créer un jeu de Sudoku en utilisant Python et la bibliothèque Pygame. Le jeu générera une grille de Sudoku du niveau de difficulté spécifié et permettra aux joueurs de résoudre le puzzle en remplissant les cases vides avec des chiffres. Le jeu offrira des fonctionnalités telles que la sélection de la difficulté, la mise en évidence des cases sélectionnées et la vérification si la grille est complète.

👀 Aperçu

Aperçu du jeu de Sudoku

🎯 Tâches

Dans ce projet, vous allez apprendre :

  • Comment importer les bibliothèques requises
  • Comment initialiser PyGame
  • Comment définir des couleurs
  • Comment définir les dimensions et le titre de la fenêtre de jeu
  • Comment créer la fenêtre de jeu
  • Comment charger des polices
  • Comment générer une grille de Sudoku
  • Comment résoudre une grille de Sudoku en utilisant l'algorithme de backtracking
  • Comment supprimer des chiffres de la grille en fonction de la difficulté
  • Comment dessiner la grille de Sudoku sur la fenêtre de jeu
  • Comment vérifier si la grille est complètement remplie
  • Comment obtenir les coordonnées de la case sous la position de la souris
  • Comment sélectionner le niveau de difficulté
  • Comment implémenter la boucle principale du jeu

🏆 Réalisations

Après avoir terminé ce projet, vous serez capable de :

  • Utiliser la bibliothèque Pygame pour le développement de jeux en Python
  • Générer une grille de Sudoku d'un niveau de difficulté spécifié
  • Résoudre une grille de Sudoku en utilisant l'algorithme de backtracking
  • Gérer les événements de souris et de clavier dans Pygame
  • Dessiner des formes et du texte sur la fenêtre de jeu
  • Implémenter la boucle principale du jeu dans Pygame

Créer les fichiers du projet

Pour commencer, créez un fichier nommé sudoku_game.py et ouvrez-le dans votre éditeur de texte ou environnement de développement intégré (IDE) préféré.

cd ~/projet
touch sudoku_game.py
✨ Vérifier la solution et pratiquer

Importer les bibliothèques requises

Importez les bibliothèques requises au début du fichier. Nous avons besoin des bibliothèques pygame et random pour ce jeu.

import pygame
import random

Installez la bibliothèque pygame à l'aide de la commande pip.

sudo pip install pygame
✨ Vérifier la solution et pratiquer

Initialiser PyGame

Initialisez la bibliothèque PyGame pour configurer la fenêtre de jeu.

pygame.init()
✨ Vérifier la solution et pratiquer

Définir les couleurs

Définissez les couleurs à utiliser dans le jeu. Nous utiliserons le format RGB pour les couleurs.

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (200, 200, 200)
BLUE = (0, 0, 255)
LIGHT_BLUE = (100, 100, 255)
✨ Vérifier la solution et pratiquer

Définir les dimensions et le titre de la fenêtre de jeu

Définissez les dimensions de la fenêtre de jeu et donnez un titre au jeu.

WINDOW_SIZE = (550, 550)
CELL_SIZE = WINDOW_SIZE[0] // 9

pygame.display.set_caption("Sudoku Game")
✨ Vérifier la solution et pratiquer

Créer la fenêtre de jeu

Créez la fenêtre de jeu avec les dimensions spécifiées.

screen = pygame.display.set_mode(WINDOW_SIZE)
✨ Vérifier la solution et pratiquer

Charger des polices

Nous devrons charger des polices pour afficher les chiffres sur l'écran du jeu. Chargez deux polices, l'une pour les chiffres plus grands et l'autre pour les chiffres plus petits.

font_large = pygame.font.SysFont("calibri", 50)
font_small = pygame.font.SysFont("calibri", 30)
✨ Vérifier la solution et pratiquer

Générer une grille de Sudoku

Créez une fonction generate_sudoku(difficulty) qui génère une nouvelle grille de Sudoku au niveau de difficulté spécifié. La fonction devrait renvoyer la grille générée.

def generate_sudoku(difficulty):
    ## Function code goes here
    pass
✨ Vérifier la solution et pratiquer

Remplir les sous-grilles diagonales

Dans la fonction generate_sudoku, remplissez les sous-grilles diagonales de la grille avec des nombres aléatoires. Cela garantit que chaque sous-grille contient les nombres de 1 à 9 sans répétition.

## Fill diagonal subgrids
for i in range(0, 9, 3):
    nums = random.sample(range(1, 10), 3)
    for j in range(3):
        grid[i + j][i + j] = nums[j]
✨ Vérifier la solution et pratiquer

Résoudre une grille de Sudoku

Créez une fonction solve_sudoku(grid) qui résout la grille de Sudoku en utilisant l'algorithme de retour en arrière. La fonction devrait renvoyer True si la grille est résoluble et False sinon.

def solve_sudoku(grid):
    ## Function code goes here
    pass
✨ Vérifier la solution et pratiquer

Trouver une cellule vide

Dans la fonction solve_sudoku, créez une fonction auxiliaire find_empty_cell(grid) qui renvoie les coordonnées de la prochaine cellule vide dans la grille. Si il n'y a pas de cellules vides, renvoyez None.

def find_empty_cell(grid):
    for row in range(9):
        for col in range(9):
            if grid[row][col] == 0:
                return (row, col)

    return None
✨ Vérifier la solution et pratiquer

Vérifier si un mouvement est valide

Dans la fonction solve_sudoku, créez une fonction auxiliaire is_valid_move(grid, row, col, num) qui vérifie si placer un nombre dans une cellule est un mouvement valide. La fonction devrait renvoyer True si le mouvement est valide et False sinon.

def is_valid_move(grid, row, col, num):
    ## Function code goes here
    pass
✨ Vérifier la solution et pratiquer

Résoudre une grille de Sudoku (suite)

Dans la fonction solve_sudoku, utilisez les fonctions auxiliaires find_empty_cell et is_valid_move pour implémenter l'algorithme de retour en arrière. Si une solution est trouvée, renvoyez True. Si le nombre actuel conduit à une solution invalide, revenez en arrière en mettant la cellule actuelle à 0.

## Essayez de remplir la cellule vide avec les nombres de 1 à 9
for num in range(1, 10):
    if is_valid_move(grid, row, col, num):
        grid[row][col] = num

        if solve_sudoku(grid):
            return True

        ## Si le nombre actuel conduit à une solution invalide, revenez en arrière
        grid[row][col] = 0

return False
✨ Vérifier la solution et pratiquer

Supprimer des nombres en fonction de la difficulté

Dans la fonction generate_sudoku, supprimez des nombres de la grille en fonction du niveau de difficulté spécifié. Les niveaux de difficulté sont : 1 (facile), 2 (moyen), 3 (difficile). Le nombre de nombres à supprimer est calculé comme suit : num_to_remove = 45 + 10 * difficulty.

## Supprimez des nombres en fonction du niveau de difficulté
num_to_remove = 45 + 10 * difficulty
for _ in range(num_to_remove):
    row = random.randint(0, 8)
    col = random.randint(0, 8)
    grid[row][col] = 0

return grid
✨ Vérifier la solution et pratiquer

Dessiner la grille

Créez une fonction draw_grid(grid, selected_cell) qui dessine la grille de Sudoku sur la fenêtre de jeu. Cette fonction devrait être responsable du dessin des cellules, des nombres et de la mise en évidence de la cellule sélectionnée.

def draw_grid(grid, selected_cell):
    ## Function code goes here
    pass
✨ Vérifier la solution et pratiquer

Remplir les cellules et dessiner les nombres

Dans la fonction draw_grid, parcourez la grille et dessinez les cellules et les nombres à l'aide des fonctions Pygame pygame.draw.rect et screen.blit.

## Dessinez les cellules
for row in range(9):
    for col in range(9):
        cell_rect = pygame.Rect(
            col * CELL_SIZE, row * CELL_SIZE, CELL_SIZE, CELL_SIZE
        )
        pygame.draw.rect(screen, GRAY, cell_rect)

        ## Dessinez les nombres
        if grid[row][col]!= 0:
            number = font_small.render(str(grid[row][col]), True, BLACK)
            text_rect = number.get_rect(
                center=(
                    col * CELL_SIZE + CELL_SIZE // 2,
                    row * CELL_SIZE + CELL_SIZE // 2,
                )
            )
            screen.blit(number, text_rect)
✨ Vérifier la solution et pratiquer

Mettre en évidence la cellule sélectionnée

Dans la fonction draw_grid, mettez en évidence la cellule sélectionnée si elle n'est pas None à l'aide de la fonction pygame.draw.rect.

## Mettez en évidence la cellule sélectionnée
if (row, col) == selected_cell:
    pygame.draw.rect(screen, LIGHT_BLUE, cell_rect, 3)
✨ Vérifier la solution et pratiquer

Dessiner les lignes de la grille

Dans la fonction draw_grid, dessinez les lignes pour créer la grille à l'aide de la fonction pygame.draw.line.

## Dessinez les lignes
for i in range(10):
    if i % 3 == 0:
        thickness = 4
    else:
        thickness = 1

    pygame.draw.line(
        screen,
        BLACK,
        (0, i * CELL_SIZE),
        (WINDOW_SIZE[0], i * CELL_SIZE),
        thickness,
    )
    pygame.draw.line(
        screen,
        BLACK,
        (i * CELL_SIZE, 0),
        (i * CELL_SIZE, WINDOW_SIZE[1]),
        thickness,
    )
✨ Vérifier la solution et pratiquer

Mettre à jour l'affichage

Dans la fonction draw_grid, mettez à jour l'affichage à l'aide de la fonction pygame.display.update.

pygame.display.update()
✨ Vérifier la solution et pratiquer

Vérifier si la grille est complète

Créez une fonction is_grid_full(grid) qui vérifie si la grille de Sudoku est complètement remplie. Cela peut être fait en parcourant la grille et en vérifiant si une cellule quelconque contient 0.

def is_grid_full(grid):
    ## Le code de la fonction va ici
    pass
✨ Vérifier la solution et pratiquer

Obtenir la cellule sous la souris

Créez une fonction get_cell_under_mouse(pos) qui renvoie les coordonnées de la cellule sous la position de la souris. Cela peut être calculé en divisant la position de la souris par la taille de la cellule.

def get_cell_under_mouse(pos):
    ## Le code de la fonction va ici
    pass
✨ Vérifier la solution et pratiquer

Sélectionner la difficulté

Créez une fonction select_difficulty() qui permet au joueur de sélectionner le niveau de difficulté avant de commencer le jeu. Cette fonction devrait afficher les options de difficulté et renvoyer le niveau de difficulté sélectionné.

def select_difficulty():
    ## Le code de la fonction va ici
    pass
✨ Vérifier la solution et pratiquer

Implémenter la sélection de difficulté

Dans la fonction select_difficulty, implémentez la logique de sélection de difficulté à l'aide des fonctions Pygame pygame.mouse.get_pos et pygame.event.get.

## Afficher le texte de sélection de difficulté
title_text = font_large.render("Select Difficulty", True, BLACK)
screen.blit(title_text, (110, 200))

## Afficher les options de difficulté
option_y = 300
for difficulty, label in difficulties.items():
    option_text = font_small.render(f"{difficulty}. {label}", True, BLACK)
    text_rect = option_text.get_rect(center=(WINDOW_SIZE[0] // 2, option_y))
    screen.blit(option_text, text_rect)
    option_y += 70

pygame.display.update()

## Attendre la sélection de difficulté
difficulty_selected = False
difficulty = 1

while not difficulty_selected:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            return
        elif event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  ## Bouton gauche de la souris
                pos = pygame.mouse.get_pos()
                if 180 <= pos[0] <= 380:
                    if 300 <= pos[1] <= 350:
                        difficulty = 1
                        difficulty_selected = True
                    elif 370 <= pos[1] <= 420:
                        difficulty = 2
                        difficulty_selected = True
                    elif 440 <= pos[1] <= 490:
                        difficulty = 3
                        difficulty_selected = True

return difficulty
✨ Vérifier la solution et pratiquer

Boucle principale du jeu

Créez la boucle principale du jeu en définissant une fonction main().

def main():
    ## Le code de la fonction va ici
    pass
✨ Vérifier la solution et pratiquer

Sélectionner la difficulté et générer la grille

Dans la fonction main, sélectionnez le niveau de difficulté en appelant select_difficulty() et retournez si la difficulté est None. Ensuite, générez une grille de Sudoku en utilisant le niveau de difficulté sélectionné en appelant generate_sudoku(difficulty).

## Sélectionnez le niveau de difficulté
difficulty = select_difficulty()
if difficulty is None:
    return

## Générez une nouvelle grille de Sudoku
grid = generate_sudoku(difficulty)
✨ Vérifier la solution et pratiquer

Variables de la boucle de jeu

Dans la fonction main, créez les variables de boucle de jeu selected_cell et running. Affectez selected_cell à None et running à True.

selected_cell = None
running = True
✨ Vérifier la solution et pratiquer

Activer la répétition de touches

Dans la fonction main, activez la répétition de touches à l'aide de la fonction pygame.key.set_repeat. Nous définissons le délai et l'intervalle sur 100 millisecondes pour faciliter la saisie des cases par les joueurs.

## Activer la répétition de touches
pygame.key.set_repeat(100, 100)
✨ Vérifier la solution et pratiquer

Gérer les événements

Dans la boucle de jeu, gérer les événements à l'aide de la fonction pygame.event.get. Vérifiez les événements de fermeture, d'événements de bouton de souris et d'événements de touches.

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    elif event.type == pygame.MOUSEBUTTONDOWN:
        ## Gérer les événements de bouton de souris
        pass
    elif event.type == pygame.KEYDOWN:
        ## Gérer les événements de touches
        pass
✨ Vérifier la solution et pratiquer

Gérer les événements de bouton de souris

Dans la gestion des événements de bouton de souris, vérifiez si le bouton gauche de la souris est cliqué ou si le bouton droit de la souris est cliqué.

if event.button == 1:  ## Bouton gauche de la souris
    ## Gérer le clic du bouton gauche de la souris
    pass
elif event.button == 3:  ## Bouton droit de la souris
    ## Gérer le clic du bouton droit de la souris
    pass
✨ Vérifier la solution et pratiquer

Gérer le clic du bouton gauche de la souris

Dans la gestion du clic du bouton gauche de la souris, obtenez les coordonnées de la cellule sous la position de la souris en appelant get_cell_under_mouse(pos).

## Obtenez la cellule sous la position de la souris
pos = pygame.mouse.get_pos()
row, col = get_cell_under_mouse(pos)
✨ Vérifier la solution et pratiquer

Gérer le clic du bouton gauche de la souris (suite)

Dans la gestion du clic du bouton gauche de la souris, sélectionnez la cellule si elle est vide en vérifiant si grid[row][col] == 0.

## Sélectionnez la cellule si elle est vide
if grid[row][col] == 0:
    selected_cell = (row, col)
✨ Vérifier la solution et pratiquer

Gérer le clic du bouton droit de la souris

Dans la gestion du clic du bouton droit de la souris, effacez la cellule sélectionnée si elle n'est pas None et si elle est vide en vérifiant si grid[selected_cell[0]][selected_cell[1]] == 0.

if selected_cell:
    ## Effacez la cellule sélectionnée si elle est vide
    if grid[selected_cell[0]][selected_cell[1]] == 0:
        grid[selected_cell[0]][selected_cell[1]] = 0
✨ Vérifier la solution et pratiquer

Gérer les événements de touches

Dans la gestion des événements de touches, vérifiez quelle touche numérique est pressée et définissez la valeur de la cellule sélectionnée en conséquence.

if selected_cell:
    ## Obtenez la touche pressée
    if event.key == pygame.K_1:
        grid[selected_cell[0]][selected_cell[1]] = 1
    elif event.key == pygame.K_2:
        grid[selected_cell[0]][selected_cell[1]] = 2
    elif event.key == pygame.K_3:
        grid[selected_cell[0]][selected_cell[1]] = 3
    elif event.key == pygame.K_4:
        grid[selected_cell[0]][selected_cell[1]] = 4
    elif event.key == pygame.K_5:
        grid[selected_cell[0]][selected_cell[1]] = 5
    elif event.key == pygame.K_6:
        grid[selected_cell[0]][selected_cell[1]] = 6
    elif event.key == pygame.K_7:
        grid[selected_cell[0]][selected_cell[1]] = 7
    elif event.key == pygame.K_8:
        grid[selected_cell[0]][selected_cell[1]] = 8
    elif event.key == pygame.K_9:
        grid[selected_cell[0]][selected_cell[1]] = 9
✨ Vérifier la solution et pratiquer

Dessiner la grille et vérifier la complétion

Dans la boucle de jeu, dessinez la grille en appelant draw_grid(grid, selected_cell). Ensuite, vérifiez si la grille est complète en appelant is_grid_full(grid).

## Dessinez la grille
draw_grid(grid, selected_cell)

## Vérifiez si la grille est complète
if is_grid_full(grid):
    print("Congratulations! You solved the Sudoku puzzle.")
✨ Vérifier la solution et pratiquer

Mettre à jour l'affichage et quitter

Après la boucle de jeu, mettez à jour l'affichage en utilisant la fonction pygame.display.update et quittez le jeu en utilisant pygame.quit().

## Mettez à jour l'affichage
pygame.display.update()

## Quittez le jeu
pygame.quit()
✨ Vérifier la solution et pratiquer

Exécuter le jeu

Enfin, ajoutez une condition pour vérifier si le fichier actuel est le point d'entrée principal du programme. Si c'est le cas, exécutez le jeu en appelant la fonction main().

if __name__ == "__main__":
    main()

Exécutez le jeu en utilisant la commande python.

python sudoku_game.py
Capture d'écran d'exécution du jeu Sudoku
✨ Vérifier la solution et pratiquer

Sommaire

Félicitations ! Vous avez réussi à créer un jeu de Sudoku en utilisant Python et la bibliothèque Pygame. Le jeu permet aux joueurs de sélectionner un niveau de difficulté, de remplir les cases vides avec des chiffres et de vérifier si la grille est complète. Amusez-vous bien à jouer et à résoudre des puzzles de Sudoku !