Programmation d'un jeu d'échec
Répondre à la discussion
Affichage des résultats 1 à 14 sur 14

Programmation d'un jeu d'échec



  1. #1
    Fabchat

    Programmation d'un jeu d'échec


    ------

    Bonjour à tous.

    J'aimerais programmer un jeu en Python. J'utilise visual studio code, mais je suis complètement débutant.

    C'est un jeu que j'ai inventé et qui est basé sur les échecs. Il se joue sur un échiquier classique.

    Je l'ai intitulé : La botte secrète du roi.

    Voici le lien d'un vidéo expliquant les règles du jeu : https://www.youtube.com/watch?v=hlAc6H_F0us&t=124s

    Y aurait-il quelqu'un d'intéressé qui aurait du temps à me consacrer pour m'aider à le programmer svp ?

    Cordialement Fabien.

    -----

  2. #2
    Henrix

    Re : Programmation d'un jeu d'échec

    Si tu compte faire jouer le pc, c'est fort ambitieux.
    Surtout pour un débutant.

  3. #3
    umfred

    Re : Programmation d'un jeu d'échec

    Apprends à faire des choses basiques pour commencer et te familiariser avec python (en particulier, les listes, puis les classes un peu plus tard, et encore plus tard la partie graphique).
    Dans tous les cas, commence par une version "console" (sans graphique) (basiquement, le plateau est une liste de liste (une liste de n lignes, chaque ligne étant une liste de n cases qui contiennent la valeur de son contenu (vide, roi, pion, ...) sous une forme ou une autre (valeur, chaine, objet,..))

  4. #4
    ThM55

    Re : Programmation d'un jeu d'échec

    Si tu connais le C et le C++, tu peux jeter un coup d'oeil au programme GNU Chess qui open-source: https://www.gnu.org/software/chess/ .

    Pas pour voir comment ils ont conçu le moteur de jeu dans un premier temps (ce qui est très compliqué) mais d'abord pour les structures de données qu'ils ont utilisée. C'est en effet un point crucial. On s'aperçoit vite qu'utiliser de mauvaises solutions pour représenter le jeu conduit à des programmes très mal construits.

  5. A voir en vidéo sur Futura
  6. #5
    Fabchat

    Re : Programmation d'un jeu d'échec

    Merci Henrix, C'est une bonne question en effet !
    Du coup, non, je voudrais pour commencer, établir un programme qui permet à 2 joueurs de jouer l'un contre l'autre, ça serait un bon début.
    Et plus tard, quand j'aurais une meilleur maîtrise, programmer le jeu pour jouer contre l'ordinateur.

    umfred J'ai commençais à faire quelque petits trucs du genre, programmer une fenêtre avec un bouton. Là je suis en train d'essayer de programmer une horloge à cadrant circulaire mais c'est pas gagné.
    Je vais suivre tes conseils. Mais j'aimerais trouver un site de formation en programmation sur Python pour bien débuter et progresser tranquillement. Sinon, je devrais apprendre sur le tas avec des tutos ou en demandant à des experts comme je fait là.
    Merci pour ton aide !

    ThM55 Non, je ne connaît pas le C et le C++, mais j'ai cliqué sur ton lien et jeté un œil sur ce site, ça m'a l'air très intéressent ! Apparemment c'est un organisme qui défend notre liberté du logiciel depuis 40 ans.
    ça m'a l'air asses complexe pour moi quand même, mais je vais étudier ça de plus près. Merci pour ces précisions, je vais suivre tes conseils !

  7. #6
    Fabchat

    Re : Programmation d'un jeu d'échec

    Pourriez vous m'aider, svp ?

    Voilà sur quoi je travail en ce moment :
    C'est le graphisme d'un échiquier.
    Code:
    coord=[
        'a8','b8','c8','d8','e8','f8','g8','h8',
        'a7','b7','c7','d7','e7','f7','g7','h7',
        'a6','b6','c6','d6','e6','f6','g6','h6',
        'a5','b5','c5','d5','e5','f5','g5','h5',
        'a4','b4','c4','d4','e4','f4','g4','h4',
        'a3','b3','c3','d3','e3','f3','g3','h3',
        'a2','b2','c2','d2','e2','f2','g2','h2',
        'a1','b1','c1','d1','e1','f1','g1','h1',
        ]
    
    self.cases = [
        Piece('TOUR','noir'),Piece('CAVALIER','noir'),Piece('FOU','noir'),Piece('DAME','noir'),Piece('ROI','noir'),Piece('FOU','noir'),Piece('CAVALIER','noir'),Piece('TOUR','noir'),
        Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),
        Piece('TOUR','blanc'),Piece('CAVALIER','blanc'),Piece('FOU','blanc'),Piece('DAME','blanc'),Piece('ROI','blanc'),Piece('FOU','blanc'),Piece('CAVALIER','blanc'),Piece('TOUR','blanc')
        ]
    
    nomPiece=(VIDE,'ROI','DAME','TOUR','CAVALIER','FOU','PION')
    valeurPiece=(0,0,9,5,3,3,1)
    tab120 = (
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1,  0,  1,  2,  3,  4,  5,  6,  7, -1,
        -1,  8,  9, 10, 11, 12, 13, 14, 15, -1,
        -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
        -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
        -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
        -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
        -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
        -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
        )
    
    tab64 = (
        21, 22, 23, 24, 25, 26, 27, 28,
        31, 32, 33, 34, 35, 36, 37, 38,
        41, 42, 43, 44, 45, 46, 47, 48,
        51, 52, 53, 54, 55, 56, 57, 58,
        61, 62, 63, 64, 65, 66, 67, 68,
        71, 72, 73, 74, 75, 76, 77, 78,
        81, 82, 83, 84, 85, 86, 87, 88,
        91, 92, 93, 94, 95, 96, 97, 98
        )
    deplacements_tour=(-10,10,-1,1)
    deplacements_fou=(-11,-9,11,9)
    deplacements_cavalier=(-12,-21,-19,-8,12,21,19,8)
    
    def evaluer(self):
            
        '''A wonderful evaluate() function
        returning actually only the material score'''
            
        WhiteScore=0
        BlackScore=0
            
        # Parsing the board squares from 0 to 63
        for pos1,piece in enumerate(self.cases):
    
            # Material score
            if(piece.couleur=='blanc'):
                WhiteScore+=piece.valeur
            else:
                # NB : here is for black piece or empty square
                BlackScore+=piece.valeur
    
        if(self.side2move=='blanc'):
            return WhiteScore-BlackScore
        else:
            return BlackScore-WhiteScore
        
    def alphabeta(self,depth,alpha,beta,b):
    
        # We arrived at the end of the search : return the board score
        if(depth==0):
            return b.evaluer()
            # TOTO : return quiesce(alpha,beta)
    
        self.nodes+=1
        self.pv_length[b.ply] = b.ply
    
        # Do not go too deep
        if(b.ply >= self.MAX_PLY-1):
            return b.evaluer()
                
        # Extensions
        # If king is in check, let's go deeper
        chk=b.in_check(b.side2move) # 'chk' used at the end of func too
        if(chk):
            depth+=1
    
        # Generate all moves for the side to move. Those who 
        # let king in check will be processed in domove()
        mList=b.gen_moves_list()
    
        f=False # flag to know if at least one move will be done
        for i,m in enumerate(mList):
               
            # Do the move 'm'.
            # If it lets king in check, undo it and ignore it
            # remind : a move is defined with (pos1,pos2,promote)
            # i.e. : 'e7e8q' is (12,4,'q')
            if(not b.domove(m[0],m[1],m[2])):
                continue
                    
            f=True # a move has passed
                
            score=-self.alphabeta(depth-1,-beta,-alpha,b)
    
            # Unmake move
            b.undomove()
    
            if(score>alpha):
                        
                # this move caused a cutoff,
                if(score>=beta):
                    return beta
                alpha = score
    
                # Updating the triangular PV-Table
                self.pv[b.ply][b.ply] = m
                j = b.ply + 1
                while(j<self.pv_length[b.ply+1]):
                    self.pv[b.ply][j] = self.pv[b.ply+1][j]
                    self.pv_length[b.ply] = self.pv_length[b.ply + 1]
                    j+=1
                        
        # If no move has been done : it is DRAW or MAT
        if(not f):
            if(chk):
                return -self.INFINITY + b.ply # MAT
            else:
                return 0 # DRAW
    
        return alpha
    Mais quand je clic sur exécuter le fichier, il m'affiche que, self, Piece et VIDE ne sont pas défini dans le terminal

    Que doit-je faire, svp ?
    Dernière modification par gienas ; 29/06/2025 à 09h08. Motif: Ajouté les balises code obligatoires pour les programmes

  8. #7
    oxycryo

    Re : Programmation d'un jeu d'échec

    tu peux essayer de reposter avec la balise [code ] [/code ]

    histoire de ne pas perdre les tabulations de ton appli ?
    libera me : ungoogled chromium, e.foundation (anti-droid)

  9. #8
    Fabchat

    Re : Programmation d'un jeu d'échec

    Désolé mais je ne vois pas.

    La balise [code ] [/code ], c'est quoi ?
    Et la tabulation c'est quoi, le chiffrage des lignes sur le côté ?

  10. #9
    Fabchat

    Re : Programmation d'un jeu d'échec

    J'ai essayé mais ça ne marche pas !
    Dernière modification par Fabchat ; 28/06/2025 à 14h25.

  11. #10
    Fabchat

    Re : Programmation d'un jeu d'échec

    Comme ça ?

    Code:
    coord=[
        'a8','b8','c8','d8','e8','f8','g8','h8',
        'a7','b7','c7','d7','e7','f7','g7','h7',
        'a6','b6','c6','d6','e6','f6','g6','h6',
        'a5','b5','c5','d5','e5','f5','g5','h5',
        'a4','b4','c4','d4','e4','f4','g4','h4',
        'a3','b3','c3','d3','e3','f3','g3','h3',
        'a2','b2','c2','d2','e2','f2','g2','h2',
        'a1','b1','c1','d1','e1','f1','g1','h1',
        ]
    
    self.cases = [
        Piece('TOUR','noir'),Piece('CAVALIER','noir'),Piece('FOU','noir'),Piece('DAME','noir'),Piece('ROI','noir'),Piece('FOU','noir'),Piece('CAVALIER','noir'),Piece('TOUR','noir'),
        Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),Piece('PION','noir'),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),Piece(),
        Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),Piece('PION','blanc'),
        Piece('TOUR','blanc'),Piece('CAVALIER','blanc'),Piece('FOU','blanc'),Piece('DAME','blanc'),Piece('ROI','blanc'),Piece('FOU','blanc'),Piece('CAVALIER','blanc'),Piece('TOUR','blanc')
        ]
    
    nomPiece=(VIDE,'ROI','DAME','TOUR','CAVALIER','FOU','PION')
    valeurPiece=(0,0,9,5,3,3,1)
    tab120 = (
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1,  0,  1,  2,  3,  4,  5,  6,  7, -1,
        -1,  8,  9, 10, 11, 12, 13, 14, 15, -1,
        -1, 16, 17, 18, 19, 20, 21, 22, 23, -1,
        -1, 24, 25, 26, 27, 28, 29, 30, 31, -1,
        -1, 32, 33, 34, 35, 36, 37, 38, 39, -1,
        -1, 40, 41, 42, 43, 44, 45, 46, 47, -1,
        -1, 48, 49, 50, 51, 52, 53, 54, 55, -1,
        -1, 56, 57, 58, 59, 60, 61, 62, 63, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
        )
    
    tab64 = (
        21, 22, 23, 24, 25, 26, 27, 28,
        31, 32, 33, 34, 35, 36, 37, 38,
        41, 42, 43, 44, 45, 46, 47, 48,
        51, 52, 53, 54, 55, 56, 57, 58,
        61, 62, 63, 64, 65, 66, 67, 68,
        71, 72, 73, 74, 75, 76, 77, 78,
        81, 82, 83, 84, 85, 86, 87, 88,
        91, 92, 93, 94, 95, 96, 97, 98
        )
    deplacements_tour=(-10,10,-1,1)
    deplacements_fou=(-11,-9,11,9)
    deplacements_cavalier=(-12,-21,-19,-8,12,21,19,8)
    
    def evaluer(self):
            
        '''A wonderful evaluate() function
        returning actually only the material score'''
            
        WhiteScore=0
        BlackScore=0
            
        # Parsing the board squares from 0 to 63
        for pos1,piece in enumerate(self.cases):
    
            # Material score
            if(piece.couleur=='blanc'):
                WhiteScore+=piece.valeur
            else:
                # NB : here is for black piece or empty square
                BlackScore+=piece.valeur
    
        if(self.side2move=='blanc'):
            return WhiteScore-BlackScore
        else:
            return BlackScore-WhiteScore
        
    def alphabeta(self,depth,alpha,beta,b):
    
        # We arrived at the end of the search : return the board score
        if(depth==0):
            return b.evaluer()
            # TOTO : return quiesce(alpha,beta)
    
        self.nodes+=1
        self.pv_length[b.ply] = b.ply
    
        # Do not go too deep
        if(b.ply >= self.MAX_PLY-1):
            return b.evaluer()
                
        # Extensions
        # If king is in check, let's go deeper
        chk=b.in_check(b.side2move) # 'chk' used at the end of func too
        if(chk):
            depth+=1
    
        # Generate all moves for the side to move. Those who 
        # let king in check will be processed in domove()
        mList=b.gen_moves_list()
    
        f=False # flag to know if at least one move will be done
        for i,m in enumerate(mList):
               
            # Do the move 'm'.
            # If it lets king in check, undo it and ignore it
            # remind : a move is defined with (pos1,pos2,promote)
            # i.e. : 'e7e8q' is (12,4,'q')
            if(not b.domove(m[0],m[1],m[2])):
                continue
                    
            f=True # a move has passed
                
            score=-self.alphabeta(depth-1,-beta,-alpha,b)
    
            # Unmake move
            b.undomove()
    
            if(score>alpha):
                        
                # this move caused a cutoff,
                if(score>=beta):
                    return beta
                alpha = score
    
                # Updating the triangular PV-Table
                self.pv[b.ply][b.ply] = m
                j = b.ply + 1
                while(j<self.pv_length[b.ply+1]):
                    self.pv[b.ply][j] = self.pv[b.ply+1][j]
                    self.pv_length[b.ply] = self.pv_length[b.ply + 1]
                    j+=1
                        
        # If no move has been done : it is DRAW or MAT
        if(not f):
            if(chk):
                return -self.INFINITY + b.ply # MAT
            else:
                return 0 # DRAW
    
        return alpha

  12. #11
    oxycryo

    Re : Programmation d'un jeu d'échec

    je trouve l'écriture self.case en dehors d'une classe fort dérangeante pour ma petite pomme..

    mais j'utilise très très peu de classe, les def python faisant les 99% de ce dont j'ai besoin

    tu devrait toutefois regarder à celle-ci, car le terme self défini en dehors d'une classe ne me semble pas "légal" (à voir donc, mais je ne l'ai jamais rencontré)

    PS: oui écrit ainsi, c'est beaucoup lus lisible, merci pour ton effort
    libera me : ungoogled chromium, e.foundation (anti-droid)

  13. #12
    Fabchat

    Re : Programmation d'un jeu d'échec

    Le terme self défini en dehors d'une classe ne te semble pas "légal".

    Ok, je vais essayer de rectifier ça alors.

    Merci beaucoup oxycryo pour ton retour
    Dernière modification par Fabchat ; 29/06/2025 à 16h35.

  14. #13
    umfred

    Re : Programmation d'un jeu d'échec

    pour les tuto de python tu as ceux du site officiel https://docs.python.org/fr/3.13/tutorial/index.html
    ceux de w3schools https://www.w3schools.com/python/
    celui de zestedesavoir https://zestedesavoir.com/tutoriels/...ste-de-python/
    ou encore le Swinnen https://inforef.be/swi/download/apprendre_python3_5.pdf

    Sinon je réitère ma suggestion d'une grille sous forme de listes de listes
    Code:
    grille=[[0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0],
               [0,0,0,0,0,0,0,0]]
    #ou plus pythonesque
    grille=[[0 for i in range(8)] for i in range(8)]
    ainsi tu accèdes à une case par grille[ligne][colonne] (en allant de 0 à 7) mais tu peux définir des fonctions pour avoir un accès avec une notation d'échecs
    Code:
    alpha=[chr(i) for i in range(ord('A)',ord('A')+8)]
    #ou 
    #import string
    #alpha=list(string.ascii_uppercase)[:8]
    def Chess2LC(case:str):
        # case de la forme "a8"
        # renvoi un tuple (Ligne,Colonne) valant (0,0)
        # par rapport à la définition que tu en faites dans ton code (A8 en haut à gauche)
        return (8-case[1],alpha.index(case[0].upper()))
    
    l,c=Chess2LC("a8")
    print(grille[l][c]) # affiche la valeur de la case A8
    pour les déplacements, ça me semble devenir plus facile (on avance d'une ligne, on incrémente ou décrémente le numéro de ligne; idem pour les colonnes


    Et dans ton code, il manque la définition de Piece (qui devrait sans doute être une classe) et de VIDE (qui devrait peut-être valoir 0 ou tu as oublié les guillemets autour du mot)

    Et en général, on n'aime pas trop les valeurs "magiques" (fixées en dur) si ça ne se justifie pas (si on peut les calculer à partir de valeurs de base, on préfèrera faire le calcul
    tes variables tab64 et tab120 contiennent des valeurs qui viennent d'on ne sait où, idem pour tes déplacements (pas d'explications sur ces valeurs "sorties de nulle part"))
    D'ailleurs dans mon code ci-dessus, on devrait remplacer les 8 de la construction de la grille (et le 8 de la construction de la liste alpha) par 2 variables type NBCOL et NBLIG, initialisées à 8 toutes les 2; ainsi si on décide de changer la taille de la grille, on ne doit que changer ces 2 valeurs et le reste se fait automatiquement).

    PS: il faudrait aussi rajouter des contrôles dans mes fonctions pour vérifier qu'on ne cherche pas à aller en dehors de la grille

  15. #14
    polo974

    Re : Programmation d'un jeu d'échec

    Citation Envoyé par Fabchat Voir le message
    Le terme self défini en dehors d'une classe ne te semble pas "légal".

    Ok, je vais essayer de rectifier ça alors.

    Merci beaucoup oxycryo pour ton retour
    le terme self est par pure convention la désignation de (la référence) de l'instance de l'objet dans lequel on travaille. cette référence est passée automatiquement en premier paramètre, les fonctions ("normales") dans une classe doivent donc être déclarée avec ce "self" en premier paramètre.

    imaginons une classe Cube dont knorr est une instance:
    écrire knorr.volume() est équivalent à écrire Cube.volume(knorr) mais c'est plus court, propre et compréhensible.

    et la fonction volume est donc écrite un peu comme ça:
    Code:
    class Cube:
        ... 
        
        def volume(self):
            return self.h * self*w * self.l
            
        ...
    Mais on voit ici que self est juste le nom qu'on a donné dans la déclaration de la fonction Cube.volume on aurait pu mettre this (pour singer le C++) ou s pour le paresseux suprême, mais ce n'est pas conforme aux règles pythonesques (les PEP)

    Par contre en dehors d'une classe, tu as le droit d'écrire self = 666 c'est zarb, mais pas interdit.

    Le nom self n'est pas réservé, mais bon, hein, on va éviter de s'en servir n'importe comment et on va s'en servir quand c'est prévu par convention car il faut toujours penser qu'un code doit pouvoir être lu et compris par quelqu'un d'autre...
    Jusqu'ici tout va bien...

Discussions similaires

  1. quelle est la difference entre programmation procedurale et la programmation orientee objet
    Par invite430abc62 dans le forum Programmation et langages, Algorithmique
    Réponses: 9
    Dernier message: 27/01/2016, 13h34
  2. Echec programmation AtTint85
    Par invite28c917f0 dans le forum Électronique
    Réponses: 10
    Dernier message: 20/04/2015, 13h58
  3. Echec au bac
    Par invite776e7e89 dans le forum Orientation après le BAC
    Réponses: 0
    Dernier message: 05/02/2010, 19h03
  4. En cas d'echec...
    Par invite71ea2a67 dans le forum Orientation après le BAC
    Réponses: 0
    Dernier message: 31/08/2008, 00h40
  5. Echec 2 la programmation ds la zone de code a l'adresse 000h
    Par inviteeddea82a dans le forum Électronique
    Réponses: 16
    Dernier message: 24/10/2003, 10h45