| 12
 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
 126
 127
 
 | class Puissance4:
    """
    Puissance4 possede:
    
    1 methode: put_pawn()
    les appels succesifs a put_pawn() font jouer tour a tour tant que Run est True.
    
    5 attributs qui permettent d'implementer une GUI: Player, Winner, Pawn, Grid et Winlist.
    Player, Winner et Pawn ne sont pas essentiels mais apportent une indiquation sur le deroulement du jeu.
    Player est le numero du joueur en cours, vaut 1 ou 2.
    Winner vaut None tant qu'il n'y a pas de gagnant, sinon vaut Player et suspend le deroulement normal de put_pawn().
    Pawn est le pion du joueur en cours.
    Grid est une liste de bytearray qui represente la grille de jeu lue horizotalement (voir la doc bytearray).
    Grid servira donc pour une interface graphique.
    exemple pour une grille 5x3:
    Grid=
    [
    b'00000',
    b'00000',
    b'00000'
    ]
    Winlist ; c'est la liste des coordonnees des pions places gagnant dans Grid.
    """    
    def __init__(self,Width,Height,Align,Empty,PawnJ1,PawnJ2):
        """
        le jeu s'initialise ainsi:
        Width et Height indiquent la taille de la grille de jeu, soit la largeur et la hauteur.
        Align indique le nombre de pions a aligner pour gagner.
        Empty,PawnJ1 et PawnJ2 sont 3 caracteres correspondant a:
        case vide, pion du 1er joueur et pion du 2nd joueur...
        vous pouvez indiquer une valeur numerique, par exemple, si vous voulez
        que 0 represente case vide:
        Empty = '\0'
        """
        self.Align = Align
        self.Pawns = [PawnJ1,PawnJ2]
        self.Empty = Empty
        self.Winner = None
        self.Run = True
        self.Shots = Width*Height
        self.Player = 1
        self.Pawn = self.Pawns[0]
        self.Winlist = ([],[],[],[])
        self.Grid = [bytearray(self.Empty*Width) for _ in range(Height)]
        self.Grid_verti = [bytearray(self.Empty*Height) for _ in range(Width)]
        self.Grid_diag1 = [bytearray(self.Empty*(Height)) for _ in range(Width+Height-1)]
        self.Grid_diag2 = [bytearray(self.Empty*(Height)) for _ in range(Width+Height-1)]
 
    def put_pawn(self,Column):
        """
        l'argument Column indique la colonne dans laquelle le joueur veut poser son pion.
        put_pawn() maintient Player, Pawn et Winner qui indiquent quel joueur joue ou va jouer ...
        et s'il y a un gagnant.
        """
        if self.Run:
            try:
                y = self.Grid_verti[Column].rindex(self.Empty)
            except: return
 
            self.Shots -= 1
 
            self.Grid[y][Column] = self.Pawn
            pos = self.Grid[y].find(self.Align*self.Pawn)
            if pos > -1:
                self.Winner = self.Player
                self.Run = False
                while self.Grid[y][pos:pos+1] == self.Pawn:
                    self.Winlist[0].append((pos,y))
                    pos+=1      
 
            self.Grid_verti[Column][y] = self.Pawn
            pos = self.Grid_verti[Column].find(self.Align*self.Pawn)
            if pos > -1:
                self.Winner = self.Player
                self.Run = False
                while self.Grid_verti[Column][pos:pos+1] == self.Pawn:
                    self.Winlist[1].append((Column,pos))
                    pos+=1
 
            diag = y+Column
            self.Grid_diag1[diag][y] = self.Pawn
            pos = self.Grid_diag1[diag].find(self.Align*self.Pawn)
            if pos > -1:
                self.Winner = self.Player
                self.Run = False
                while self.Grid_diag1[diag][pos:pos+1] == self.Pawn:
                    self.Winlist[2].append((diag-pos,pos))
                    pos += 1
 
            diag = Column-y+len(self.Grid)-1
            self.Grid_diag2[diag][y] = self.Pawn
            pos = self.Grid_diag2[diag].find(self.Align*self.Pawn)
            if pos > -1:
                self.Winner = self.Player
                self.Run = False
                while self.Grid_diag2[diag][pos:pos+1] == self.Pawn:
                    self.Winlist[3].append((Column-y+pos,pos))
                    pos += 1
 
            if not self.Shots: self.Run = False
            if self.Run:
                self.Pawns.reverse()
                self.Pawn = self.Pawns[0]
                self.Player = (not self.Player-1)+1
 
#***************************************************************************************************************
#***************************************************************************************************************
# exemple en mode console
if __name__ == '__main__':
    # routine qui affiche la grille
    def showgrid():
        print ' A B C D E F G'
        for _ in game.Grid:
            print _.replace('','|')
            print '---------------'
    # routine qui lit dans quelle colonne poser le pion
    askwhere = lambda: 'ABCDEFG'.index(raw_input("joueur "+str(game.Player)+" joue: ").upper())
    # arguments pour l'initialisation du jeu
    init = largeur,hauteur,alignement,case_vide,pion_joueur_1,pion_joueur_2 = 7,6,4,' ','x','o'
 
    game = Puissance4(*init) # init du jeu
    showgrid() # affichage de la grille
    while game.Run: # tant que c'est jouable ...
        game.put_pawn(askwhere()) # poser un pion
        showgrid() # affichage de la grille
    print "joueur "+game.Winner+" gagne!" if game.Winner else "personne ne gagne"
    print game.Winlist |