Sudoku-Spielentwicklung mit Python und Pygame

PythonPythonIntermediate
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Projekt werden wir ein Sudoku-Spiel mit Python und der Pygame-Bibliothek erstellen. Das Spiel wird ein Sudoku-Gitter vom angegebenen Schwierigkeitsgrad generieren und den Spielern ermöglichen, das Rätsel zu lösen, indem sie die leeren Zellen mit Zahlen ausfüllen. Das Spiel wird Funktionen wie die Auswahl der Schwierigkeit, das Hervorheben ausgewählter Zellen und das Überprüfen, ob das Gitter vollständig ist, bieten.

👀 Vorschau

Sudoku-Spielvorschau

🎯 Aufgaben

In diesem Projekt lernen Sie:

  • Wie erforderliche Bibliotheken importiert werden
  • Wie PyGame initialisiert wird
  • Wie Farben definiert werden
  • Wie die Größe und der Titel des Spielfensters festgelegt werden
  • Wie das Spielfenster erstellt wird
  • Wie Schriftarten geladen werden
  • Wie ein Sudoku-Gitter generiert wird
  • Wie das Sudoku-Gitter mit dem Rückwärtsverfolgungsalgorithmus gelöst wird
  • Wie Zahlen aus dem Gitter aufgrund der Schwierigkeit entfernt werden
  • Wie das Sudoku-Gitter auf dem Spielfenster gezeichnet wird
  • Wie überprüft wird, ob das Gitter vollständig ausgefüllt ist
  • Wie die Zellenkoordinaten unter der Mausposition abgerufen werden
  • Wie der Schwierigkeitsgrad ausgewählt wird
  • Wie die Hauptspielschleife implementiert wird

🏆 Errungenschaften

Nach Abschluss dieses Projekts werden Sie in der Lage sein:

  • Die Pygame-Bibliothek für die Spieleentwicklung in Python zu verwenden
  • Ein Sudoku-Gitter vom angegebenen Schwierigkeitsgrad zu generieren
  • Ein Sudoku-Gitter mit dem Rückwärtsverfolgungsalgorithmus zu lösen
  • Maus- und Tastaturevents in Pygame zu behandeln
  • Formen und Text auf dem Spielfenster zu zeichnen
  • Die Hauptspielschleife in Pygame zu implementieren

Erstellen der Projekt-Dateien

Beginnen Sie mit dem Erstellen einer Datei namens sudoku_game.py und öffnen Sie sie in Ihrem bevorzugten Texteditor oder integrierten Entwicklungsumgebung (IDE).

cd ~/project
touch sudoku_game.py
✨ Lösung prüfen und üben

Importieren erforderlicher Bibliotheken

Importieren Sie die erforderlichen Bibliotheken am Anfang der Datei. Für dieses Spiel benötigen wir die pygame- und die random-Bibliothek.

import pygame
import random

Installieren Sie die pygame-Bibliothek mit dem pip-Befehl.

sudo pip install pygame
✨ Lösung prüfen und üben

Initialisiere PyGame

Initialisiere die Pygame-Bibliothek, um das Spielfenster einzurichten.

pygame.init()
✨ Lösung prüfen und üben

Definiere Farben

Definiere die Farben, die im Spiel verwendet werden sollen. Wir werden das RGB-Format für die Farben verwenden.

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (200, 200, 200)
BLUE = (0, 0, 255)
LIGHT_BLUE = (100, 100, 255)
✨ Lösung prüfen und üben

Setze die Dimensionen des Spielfensters und den Titel

Setze die Dimensionen des Spielfensters und gebe einen Titel für das Spiel fest.

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

pygame.display.set_caption("Sudoku Game")
✨ Lösung prüfen und üben

Erzeuge das Spielfenster

Erzeuge das Spielfenster mit den angegebenen Dimensionen.

screen = pygame.display.set_mode(WINDOW_SIZE)
✨ Lösung prüfen und üben

Lade Schriftarten

Wir müssen Schriftarten laden, um Zahlen auf dem Spielfenster anzuzeigen. Lade zwei Schriftarten, eine für die größeren Zahlen und eine für die kleineren Zahlen.

