Tutorial para crear un juego Tic-Tac-Toe con Python y Pygame paso a paso
¡Bienvenido a este tutorial para programadores principiantes! Hoy aprenderás a crear un clásico juego de Tic-Tac-Toe (Tres en Raya) usando Python y la biblioteca Pygame. Este proyecto es ideal para quienes quieren iniciarse en el desarrollo de juegos Python y entender conceptos esenciales como programación de eventos, lógica básica de juegos y diseño de interfaces gráficas.
Índice
- Introducción y requisitos
- Instalación y configuración del entorno
- Estructura del proyecto
- Diseñando la interfaz gráfica con Pygame
- Implementación de la lógica del juego
- Detección de ganadores y empates
- Manejo de eventos de teclado y ratón
- Conclusión y buenas prácticas
Introducción y requisitos
El Tic-Tac-Toe es un juego muy popular para dos jugadores en el que cada uno marca una casilla en un tablero de 3×3 intentando formar una línea horizontal, vertical o diagonal completa con sus símbolos (X o O). Nuestro objetivo será:
- Crear una ventana con Pygame
- Dibujar el tablero y las marcas
- Controlar turnos de los jugadores
- Detectar ganadores o empates
- Permitir reiniciar el juego
Requisitos
- Tener instalado Python 3.x
- Instalar la biblioteca Pygame
Este tutorial está dirigido a programadores principiantes, por lo que explicaremos cada paso con detalle.
Instalación y configuración del entorno
Paso 1: Instalar Python
Si aún no tienes Python, descárgalo desde https://python.org. Recomendamos la versión 3.6 o superior.
Para verificar que ya está instalado, abre una terminal y escribe:
1 2 |
python --version |
O si usas python3
:
1 2 |
python3 --version |
Paso 2: Instalar Pygame
Pygame es la librería que nos permitirá manejar gráficos y eventos fácilmente. Para instalarla, en la terminal escribe:
1 2 |
pip install pygame |
Si usas pip3
:
1 2 |
pip3 install pygame |
Paso 3: Verificar instalación
Para comprobar que Pygame funciona, abre una consola interactiva de Python (python
o python3
) e ingresa:
1 2 3 4 5 |
import pygame pygame.init() print("¡Pygame está listo para usar!") pygame.quit() |
Si no obtienes errores, estás listo para comenzar.
Estructura del proyecto
Vamos a crear un único archivo llamado tic_tac_toe.py
donde implementaremos todo el código. Esto es suficiente para un programa pequeño y facilita la comprensión.
La estructura básica será:
- Inicializar Pygame y crear la ventana
- Dibujar el tablero
- Manejar eventos del ratón y teclado
- Implementar la lógica del juego (turnos, ganador, empate)
- Permitir reiniciar el juego
Diseñando la interfaz gráfica con Pygame
Comencemos creando la ventana y dibujando el tablero de 3×3.
Crear la ventana y configurar colores
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
import pygame import sys # Inicializamos Pygame game = pygame.init() # Definimos dimensiones de la ventana WIDTH, HEIGHT = 600, 600 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Tic-Tac-Toe con Pygame") # Colores en RGB WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) BLUE = (0, 0, 255) # Velocidad de refresco delay = pygame.time.Clock() |
Dibujar las líneas del tablero
El tablero es una cuadrícula 3×3, usaremos líneas para dividirlo:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def draw_board(): WIN.fill(WHITE) # Fondo blanco # Grosor líneas line_thickness = 15 # Líneas verticales pygame.draw.line(WIN, BLACK, (WIDTH // 3, 0), (WIDTH // 3, HEIGHT), line_thickness) pygame.draw.line(WIN, BLACK, (2 * WIDTH // 3, 0), (2 * WIDTH // 3, HEIGHT), line_thickness) # Líneas horizontales pygame.draw.line(WIN, BLACK, (0, HEIGHT // 3), (WIDTH, HEIGHT // 3), line_thickness) pygame.draw.line(WIN, BLACK, (0, 2 * HEIGHT // 3), (WIDTH, 2 * HEIGHT // 3), line_thickness) pygame.display.update() |
Probar la ventana y el tablero
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
def main(): run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False draw_board() delay.tick(60) # 60 FPS pygame.quit() sys.exit() if __name__ == "__main__": main() |
Si ejecutas este script verás una ventana 600×600 con el tablero dividido.
Implementación de la lógica del juego
Representar el estado del tablero
Vamos a usar una lista de listas (matriz 3×3) para mantener el estado actual del juego. Cada casilla puede ser:
None
: vacía'X'
: jugador 1'O'
: jugador 2
1 2 3 4 |
board = [[None, None, None], [None, None, None], [None, None, None]] |
Dibujar las marcas (X y O) en el tablero
Para dibujar símbolos en la pantalla:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
def draw_marks(): font = pygame.font.SysFont(None, 150) for row in range(3): for col in range(3): mark = board[row][col] if mark is not None: color = RED if mark == 'X' else BLUE # Centramos el texto en la casilla text = font.render(mark, True, color) text_rect = text.get_rect(center=((col * WIDTH//3) + WIDTH//6, (row * HEIGHT//3) + HEIGHT//6)) WIN.blit(text, text_rect) pygame.display.update() |
Variables para el control del juego
Agregamos una variable para el jugador actual y para indicar si el juego terminó:
1 2 3 |
current_player = 'X' # X empieza winner = None |
Detección de ganadores y empates
Necesitamos verificar después de cada movimiento si alguien ganó o si hay empate.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
def check_winner(): global winner # Filas for row in board: if row[0] == row[1] == row[2] and row[0] is not None: winner = row[0] return True # Columnas for col in range(3): if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None: winner = board[0][col] return True # Diagonales if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None: winner = board[0][0] return True if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None: winner = board[0][2] return True # Empate (no hay movimientos vacíos) if all(all(cell is not None for cell in row) for row in board): winner = 'Empate' return True return False |
Manejo de eventos de teclado y ratón
Detectar clics para colocar marcas
Cuando el jugador hace clic en una casilla vacía, colocamos su marca.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
def get_clicked_cell(pos): x, y = pos row = y // (HEIGHT // 3) col = x // (WIDTH // 3) return row, col # Dentro del loop principal: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False elif event.type == pygame.MOUSEBUTTONDOWN and winner is None: pos = pygame.mouse.get_pos() row, col = get_clicked_cell(pos) if board[row][col] is None: board[row][col] = current_player if check_winner(): print(f"Ganador: {winner}") else: # Cambiar turno current_player = 'O' if current_player == 'X' else 'X' |
Reiniciar el juego con tecla
Agregamos la opción de reiniciar el juego presionando la tecla R.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
for event in pygame.event.get(): if event.type == pygame.QUIT: run = False elif event.type == pygame.MOUSEBUTTONDOWN and winner is None: # (manejo clic aquí) pass elif event.type == pygame.KEYDOWN: if event.key == pygame.K_r: global board, winner, current_player board = [[None]*3 for _ in range(3)] winner = None current_player = 'X' draw_board() draw_marks() |
Código completo optimizado
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
import pygame import sys pygame.init() WIDTH, HEIGHT = 600, 600 WIN = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("Tic-Tac-Toe con Pygame") WHITE = (255, 255, 255) BLACK = (0, 0, 0) RED = (255, 0, 0) BLUE = (0, 0, 255) line_thickness = 15 board = [[None]*3 for _ in range(3)] current_player = 'X' winner = None clock = pygame.time.Clock() def draw_board(): WIN.fill(WHITE) # Líneas verticales pygame.draw.line(WIN, BLACK, (WIDTH // 3, 0), (WIDTH // 3, HEIGHT), line_thickness) pygame.draw.line(WIN, BLACK, (2 * WIDTH // 3, 0), (2 * WIDTH // 3, HEIGHT), line_thickness) # Líneas horizontales pygame.draw.line(WIN, BLACK, (0, HEIGHT // 3), (WIDTH, HEIGHT // 3), line_thickness) pygame.draw.line(WIN, BLACK, (0, 2 * HEIGHT // 3), (WIDTH, 2 * HEIGHT // 3), line_thickness) def draw_marks(): font = pygame.font.SysFont(None, 150) for row in range(3): for col in range(3): mark = board[row][col] if mark is not None: color = RED if mark == 'X' else BLUE text = font.render(mark, True, color) text_rect = text.get_rect(center=((col * WIDTH//3) + WIDTH//6, (row * HEIGHT//3) + HEIGHT//6)) WIN.blit(text, text_rect) pygame.display.update() def check_winner(): global winner # Filas for row in board: if row[0] == row[1] == row[2] and row[0] is not None: winner = row[0] return True # Columnas for col in range(3): if board[0][col] == board[1][col] == board[2][col] and board[0][col] is not None: winner = board[0][col] return True # Diagonales if board[0][0] == board[1][1] == board[2][2] and board[0][0] is not None: winner = board[0][0] return True if board[0][2] == board[1][1] == board[2][0] and board[0][2] is not None: winner = board[0][2] return True # Empate if all(all(cell is not None for cell in row) for row in board): winner = 'Empate' return True return False def get_clicked_cell(pos): x, y = pos row = y // (HEIGHT // 3) col = x // (WIDTH // 3) return row, col def main(): global current_player, winner, board run = True while run: draw_board() draw_marks() for event in pygame.event.get(): if event.type == pygame.QUIT: run = False elif event.type == pygame.MOUSEBUTTONDOWN and winner is None: pos = pygame.mouse.get_pos() row, col = get_clicked_cell(pos) if board[row][col] is None: board[row][col] = current_player if check_winner(): print(f"Ganador: {winner}") else: current_player = 'O' if current_player == 'X' else 'X' elif event.type == pygame.KEYDOWN: if event.key == pygame.K_r: board = [[None]*3 for _ in range(3)] winner = None current_player = 'X' draw_board() draw_marks() print("Juego reiniciado") clock.tick(60) pygame.quit() sys.exit() if __name__ == "__main__": main() |
Conclusión y buenas prácticas
¡Felicidades! Ahora tienes un juego Tic-Tac-Toe completamente funcional usando Python y Pygame. Este proyecto te introduce a varias áreas fundamentales:
- Manejo de gráficos y ventanas con Pygame
- Uso de estructuras de datos para representar el estado del juego
- Lógica de control para alternar turnos y verificar ganadores
- Detección de eventos de ratón y teclado
Buenas prácticas para seguir explorando
- Añade mensajes en pantalla para indicar el turno o el ganador
- Mejora la interfaz con animaciones o sonidos
- Divide el código en funciones y archivos para mantener organización
- Experimenta con la opción de jugar contra la computadora
Llamado a la acción
Si te gustó este tutorial, ¡no olvides compartirlo! También puedes seguir aprendiendo sobre programación para principiantes y desarrollo de juegos con Python explorando documentación de Pygame y ejercicios prácticos.
Si tienes dudas o sugieres mejoras, deja un comentario y estaré encantado de ayudarte. ¡A programar y divertirse creando juegos!