En prime

En cadeau une version complète, légérement modifiée, qui utilise différemment les flèches de direction. L'appui sur une des quatre flèches de direction fait tourner le serpent dans cette direction de façon absolue : par exemple, si on appuie sur la flèche HAUT le serpent part vers le haut.

# -*- 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 ""
def bas() :
    if (direction == DROITE) or (direction==GAUCHE) :
        return BAS
    return direction

# renvoie la nouvelle direction après appui sur la touche "haut"
def haut() :
    if (direction == DROITE) or (direction==GAUCHE) :
        return HAUT
    return direction

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

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

# calcule la nouvelle position et place le serpent
def deplace() :
    serpent.append((ligne,colonne))    # 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:                  # pour toutes les cases du serpent ...
        ecran.addch(z[LGN],z[COL],'*') #   ... afficher la case
    ecran.addch(l,c,'O')
    return l,c

# NOUVEAU : la fonction est réécrite entièrement
# teste si on a touché les bords ou le corps
def touche() :
    # si la tête du serpent touche le bord 
    if (ligne <= 0) or (colonne <= 0) or (ligne >= hauteur-1) or (colonne >= largeur-1) :
        return True    # renvoyer VRAI (= on a perdu)
    # pour toutes les cases du serpent
    for z in serpent:
        if z == (ligne,colonne) : # si la case est au même endroit que la tête ...
            return True           #   ... renvoyer VRAI (= on a perdu)
    # si on arrive ici, c'est qu'il n'y a pas eu de problème
    return False       # renvoyer FAUX (= pas de problème)

# 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)

compteur=0                          # compteur  entre 2 croissance du serpent

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:] # ne garde que la fin du serpent (taille invariable)
    compteur += 1                 # un tour de plus
    if compteur > 5:              # si on passe 5 tours ...
        compteur = 0              #   ... remise du compteur à zéro
        longueur += 1             #   ... fait grandir le serpent
    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
    elif c == curses.KEY_UP: direction = haut()
                                  # on tourne à gauche
    elif c == curses.KEY_DOWN: direction = bas()
                                  # 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!