font_large = pygame.font.SysFont("calibri", 50)
font_small = pygame.font.SysFont("calibri", 30)
✨ Lösung prüfen und üben

Generiere das Sudoku-Gitter

Erstelle eine Funktion generate_sudoku(difficulty), die ein neues Sudoku-Gitter des angegebenen Schwierigkeitsgrades generiert. Die Funktion sollte das generierte Gitter zurückgeben.

def generate_sudoku(difficulty):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Fülle die diagonalen Teilgitter

Innerhalb der generate_sudoku-Funktion fülle die diagonalen Teilgitter des Gitters mit zufälligen Zahlen. Dadurch wird sichergestellt, dass jedes Teilgitter Zahlen von 1 bis 9 enthält, ohne Wiederholungen.

## Fülle die diagonalen Teilgitter
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]
✨ Lösung prüfen und üben

Löse das Sudoku-Gitter

Erstelle eine Funktion solve_sudoku(grid), die das Sudoku-Gitter mit dem Backtracking-Algorithmus löst. Die Funktion sollte True zurückgeben, wenn das Gitter lösbar ist, und False sonst.

def solve_sudoku(grid):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Finde eine leere Zelle

Innerhalb der solve_sudoku-Funktion erstelle eine Hilfsfunktion find_empty_cell(grid), die die Koordinaten der nächsten leeren Zelle im Gitter zurückgibt. Wenn es keine leeren Zellen gibt, gebe None zurück.

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
✨ Lösung prüfen und üben

Überprüfe einen gültigen Zug

Innerhalb der solve_sudoku-Funktion erstelle eine Hilfsfunktion is_valid_move(grid, row, col, num), die überprüft, ob das Setzen einer Zahl in einer Zelle ein gültiger Zug ist. Die Funktion sollte True zurückgeben, wenn der Zug gültig ist, und False sonst.

def is_valid_move(grid, row, col, num):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Löse das Sudoku-Gitter (Fortsetzung)

Innerhalb der solve_sudoku-Funktion verwende die Hilfsfunktionen find_empty_cell und is_valid_move, um den Backtracking-Algorithmus zu implementieren. Wenn eine Lösung gefunden wird, gebe True zurück. Wenn die aktuelle Zahl zu einer ungültigen Lösung führt, gehe zurück, indem du die aktuelle Zelle auf 0 setzt.

## Versuche, die leere Zelle mit Zahlen von 1 bis 9 zu füllen
for num in range(1, 10):
    if is_valid_move(grid, row, col, num):
        grid[row][col] = num

        if solve_sudoku(grid):
            return True

        ## Wenn die aktuelle Zahl zu einer ungültigen Lösung führt, gehe zurück
        grid[row][col] = 0

return False
✨ Lösung prüfen und üben

Entferne Zahlen basierend auf der Schwierigkeit

Innerhalb der generate_sudoku-Funktion entferne Zahlen aus dem Gitter basierend auf dem angegebenen Schwierigkeitsgrad. Die Schwierigkeitsgrade sind: 1 (leicht), 2 (mittel), 3 (schwer). Die Anzahl der zu entfernenden Zahlen wird berechnet als num_to_remove = 45 + 10 * difficulty.

## Entferne Zahlen basierend auf dem Schwierigkeitsgrad
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
✨ Lösung prüfen und üben

Zeichne Gitter

Erstelle eine Funktion draw_grid(grid, selected_cell), die das Sudoku-Gitter auf dem Spielfenster zeichnet. Diese Funktion sollte für das Zeichnen von Zellen, Zahlen und das Hervorheben der ausgewählten Zelle verantwortlich sein.

def draw_grid(grid, selected_cell):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Fülle Zellen und zeichne Zahlen

Innerhalb der draw_grid-Funktion gehe durch das Gitter und zeichne die Zellen und Zahlen mit den Pygame-Funktionen pygame.draw.rect und screen.blit.

## Zeichne die Zellen
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)

        ## Zeichne die Zahlen
        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)
✨ Lösung prüfen und üben

Hervorhebe ausgewählte Zelle

Innerhalb der draw_grid-Funktion, wenn die ausgewählte Zelle nicht None ist, verwende die pygame.draw.rect-Funktion, um die ausgewählte Zelle hervorzuheben.

