Ein TicTacToe Spiel mit Claude programmieren

Prolog

Ich habe mit Hilfe von Claude.AI ein TikTakToe Spiel programmiert. Nach etwa 15 Minuten und ein paar Iterationen war das Spiel soweit. Dann habe ich Claude gebeten, den Prozess der Entwicklung zusammenzufassen und den Code ganz unten mit einzubauen. Dies ist das Ergebnis.

Entwicklung eines Tic-Tac-Toe-Spiels mit Pygame

In diesem Blogbeitrag möchte ich den Prozess der Entwicklung eines Tic-Tac-Toe-Spiels mit Python und Pygame teilen. Wir haben das Spiel Schritt für Schritt aufgebaut und dabei verschiedene Funktionen hinzugefügt.

Erste Version: Grundlegendes Spiel

Wir begannen mit der Erstellung eines einfachen Tic-Tac-Toe-Spiels, das folgende Funktionen hatte:

  • Ein 3x3 Spielfeld
  • Abwechselnde Züge für zwei Spieler (X und O)
  • Erkennung von Gewinnern und Unentschieden
  • Eine grafische Benutzeroberfläche mit Pygame
  • Ein karierter Papierhintergrund für das Spielfeld

Verbesserung: Spielmodus-Auswahl und Computer-Gegner

Als nächstes fügten wir die Möglichkeit hinzu, zwischen zwei Spielmodi zu wählen:

  1. Spieler gegen Spieler
  2. Spieler gegen Computer

Wir implementierten auch einen einfachen Computer-Gegner, der zufällige Züge machte.

UI-Verbesserungen

Wir nahmen einige UI-Verbesserungen vor:

  • Hinzufügen eines “Neustart”-Knopfs am Ende des Spiels
  • Anpassung des Layouts, um den Gewinner-Text und den Neustart-Knopf nebeneinander anzuzeigen

Verbesserter Computer-Gegner

Schließlich haben wir den Computer-Gegner verbessert, indem wir eine Strategie implementiert haben:

  1. Versuche zu gewinnen, wenn möglich
  2. Blockiere den Spieler vom Gewinnen, wenn nötig
  3. Besetze eine freie Ecke, wenn verfügbar
  4. Besetze das Zentrum, wenn frei
  5. Besetze eine freie Kante

Diese Strategie macht den Computer-Gegner zu einem herausfordernderen Gegner, der nicht leicht zu schlagen ist.

Fazit

Die Entwicklung dieses Tic-Tac-Toe-Spiels war ein interessanter Prozess, bei dem wir schrittweise Funktionen hinzugefügt und das Spiel verbessert haben. Von einem einfachen Zwei-Spieler-Spiel haben wir es zu einem Spiel mit Computergegner und verbesserter KI entwickelt.

Der vollständige Code für das finale Spiel ist unten zu finden. Viel Spaß beim Spielen und eventuellen Weiterentwickeln!


Vollständiger Code

import pygame
import sys
import random

# Initialisierung von Pygame
pygame.init()

# Bildschirmgröße
WIDTH, HEIGHT = 600, 650

# Farben
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)
GRID_COLOR = (200, 200, 200)
BUTTON_COLOR = (100, 200, 100)
BUTTON_HOVER_COLOR = (150, 250, 150)

# Spielfeld
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Tic Tac Toe")

# Schriftarten
font = pygame.font.Font(None, 36)
large_font = pygame.font.Font(None, 48)

# Spielmodus
PLAYER_VS_PLAYER = "player_vs_player"
PLAYER_VS_COMPUTER = "player_vs_computer"
game_mode = None

def init_game():
    global board, current_player, game_over, winner
    board = [['' for _ in range(3)] for _ in range(3)]
    current_player = 'X'
    game_over = False
    winner = None

