"""Snake en Python con curses compatible Python 3.8+"""
import curses
import random
import time
# Dimensiones del área de juego (dentro del borde)
WIDTH = 40
HEIGHT = 20
# Teclas de dirección (flechas y WASD)
UP = {curses.KEY_UP, ord('w'), ord('W')}
DOWN = {curses.KEY_DOWN, ord('s'), ord('S')}
LEFT = {curses.KEY_LEFT, ord('a'), ord('A')}
RIGHT = {curses.KEY_RIGHT, ord('d'), ord('D')}
# Velocidad: segundos por tick
TICK = 0.1
def spawn_food(snake):
"""Coloca la comida en una posición libre."""
body = set(snake)
while True:
pos = (random.randint(1, HEIGHT - 2), random.randint(1, WIDTH - 2))
if pos not in body:
return pos
def main(stdscr):
curses.curs_set(0) # Ocultar cursor
stdscr.nodelay(True) # No bloquear en getch()
stdscr.timeout(0)
# Colores
curses.start_color()
curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) # serpiente
curses.init_pair(2, curses.COLOR_RED, curses.COLOR_BLACK) # comida
curses.init_pair(3, curses.COLOR_YELLOW, curses.COLOR_BLACK) # score
curses.init_pair(4, curses.COLOR_CYAN, curses.COLOR_BLACK) # borde
def play():
stdscr.clear()
# Estado inicial
cy, cx = HEIGHT // 2, WIDTH // 2
snake = [(cy, cx), (cy, cx - 1), (cy, cx - 2)]
direction = (0, 1) # (dy, dx) ? derecha
food = spawn_food(snake)
score = 0
game_over = False
last_tick = time.monotonic()
while not game_over:
# ?? Input ????????????????????????????????????????
key = stdscr.getch()
if key in UP and direction != (1, 0): direction = (-1, 0)
elif key in DOWN and direction != (-1, 0): direction = (1, 0)
elif key in LEFT and direction != (0, 1): direction = (0, -1)
elif key in RIGHT and direction != (0, -1): direction = (0, 1)
elif key == ord('q'):
return False # salir sin reiniciar
# ?? Lógica (un tick cada TICK segundos) ??????????
now = time.monotonic()
if now - last_tick >= TICK:
last_tick = now
head = (snake[0][0] + direction[0], snake[0][1] + direction[1])
# Colisión con borde
if not (0 < head[0] < HEIGHT - 1 and 0 < head[1] < WIDTH - 1):
game_over = True
break
# Colisión consigo misma
if head in snake[:-1]:
game_over = True
break
snake.insert(0, head)
if head == food:
score += 10
food = spawn_food(snake)
else:
snake.pop()
# ?? Dibujo ???????????????????????????????????????
stdscr.erase()
# Borde
for x in range(WIDTH):
stdscr.addch(0, x, '#', curses.color_pair(4))
stdscr.addch(HEIGHT - 1, x, '#', curses.color_pair(4))
for y in range(HEIGHT):
stdscr.addch(y, 0, '#', curses.color_pair(4))
stdscr.addch(y, WIDTH - 1, '#', curses.color_pair(4))
# Comida
stdscr.addch(food[0], food[1], '*', curses.color_pair(2))
# Serpiente
for i, (y, x) in enumerate(snake):
char = '@' if i == 0 else 'o'
stdscr.addch(y, x, char, curses.color_pair(1))
# Score
stdscr.addstr(0, 2, f' Puntuacion: {score} ', curses.color_pair(3))
stdscr.addstr(HEIGHT, 0, 'WASD / flechas para mover | Q para salir', curses.color_pair(3))
stdscr.refresh()
time.sleep(0.016) # ~60 fps de dibujado
# ?? Game over ?????????????????????????????????????????
msg = f'GAME OVER Puntuacion: {score}'
stdscr.addstr(HEIGHT // 2, (WIDTH - len(msg)) // 2, msg, curses.color_pair(2) | curses.A_BOLD)
stdscr.addstr(HEIGHT // 2 + 1, (WIDTH - 24) // 2, 'R para reiniciar Q para salir')
stdscr.refresh()
stdscr.nodelay(False)
while True:
k = stdscr.getch()
if k in (ord('r'), ord('R')):
return True # reiniciar
if k in (ord('q'), ord('Q'), 27):
return False # salir
# Bucle de reinicio
while play():
pass
if __name__ == '__main__':
curses.wrapper(main)
Snake en Python con curses
Juego Snake completo en Python usando el módulo curses de la biblioteca estándar. Sin dependencias externas, controles de teclado y WASD, velocidad configurable y detección de colisiones. Compatible Python 3.8+.
Descargar adjuntos
COMPARTE ESTE TUTORIAL
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP