Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Pascal Discussion :

Représentation du jeu du moulin


Sujet :

Pascal

  1. #1
    Rédacteur/Modérateur

    Représentation du jeu du moulin
    Bonjour !

    J'aimerais bien travailler sur le jeu du moulin, qui est connu aussi sous d'autre noms. Si vous ne connaissez pas, voici deux (très beaux) logiciels qui permettent d'y jouer :


    Comment vous y prendriez-vous pour représenter la table de jeu ? Je ne parle de la représentation visuelle, mais de la représentation logique. Comment désigner les cases ou les emplacements ? Comment déterminer que deux cases sont reliées ? Comment déterminer que trois cases sont alignées ?

    Le problème est d'autant plus amusant que le jeu a des variantes (on peut s'en faire une idée en regardant cette page).

    Il faut donc imaginer une notation pour les coups, déterminer si les coups sont possibles, s'ils ont pour résultat un moulin (un alignement de trois pièces)...

    Qu'en pensez-vous ? Pour ma part, à première vue, je trouve ça assez compliqué.

  2. #2
    Responsable Pascal, Lazarus et Assembleur

    Bonjour Roland,

    Effectivement cela paraît assez compliqué. Pour la représentation en mémoire, je partirais de l'existence de 24 intersections et de 16 moulins, chaque intersection ayant 2 ou 3 intersections adjacentes et appartenant à 2 moulins :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    type
     
      TIntersection = Record
        Valeur : Integer;
        IndiceAdjacent1 : Integer;
        IndiceAdjacent2 : Integer;
        IndiceAdjacent3 : Integer;
        IndiceMoulin1 : Integer;
        IndiceMoulin2 : Integer;
      end;
     
      TMoulin = Record
        Complet : Boolean;
        IndiceIntersection1 : Integer;
        IndiceIntersection2 : Integer;
        IndiceIntersection3 : Integer;
      end;
     
      TIntersections = Array [1..24] of TIntersection;
      TMoulins = Array [1..16] of TMoulin;

    Chaque changement de valeur d'une intersection se reporterait ainsi sur les deux moulins qu'elle concerne et il serait aisé d'accéder à la complétude (ou non) des deux moulins liés à chaque intersection. Une version objet ou avec des enregistrements étendus serait bien sûr plus élégante. D'autres auront peut-être des idées plus performantes.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]

  3. #3
    Membre expert
    Salut Roland,

    cela me fait penser à un "morpion" sous stéroïde. L'emploi d'un algo genre NegaMax / MinMax devrait permettre de trouver si il y un "moulin" correcte et/ou permettre de déterminer les mouvements de l'IA.

    Pour ce qui est de la structure, je ferai peut-être quelques chose orienté objet dans ce style :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    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
    Type
      TPlayerType = (ptHuman, ptComputer);
     
      TCellStatus = (csUndefined, csPlayer1, csPlayer2);
      TBoard = Array of TCellStatus;//Array[0..cMaxBoardSize-1] of TCellStatus;  
      TMills = Array of Array of Byte;
     
     
      TBoardGame = class
      private
         FMaxBoardSize : Byte;
         FMaxVoisin : Byte;
         FBoardName : String;
         FBoardWidth, FBoardHeight : Byte;
     
         FBoard : TBoard;
     
         FMaxMills : Byte;
         FMaxMillTokens : Byte;
         FMills : TMills
       // Exemple  FMills avec FMaxMills = 16 FMaxMillToken = 3
       // Moulins horizontaux
      { (0, 1, 2),      (3, 4, 5),      
       (6, 7, 8),      (9, 10, 11),   
       (12, 13, 14), (15, 16, 17),
       (18, 19, 20), (21, 22, 23),
       // Moulins Verticaux
       (0, 9, 21),     (3, 10, 18),
       (6, 11, 15),   (1, 4, 7),
       (16, 19, 22), (8, 12, 17),
       (5, 13, 20),  (2,14,23) }
     
      protected
     
      public     
         Constructor Create;
         Destructor Destroy;
     
         function getBoard : TBoard;
     
         property MaxBoardSize : Byte read FMaxBoardSize;
         property MaxVoisin : Byte read MaxVoisin;
         property BoardName : String read FBoardName;
         property FBoardWidth : Byte read FBoardWidth;
         property BoardHeight : Byte read FBoardHeight;
         property MaxMills : Byte read FMaxMills;
         property MaxMillTokens : Byte read FMaxMillTokens;
     
         property Mill[MillIndex : Integer; TokenIndex : Integer] : Integer read getMillToken;
         property Cell[Index : Integer] : TCellStatus read getCell write setCell
      end;
     
      TPlayer = Class
      private
        FBoard : TBoardGame;
        FPlayerType : TPlayerType;
     
        function CanMove(OldPos, NewPos : Integer) : Boolean;
      public
         Constructor Create(ABoard : TBoardGame);
     
         procedure SetMove(NewPos : Integer):
         procedure UpdateMove(OldPos, NewPos : Integer):
     
         function CheckIfWin : Boolean;
     
         property PlayerType : TPlayerType read FPlayerType write FPlayerType;
      end;


    Il manque quelques éléments pour obtenir des plateaux de jeux persos. A voir comment ajouter, personnaliser la position des cases en fonction de l'algo pour dessiner les grilles de jeu. On pourrait également ajouter un tableau pour stocker tous les voisins à une position X (un peu comme le FMills) Ce qui simplifierait les tests.

    A+

    Jérôme
    • "L'Homme devrait mettre autant d'ardeur à simplifier sa vie qu'il met à la compliquer" - Henri Bergson
    • "Bien des livres auraient été plus clairs s'ils n'avaient pas voulu être si clairs" - Emmanuel Kant
    • "La simplicité est la sophistication suprême" - Léonard De Vinci
    • "Ce qui est facile à comprendre ou à faire pour toi, ne l'est pas forcément pour l'autre." - Mon pèrei

    Mes projets sur Github - Blog - Site DVP

  4. #4
    Rédacteur/Modérateur

    Citation Envoyé par Alcatîz Voir le message
    Bonjour Roland,

    Effectivement cela paraît assez compliqué. Pour la représentation en mémoire, je partirais de l'existence de 24 intersections et de 16 moulins, chaque intersection ayant 2 ou 3 intersections adjacentes et appartenant à 2 moulins :
    Intéressant. C'est déjà un peu plus clair. Merci !

    Je prends encore quelques jours pour jouer et bien assimiler les règles, et je passe aux travaux pratiques.

  5. #5
    Rédacteur/Modérateur

    Citation Envoyé par BeanzMaster Voir le message
    Pour ce qui est de la structure, je ferai peut-être quelques chose orienté objet dans ce style :
    Merci Jérôme pour toutes ces idées. Je vais m'en inspirer.

    Au fait, j'ai encore trouvé un autre logiciel, qui a quelques années, mais qui fonctionne parfaitement : http://belasius.com/mulino/

    Il y a aussi celui-ci, en C, qui est plus basique, mais qui fonctionne bien aussi : https://github.com/paul-maxime/merreles

    Ce serait amusant de faire un tournoi de robots. Il faudrait inventer un protocole... Bon, nous n'en sommes pas là, mais l'idée me plaît bien. Ça m'a même presque empêché de dormir.

  6. #6
    Expert confirmé
    salut

    un tableau ou un arbre

    tu as un maximum 4 connexions

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
       Directions = (Haut,Bas,Droite,Gauche)
     
    TCellule = Class
     
    TConnexion = Class 
      Voisin : Array[Directions] of TCellule;
    End
     
    TCellule = Class 
       Ident         : integer;
       Position     : Tpos;
       Connexion : TConnexion;
    End;
    Nous souhaitons la vérité et nous trouvons qu'incertitude. [...]
    Nous sommes incapables de ne pas souhaiter la vérité et le bonheur, et sommes incapables ni de certitude ni de bonheur.
    Blaise Pascal
    PS : n'oubliez pas le tag

  7. #7
    Rédacteur/Modérateur

    Je partirais sur quelque chose de ce style :

    Des pions valant 1 (blanc) ou -1 (noir), un moulin complet valant +3 ou -3.
    Des moulins contenant la liste de leurs points.
    Des points contenant leur couleur actuelle, la liste des moulins les contenant et les points connectés pour déplacement.
    Des joueurs avec leur couleur et les points qu'ils possèdent.

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    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
    type
      TMoveResult = (tmDenied, tmPartial, tmFull); // Point déjà occupé, moulin partiel ou complet
     
      TCell = class;
     
      TMill = class
        Cells :array of TCell;
        function IsFull :boolean;  // +3: blanc, -3:noir
      end;
     
      TCell = class
        Color :shortint;           // 0: vide, 1: blanc, -1:noir
        Mills :array of TMill;     // Moulins concernés
        Cells :array of TCell;     // Points connexes pour déplacement
        function Move(aDest :TCell) :TMoveResult;
      end;
     
      TPlayer = class
        Color :shortint;           // 1: blanc, -1:noir (constante)
        Cells :array of TCell;     // Points avec sa couleur, augmente de 1 à 9 puis se réduit de 9 à 2
      end;
     
      TBoard = class
        Players :array[boolean] of TPlayer;
        Current :boolean;                     // Joueur actuel
        Grid : array of array of TCell;       // Grille contenant ou non (nil) un point
        function Move(aSource, aDest :TCell) :TMoveResult;
      end;


    Sur OnMouseDown, contrôle de la validité du pion pour le joueur actuel et sur OnMouseUp TBoard.Move appelle TCell.Move pour contrôler la validité du déplacement puis assigne la cellule au joueur qui la remplit de sa couleur et éventuellement retire un pion adverse, etc, etc.

  8. #8
    Rédacteur/Modérateur

    Merci pour vos précieuses contributions.

    Citation Envoyé par Andnotor Voir le message
    Sur OnMouseDown, contrôle de la validité du pion pour le joueur actuel et sur OnMouseUp TBoard.Move appelle TCell.Move pour contrôler la validité du déplacement puis assigne la cellule au joueur qui la remplit de sa couleur et éventuellement retire un pion adverse, etc, etc.
    Dans un premier temps je pense faire une application console, où l'on entre les coups au clavier.

  9. #9
    Rédacteur/Modérateur

    Petite parenthèse, sur le nom du jeu. Si l'on en croit Littré, le nom du jeu serait... marelle. Je suis allé voir aussi l'article moulin : on n'y trouve aucune mention d'un jeu qui porterait ce nom.

    P.-S. Plus d'informations dans cet article.

  10. #10
    Rédacteur/Modérateur

    Je n'ai pas oublié cette discussion. J'ai regardé d'un peu plus près ce programme-ci. Je l'ai trouvé très bien écrit. J'ai bien envie de le traduire en Pascal.

    Autrement j'ai commencé à réfléchir à la façon de numéroter les intersections.

    Code X :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    7   000------------001------------002
         |              |              |
    6    |   008-------009-------010   |
         |    |         |         |    |
    5    |    |   016--017--018   |    |
         |    |    |         |    |    |
    4   007--015--023       019--011--003
         |    |    |         |    |    |
    3    |    |   022--021--020   |    |
         |    |         |         |    |
    2    |   014-------013-------012   |
         |              |              |
    1   006------------005------------004
    
         a    b    c    d    e    f    g


    La plupart des programmes que j'ai vus numérotent les lignes de haut en bas. Moi j'ai tendance à préférer comme ça. Mais il vaudrait peut-être mieux suivre l'usage le plus commun.

    P.-S. J'ai trouvé aussi ce livre, qui a l'air intéressant : Récréations mathématiques

###raw>template_hook.ano_emploi###