def draw_grid():
    for x in range(0, WIDTH, 20):
        pygame.draw.line(screen, GRID_COLOR, (x, 0), (x, HEIGHT - 70))
    for y in range(0, HEIGHT - 70, 20):
        pygame.draw.line(screen, GRID_COLOR, (0, y), (WIDTH, y))
    
    for i in range(1, 3):
        pygame.draw.line(screen, BLACK, (i * WIDTH // 3, 0), (i * WIDTH // 3, HEIGHT - 70), 2)
        pygame.draw.line(screen, BLACK, (0, i * (HEIGHT - 70) // 3), (WIDTH, i * (HEIGHT - 70) // 3), 2)

def draw_xo():
    for row in range(3):
        for col in range(3):
            if board[row][col] == 'X':
                x = col * WIDTH // 3 + WIDTH // 6
                y = row * (HEIGHT - 70) // 3 + (HEIGHT - 70) // 6
                pygame.draw.line(screen, RED, (x - 50, y - 50), (x + 50, y + 50), 4)
                pygame.draw.line(screen, RED, (x + 50, y - 50), (x - 50, y + 50), 4)
            elif board[row][col] == 'O':
                x = col * WIDTH // 3 + WIDTH // 6
                y = row * (HEIGHT - 70) // 3 + (HEIGHT - 70) // 6
                pygame.draw.circle(screen, BLUE, (x, y), 50, 4)

def check_winner():
    for i in range(3):
        if board[i][0] == board[i][1] == board[i][2] != '':
            return board[i][0]
        if board[0][i] == board[1][i] == board[2][i] != '':
            return board[0][i]
    
    if board[0][0] == board[1][1] == board[2][2] != '':
        return board[0][0]
    if board[0][2] == board[1][1] == board[2][0] != '':
        return board[0][2]
    
    return None

def is_board_full():
    return all(all(cell != '' for cell in row) for row in board)

def draw_button(rect, text):
    button_color = BUTTON_HOVER_COLOR if rect.collidepoint(pygame.mouse.get_pos()) else BUTTON_COLOR
    pygame.draw.rect(screen, button_color, rect)
    button_text = font.render(text, True, BLACK)
    text_rect = button_text.get_rect(center=rect.center)
    screen.blit(button_text, text_rect)

def get_empty_cells():
    return [(row, col) for row in range(3) for col in range(3) if board[row][col] == '']

def check_win_move(player):
    for row, col in get_empty_cells():
        board[row][col] = player
        if check_winner() == player:
            board[row][col] = ''
            return row, col
        board[row][col] = ''
    return None

def get_corner_move():
    corners = [(0, 0), (0, 2), (2, 0), (2, 2)]
    empty_corners = [corner for corner in corners if board[corner[0]][corner[1]] == '']
    return random.choice(empty_corners) if empty_corners else None

def get_center_move():
    return (1, 1) if board[1][1] == '' else None

def get_edge_move():
    edges = [(0, 1), (1, 0), (1, 2), (2, 1)]
    empty_edges = [edge for edge in edges if board[edge[0]][edge[1]] == '']
    return random.choice(empty_edges) if empty_edges else None

def computer_move():
    # Versuche zu gewinnen
    win_move = check_win_move('O')
    if win_move:
        return win_move

    # Blockiere den Spieler vom Gewinnen
    block_move = check_win_move('X')
    if block_move:
        return block_move

    # Versuche eine Ecke zu besetzen
    corner_move = get_corner_move()
    if corner_move:
        return corner_move

    # Versuche das Zentrum zu besetzen
    center_move = get_center_move()
    if center_move:
        return center_move

    # Besetze eine Kante
    edge_move = get_edge_move()
    if edge_move:
        return edge_move

    # Sollte nie erreicht werden, da alle möglichen Züge abgedeckt sind
    return random.choice(get_empty_cells())

def draw_start_screen():
    screen.fill(WHITE)
    title = large_font.render("Tic Tac Toe", True, BLACK)
    screen.blit(title, (WIDTH // 2 - title.get_width() // 2, 100))

    pvp_rect = pygame.Rect(WIDTH // 2 - 150, 250, 300, 60)
    pvc_rect = pygame.Rect(WIDTH // 2 - 150, 350, 300, 60)

    draw_button(pvp_rect, "Spieler vs. Spieler")
    draw_button(pvc_rect, "Spieler vs. Computer")

    return pvp_rect, pvc_rect

# Hauptspielschleife
running = True
init_game()

while running:
    if game_mode is None:
        pvp_rect, pvc_rect = draw_start_screen()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if pvp_rect.collidepoint(event.pos):
                    game_mode = PLAYER_VS_PLAYER
                elif pvc_rect.collidepoint(event.pos):
                    game_mode = PLAYER_VS_COMPUTER
    else:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.MOUSEBUTTONDOWN and not game_over:
                x, y = event.pos
                if y < HEIGHT - 70:
                    col = x // (WIDTH // 3)
                    row = y // ((HEIGHT - 70) // 3)
                    
                    if board[row][col] == '':
                        board[row][col] = current_player
                        winner = check_winner()
                        if winner:
                            game_over = True
                        elif is_board_full():
                            game_over = True
                        else:
                            current_player = 'O' if current_player == 'X' else 'X'
                            if game_mode == PLAYER_VS_COMPUTER and current_player == 'O':
                                row, col = computer_move()
                                board[row][col] = 'O'
                                winner = check_winner()
                                if winner:
                                    game_over = True
                                elif is_board_full():
                                    game_over = True
                                else:
                                    current_player = 'X'
        
        screen.fill(WHITE)
        draw_grid()
        draw_xo()
        
        if game_over:
            if winner:
                text = font.render(f"Spieler {winner} gewinnt!", True, BLACK)
            else:
                text = font.render("Unentschieden!", True, BLACK)
            text_rect = text.get_rect(left=10, centery=HEIGHT - 35)
            screen.blit(text, text_rect)

            restart_rect = pygame.Rect(WIDTH - 210, HEIGHT - 60, 200, 50)
            draw_button(restart_rect, "Neu starten")

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if restart_rect.collidepoint(event.pos):
                        init_game()
                        game_mode = None

    pygame.display.flip()

pygame.quit()
sys.exit()