## Hervorhebe die ausgewählte Zelle
if (row, col) == selected_cell:
    pygame.draw.rect(screen, LIGHT_BLUE, cell_rect, 3)
✨ Lösung prüfen und üben

Zeichne Gitterlinien

Innerhalb der draw_grid-Funktion, zeichne die Linien, um das Gitter zu erstellen, mit der pygame.draw.line-Funktion.

## Zeichne die Linien
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,
    )
✨ Lösung prüfen und üben

Aktualisiere die Anzeige

Innerhalb der draw_grid-Funktion, aktualisiere die Anzeige mit der pygame.display.update-Funktion.

pygame.display.update()
✨ Lösung prüfen und üben

Überprüfe, ob das Gitter voll ist

Erstelle eine Funktion is_grid_full(grid), die überprüft, ob das Sudoku-Gitter vollständig ausgefüllt ist. Dies kann durch das Durchlaufen des Gitters und das Überprüfen, ob eine Zelle 0 enthält, erreicht werden.

def is_grid_full(grid):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Hole die Zelle unter der Maus

Erstelle eine Funktion get_cell_under_mouse(pos), die die Koordinaten der Zelle unter der Mausposition zurückgibt. Dies kann berechnet werden, indem die Mausposition durch die Zellgröße geteilt wird.

def get_cell_under_mouse(pos):
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Wähle die Schwierigkeit

Erstelle eine Funktion select_difficulty(), die dem Spieler ermöglicht, das Schwierigkeitsniveau vor dem Start des Spiels auszuwählen. Diese Funktion sollte die Schwierigkeitsoptionen anzeigen und das ausgewählte Schwierigkeitsniveau zurückgeben.

def select_difficulty():
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Implementiere die Schwierigkeitsauswahl

Innerhalb der select_difficulty-Funktion, implementiere die Logik zur Schwierigkeitsauswahl mit den Pygame-Funktionen pygame.mouse.get_pos und pygame.event.get.

## Zeige den Text zur Schwierigkeitsauswahl an
title_text = font_large.render("Select Difficulty", True, BLACK)
screen.blit(title_text, (110, 200))

## Zeige die Schwierigkeitsoptionen an
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()

## Warte auf die Schwierigkeitsauswahl
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:  ## Linke Maustaste
                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
✨ Lösung prüfen und üben

Hauptspielschleife

Erstelle die Hauptspielschleife, indem du eine Funktion main() definierst.

def main():
    ## Function code goes here
    pass
✨ Lösung prüfen und üben

Wähle die Schwierigkeit und generiere das Gitter

Innerhalb der main-Funktion, wähle das Schwierigkeitsniveau, indem du select_difficulty() aufrufst und beende die Funktion, wenn die Schwierigkeit None ist. Dann generiere ein Sudoku-Gitter mit dem ausgewählten Schwierigkeitsniveau, indem du generate_sudoku(difficulty) aufrufst.

## Wähle das Schwierigkeitsniveau
difficulty = select_difficulty()
if difficulty is None:
    return

## Generiere ein neues Sudoku-Gitter
grid = generate_sudoku(difficulty)
✨ Lösung prüfen und üben

Spielschleifenvariablen

Innerhalb der main-Funktion, erstelle die Spielschleifenvariablen selected_cell und running. Setze selected_cell auf None und running auf True.

selected_cell = None
running = True
✨ Lösung prüfen und üben

Aktiviere die Tastendauerfortsetzung

Innerhalb der main-Funktion, aktiviere die Tastendauerfortsetzung mit der Funktion pygame.key.set_repeat. Wir setzen die Verzögerung und das Intervall auf 100 Millisekunden, um es Spielern einfacher zu machen, Zellen auszufüllen.

## Aktiviere die Tastendauerfortsetzung
pygame.key.set_repeat(100, 100)
✨ Lösung prüfen und üben

Behandle Ereignisse

Innerhalb der Spielschleife, behandle Ereignisse mit der Funktion pygame.event.get. Überprüfe auf Beenden-Ereignisse, Mausknopfe-Ereignisse und Tasteneingabe-Ereignisse.

