Pacman en Python con curses

Versión Python del clásico Pacman en modo texto, usando el módulo curses de la biblioteca estándar para gestionar el terminal. Funciona en Linux y macOS sin dependencias adicionales; en Windows basta con instalar windows-curses. Mueve a Pacman con las flechas del teclado y come todos los puntos antes de que te alcancen los monstruos.
				"""
pacman.py — Juego tipo Pacman en modo texto

Versión Python del clásico Pacman en C (2003) de Dorian Butrón y Dr. Gustavo Calderón.
Usa el módulo curses de la biblioteca estándar para gestionar el terminal.

Autor: David Carrero Fernandez-Baillo
Web:   https://carrero.es

Requisitos: Python 3.8+, módulo curses (incluido en la biblioteca estándar)
  - Linux/macOS: sin dependencias adicionales
  - Windows:     pip install windows-curses
Ejecutar: python pacman.py

Versión C:   https://programacion.net/codigo/pacman_64
Versión PHP: https://programacion.net/codigo/pacman-php_1893
"""

import curses
import random
import time

FILAS   = 10
COLS    = 20
RETARDO = 0.12   # segundos entre fotogramas


def generar_tablero() -> list[list]:
    return [['.' for _ in range(COLS)] for _ in range(FILAS)]


def tablero_vacio(tablero: list[list]) -> bool:
    return not any(c == '.' for fila in tablero for c in fila)


def dibujar(ventana, tablero: list[list], puntos: int) -> None:
    ventana.clear()
    ventana.addstr(0, 0,
                   f"Flechas=mover  ESC=salir  Puntos: {puntos * 15}",
                   curses.color_pair(3) | curses.A_BOLD)

    for i, fila in enumerate(tablero):
        for j, celda in enumerate(fila):
            y, x = i + 1, j * 2
            if celda == '@':
                ventana.addch(y, x, '@', curses.color_pair(1) | curses.A_BOLD)
            elif celda in (1, 2):
                ventana.addch(y, x, 'M', curses.color_pair(2) | curses.A_BOLD)
            elif celda == 'X':
                ventana.addch(y, x, 'X', curses.color_pair(2) | curses.A_BOLD)
            else:
                ventana.addch(y, x, str(celda) if isinstance(celda, str) else '.')
    ventana.refresh()


def mover_monstruo(pos: int, limite: int) -> int:
    delta = 1 if random.randint(0, 1) else -1
    return max(0, min(limite - 1, pos + delta))


def jugar(ventana) -> None:
    # Configurar curses
    curses.curs_set(0)
    ventana.nodelay(True)
    curses.start_color()
    curses.init_pair(1, curses.COLOR_YELLOW, curses.COLOR_BLACK)  # pacman
    curses.init_pair(2, curses.COLOR_RED,    curses.COLOR_BLACK)  # monstruo / muerte
    curses.init_pair(3, curses.COLOR_GREEN,  curses.COLOR_BLACK)  # HUD

    tablero = generar_tablero()
    py, px  = 0, 0
    m1y, m1x = 0, COLS - 1
    m2y, m2x = FILAS - 1, COLS - 1
    puntos  = 0

    tablero[py][px]   = '@'
    tablero[m1y][m1x] = 1
    tablero[m2y][m2x] = 2

    while True:
        dibujar(ventana, tablero, puntos)
        time.sleep(RETARDO)

        # Retirar monstruos del tablero para calcular movimiento
        tablero[m1y][m1x] = ' '
        tablero[m2y][m2x] = ' '

        if tablero_vacio(tablero):
            ventana.nodelay(False)
            ventana.addstr(FILAS // 2, 2,
                           f"¡Ganaste! Puntos: {puntos * 15}",
                           curses.color_pair(3) | curses.A_BOLD)
            ventana.refresh()
            ventana.getch()
            return

        # Leer tecla
        tecla = ventana.getch()
        if tecla != curses.ERR:
            tablero[py][px] = ' '
            if   tecla == curses.KEY_UP    and py > 0:       py -= 1
            elif tecla == curses.KEY_DOWN  and py < FILAS-1: py += 1
            elif tecla == curses.KEY_LEFT  and px > 0:       px -= 1
            elif tecla == curses.KEY_RIGHT and px < COLS-1:  px += 1
            elif tecla == 27:  # ESC
                return

            if tablero[py][px] == '.':
                puntos += 1
            tablero[py][px] = '@'

        # Colisión monstruo-jugador
        if (m1x == px and m1y == py) or (m2x == px and m2y == py):
            tablero[py][px] = 'X'
            dibujar(ventana, tablero, puntos)
            ventana.nodelay(False)
            ventana.addstr(FILAS // 2, 2,
                           f"¡Perdiste! Puntos: {puntos * 15}",
                           curses.color_pair(2) | curses.A_BOLD)
            ventana.refresh()
            ventana.getch()
            return

        # Mover monstruos
        m1x = mover_monstruo(m1x, COLS)
        m1y = mover_monstruo(m1y, FILAS)
        tablero[m1y][m1x] = 1

        m2x = mover_monstruo(m2x, COLS)
        m2y = mover_monstruo(m2y, FILAS)
        tablero[m2y][m2x] = 2


if __name__ == '__main__':
    curses.wrapper(jugar)

			
Descargar adjuntos
COMPARTE ESTE TUTORIAL

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
TUTORIAL ANTERIOR

SIGUIENTE TUTORIAL