Un vrai serpent

# -*- coding: utf-8 -*-
import curses  # pour le dessin
import time    # pour la mesure du temps d'attente

# renvoie la nouvelle direction après appui sur la touche "DROITE"
def droite() :
    if direction == DROITE : return BAS
    elif direction == BAS : return GAUCHE
    elif direction == GAUCHE : return HAUT
    else : return DROITE

# renvoie la nouvelle direction après appui sur la touche "GAUCHE"
def gauche() :
    if direction == DROITE : return HAUT
    elif direction == HAUT : return GAUCHE
    elif direction == GAUCHE : return BAS
    else : return DROITE

# calcule la nouvelle position et place le serpent
def deplace() :
    serpent.append((ligne,colonne))    # NOUVEAU : ajoute la position actuelle de 
                                       # la tête en fin de la liste des positions
    l = ligne + direction[LGN]
    c = colonne + direction[COL]
    for z in serpent:                  # NOUVEAU : pour toutes les cases du serpent ...
        ecran.addch(z[LGN],z[COL],'*') #   ... afficher la case
    ecran.addch(l,c,'O')
    return l,c

# teste si on a touché les bords
def touche() :
    return (ligne <= 0) or (colonne <= 0) or (ligne >= hauteur-1) or (colonne >= largeur-1)

# affiche un message (s) au centre de l'écran
def message(s) :
    vide = (largeur-len(s))/2                   # longueur libre de chaque côté du message
    debut = hauteur/2 - 2                       # hauteur d'affichage du message
    ecran.addstr(debut  ,0,largeur*"=")         # un trait au-dessus
    ecran.addstr(debut+1,0,vide*" "+s+vide*" ") # message au centre de la ligne
    ecran.addstr(debut+2,0,largeur*"=")         # un trait au-dessous
    ecran.nodelay(False)                        # attente sur les getch()
    ecran.getch()                               # pour attendre...
    
# dessine le bord du terrain
def bord():
    ecran.addstr(0,0,largeur*"+")          # bord du haut
    ecran.addstr(hauteur-1,0,largeur*"+")  # bord du bas
    for lg in range(1,hauteur-1):          # les côtés ...
        ecran.addstr(lg,0,"+")             #   ... à gauche   
        ecran.addstr(lg,largeur-1,"+")     #   ... à droite

    
ecran = curses.initscr() # intialisation de l'écran
ecran.nodelay(True)      # pas d'attente sur getch()
ecran.keypad(True)       # UN code sur les touches de fonctions
curses.curs_set(False)   # cacher le curseur
serpent = []             # création du serpent (liste) vide
longueur = 15            # taille du serpent

# définitions des directions de déplacement
DROITE = (0,1)
GAUCHE = (0,-1)
HAUT = (-1,0)
BAS = (1,0)

# indices pour les accès aux éléments d'un couple de  coordonénes
LGN = 0
COL = 1

# initialisations du positionnement du serpent
hauteur, largeur = ecran.getmaxyx() # taille de l'écran
ligne,colonne = hauteur/3,largeur/3 # position (de départ : arbitraire!)
direction = DROITE                  # directon (de départ : arbitraire!)
largeur -= 1                        # pour ne pas accéder à la dernière colonne
                                    # (bord : pb d'affichage dans coin en bas à droite)


c=''                              # pour que c existe à la ligne suivante
while c <> ord('q'):              # tant qu'on n'a pas appuyé sur la touche 'q'
    ecran.clear()                 # effacer l'écran
    bord()                        # dessin du bord du terrain
    ligne,colonne = deplace()     # calcule la nouvelle position et place le serpent
    serpent = serpent[-longueur:] # NOUVEAU : ne garde que la fin du serpent (taille invariable)
    if touche() :                 # si on touche le bord ...
        message ('Perdu !')       #   ... affichage du message "Perdu!"
        break                     #   ... sortie de la boucle while (donc fin du programme)
    time.sleep(0.1)               # attente pour ralentir (arbitraire!)
    c=ecran.getch()               # saisie de l'appui sur une touche du clavier
    if c == curses.KEY_LEFT: direction = gauche()
                                  # on tourne à gauche
    elif c == curses.KEY_RIGHT: direction = droite()
                                  # on tourne à droite

# remettre l'écran en "bon" état
curses.endwin()                   # sortie du mode "curses"
print "\n\n\tF I N I !\n\n"       # message de fin!