for event in pygame.event.get():
    if event.type == pygame.QUIT:
        running = False
    elif event.type == pygame.MOUSEBUTTONDOWN:
        ## Behandle Mausknopfe-Ereignisse
        pass
    elif event.type == pygame.KEYDOWN:
        ## Behandle Tasteneingabe-Ereignisse
        pass
✨ Lösung prüfen und üben

Behandle Mausknopfe-Ereignisse

Innerhalb der Ereignisbehandlung für Mausknopfe-Ereignisse, überprüfe, ob die linke oder rechte Maustaste gedrückt wurde.

if event.button == 1:  ## Linke Maustaste
    ## Behandle das Klicken der linken Maustaste
    pass
elif event.button == 3:  ## Rechte Maustaste
    ## Behandle das Klicken der rechten Maustaste
    pass
✨ Lösung prüfen und üben

Behandle das Klicken der linken Maustaste

Innerhalb der Behandlung des Klicks auf die linke Maustaste, ermittle die Zellenkoordinaten unter der Mausposition, indem du get_cell_under_mouse(pos) aufrufst.

## Ermittle die Zelle unter der Mausposition
pos = pygame.mouse.get_pos()
row, col = get_cell_under_mouse(pos)
✨ Lösung prüfen und üben

Behandle das Klicken der linken Maustaste (Fortsetzung)

Innerhalb der Behandlung des Klicks auf die linke Maustaste, wähle die Zelle aus, wenn sie leer ist, indem du prüfst, ob grid[row][col] == 0.

## Wähle die Zelle aus, wenn sie leer ist
if grid[row][col] == 0:
    selected_cell = (row, col)
✨ Lösung prüfen und üben

Behandle das Klicken der rechten Maustaste

Innerhalb der Behandlung des Klicks auf die rechte Maustaste, lösche die ausgewählte Zelle, wenn sie nicht None ist und leer ist, indem du prüfst, ob grid[selected_cell[0]][selected_cell[1]] == 0.

if selected_cell:
    ## Lösche die ausgewählte Zelle, wenn sie leer ist
    if grid[selected_cell[0]][selected_cell[1]] == 0:
        grid[selected_cell[0]][selected_cell[1]] = 0
✨ Lösung prüfen und üben

Behandle Tasteneingaben

Innerhalb der Ereignisbehandlung für Tasteneingaben, überprüfe, welche Zifferntaste gedrückt wurde und setze den Wert der ausgewählten Zelle entsprechend.

if selected_cell:
    ## Ermittle die gedrückte Taste
    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
✨ Lösung prüfen und üben

Zeichne das Gitter und überprüfe die Vervollständigung

Innerhalb der Spielschleife, zeichne das Gitter, indem du draw_grid(grid, selected_cell) aufrufst. Dann überprüfe, ob das Gitter vollständig ist, indem du is_grid_full(grid) aufrufst.

## Zeichne das Gitter
draw_grid(grid, selected_cell)

## Überprüfe, ob das Gitter vollständig ist
if is_grid_full(grid):
    print("Glückwunsch! Du hast das Sudoku-Puzzle gelöst.")
✨ Lösung prüfen und üben

Aktualisiere die Anzeige und beende das Spiel

Nach der Spielschleife aktualisiere die Anzeige mit der Funktion pygame.display.update und beende das Spiel mit pygame.quit().

## Aktualisiere die Anzeige
pygame.display.update()

## Beende das Spiel
pygame.quit()
✨ Lösung prüfen und üben

Starte das Spiel

Schließlich füge eine Bedingung hinzu, um zu überprüfen, ob die aktuelle Datei der Haupteinstiegspunkt des Programms ist. Wenn ja, starte das Spiel, indem du die Funktion main() aufrufst.

if __name__ == "__main__":
    main()

Starte das Spiel mit dem Befehl python.

python sudoku_game.py
Screenshot der Ausführung des Sudoku-Spiels
✨ Lösung prüfen und üben

Zusammenfassung

Glückwunsch! Du hast erfolgreich ein Sudoku-Spiel mit Python und der Pygame-Bibliothek erstellt. Das Spiel ermöglicht es Spielern, ein Schwierigkeitslevel auszuwählen, leere Zellen mit Zahlen zu füllen und zu überprüfen, ob das Gitter vollständig ist. Viel Spaß beim Spielen und Lösen von Sudoku-Puzzles!