1. #1
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut Validation d'une chaîne au format FEN

    Bonjour !

    Je suis en train d'apprendre la programmation en Lua et pour me faire la main je me suis lancé dans le projet d'un validateur de chaîne au format FEN.

    Je vous propose ce que j'ai fait jusqu'à présent, en espérant que le sujet intéresse quelqu'un d'autre et soit l'occasion d'échanger des connaissances. Le code suivant utilise abondamment les patterns.

    Je n'ai pas eu le courage de commenter le code : je me suis contenté de marquer les endroits à compléter ou à améliorer. Merci d'avance pour vos suggestions.

    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
     
    -- Nom du fichier : validateur_001.lua
    -- Exercice de programmation en Lua
    -- Validation d'une chaîne de caractères au format FEN
    -- http://kirill-kryukov.com/chess/doc/fen.html
    -- Lua 5.2
     
    local exemple = "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1"
     
    t = {}
    for s in string.gmatch(exemple, "%S+") do
      t[#t + 1] = s
    end
    assert(#t == 6)
     
    assert(string.match(t[1], "%w+/%w+/%w+/%w+/%w+/%w+/%w+/%w+")) -- insuffisant
     
    local p
    p = "[bknpqrBKNPQR12345678]+"
    p = string.rep(p .. "/", 7) .. p
    assert(string.match(t[1], p)) -- un peu mieux mais toujours insuffisant
     
    t1 = {}
    for s in string.gmatch(t[1], "[^/]+") do
      t1[#t1 + 1] = s
    end
    assert(#t1 == 8)
    p = "[bknpqrBKNPQR12345678]+"
    for i = 1, 8 do
      assert(string.match(t1[i], p)) -- même chose si ce n'est que les séquences de
      -- caractères sont vérifiées une à une
    end
     
    assert((string.len(t[2]) == 1) and string.match(t[2], "[wb]"))
     
    assert(
      (string.len(t[3]) == string.len(string.match(t[3], "[kqKQ]+"))) or
      (t[3] == "-")
    )
     
    assert(
      (t[4] == "-") or
      (string.len(t[4]) == 2) and string.match(t[4], "[abcdefgh12345678]+")
    ) -- insuffisant
     
    assert((tonumber(t[5]) ~= nil))
     
    assert((tonumber(t[6]) ~= nil) and (tonumber(t[6]) >= 1))

  2. #2
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    Pour le quatrième champ ("en passant target square"), je n'étais pas loin de la solution. Je pense que le code suivant fait l'affaire (mais il y a peut-être mieux).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    assert(
      (t[4] == "-") or
      (string.len(t[4]) == 2) and
      string.match(string.sub(t[4], 1, 1), "[abcdefgh]") and
      string.match(string.sub(t[4], 2, 2), "[12345678]") -- ou même "[36]"
    )
    Reste à traiter le premier champ ("piece placement data").

  3. #3
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    Pour le premier champ, il me semble qu'on doit pouvoir faire quelque chose comme ça :

    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
    t1 = {}
    for s in string.gmatch(t[1], "[^/]+") do
      t1[#t1 + 1] = s
    end
    assert(#t1 == 8)
     
    function f(s)
      local n = 0
      for i = 1, string.len(s) do
        if string.match(string.sub(s, i, i), "[bknpqrBKNPQR]") then
          n = n + 1
        elseif string.match(string.sub(s, i, i), "[12345678]") then
          n = n + tonumber(string.sub(s, i, i))
        end
      end
      return n == 8
    end
     
    for i = 1, 8 do
      assert(f(t1[i]))
    end
    De cette façon on s'assure que chacune des huit sous-chaînes représente bien huit cases.
    Fichiers attachés Fichiers attachés

  4. #4
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    J'ai terminé mon programme. Il peut certainement être amélioré, mais semble fonctionner correctement.

    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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    -- Nom du fichier : validateur_003.lua
    -- Exercice de programmation en Lua
    -- Validation d'une chaîne de caractères au format FEN
    -- http://kirill-kryukov.com/chess/doc/fen.html
    -- Lua 5.2
     
    local exemples = {
      -- chaînes valides
      "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
      "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c6 0 2",
      "rnbqkbnr/pp1ppppp/8/2p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2",
      "4k3/8/8/8/8/8/4P3/4K3 w - - 5 39",
      -- chaînes non valides
      "rnbqqbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", -- qk --> qq
      "rnbqkbnr/pp1ppppp/8/2p5/4P3/8/PPPP1PPP/RNBQKBNR w KQkq c5 0 2", -- c6 --> c5
      "rnbqkbnr/pp1ppppp/8/3p5/4P3/5N2/PPPP1PPP/RNBQKB1R b KQkq - 1 2", -- 2p5 --> 3p5
      "4k3/8/8/8/8/8/4P3/4K3 W - - 5 39"  -- w --> W
    }
     
    function IsFEN(str)
      t = {}
      for s in string.gmatch(str, "%S+") do
      t[#t + 1] = s
      end
      if #t ~= 6 then
        return false
      end
     
      if (string.match(t[1], "k") == nil) or (string.match(t[1], "K") == nil) then
        return false
      end
     
      t1 = {}
      for s in string.gmatch(t[1], "[^/]+") do
      t1[#t1 + 1] = s
      end
      if #t1 ~= 8 then
        return false
      end
     
      function f(s)
        local n = 0
        for i = 1, string.len(s) do
          if string.match(string.sub(s, i, i), "[bknpqrBKNPQR]") then
            n = n + 1
          elseif string.match(string.sub(s, i, i), "[12345678]") then
            n = n + tonumber(string.sub(s, i, i))
          end
        end
        return n == 8
      end
     
      for i = 1, 8 do
        if not f(t1[i]) then
          return false
        end
      end
     
      if not ((string.len(t[2]) == 1) and string.match(t[2], "[wb]")) then
        return false
      end
     
      if t[3] ~= "-" then
        if string.len(t[3]) ~= string.len(string.match(t[3], "[kqKQ]+")) then
          return false
        end
      end
     
      if not (
        (t[4] == "-") or
        (string.len(t[4]) == 2) and
        string.match(string.sub(t[4], 1, 1), "[abcdefgh]") and
        string.match(string.sub(t[4], 2, 2), "[36]")
      ) then
        return false
      end
     
      if (tonumber(t[5]) == nil) then
        return false
      end
     
      if ((tonumber(t[6]) == nil) or (tonumber(t[6]) < 1)) then
        return false
      end
     
      return true
    end
     
    for i = 1, #exemples do
      print(IsFEN(exemples[i]))
    end
    Ce que j'aimerais bien maintenant, c'est pouvoir utiliser le script dans un programme en C ou en Pascal, mais ça pour le moment je ne sais pas le faire.

  5. #5
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    Citation Envoyé par Roland Chastain Voir le message
    Ce que j'aimerais bien maintenant, c'est pouvoir utiliser le script dans un programme en C ou en Pascal, mais ça pour le moment je ne sais pas le faire.
    En m'inspirant d'un exemple, j'ai réussi à faire un petit programme en C qui utilise mon validateur. Le programme se compile avec Borland C++ 5.5. J'ai inclus dans l'archive ci-jointe tous les fichiers nécessaires à la compilation.

    J'ai changé les valeurs de retour de ma fonction IsFen (remplacé false par 0 et true par 1) parce que je ne savais pas comment capter les valeurs booléennes dans mon programme.
    Fichiers attachés Fichiers attachés

  6. #6
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    Je viens de découvrir l'existence de ce tutoriel :

    Utiliser Lua dans du code C

  7. #7
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    Voici une version légèrement retravaillée du programme en C, cette fois pour MinGW-GCC 4.8.1.

    J'ai rétabli la valeur de retour booléenne pour la fonction IsFEN, ce qui donne la chose suivante dans le code C :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
      int result;
      ...
      result = (int)lua_toboolean(L, -1);
    Comme ça fonctionne, je suppose que c'est correct.

    Les fichiers *.h et *.a proviennent de cette archive.
    Fichiers attachés Fichiers attachés

  8. #8
    Rédacteur/Modérateur

    Avatar de Roland Chastain
    Homme Profil pro
    Enseignant
    Inscrit en
    décembre 2011
    Messages
    3 212
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Sénégal

    Informations professionnelles :
    Activité : Enseignant

    Informations forums :
    Inscription : décembre 2011
    Messages : 3 212
    Points : 11 725
    Points
    11 725
    Billets dans le blog
    5

    Par défaut

    C'est encore moi. Au cas où cela intéresserait quelqu'un j'ai posté dans le forum Pascal un exemple d'utilisation de mon script dans un programme... en Pascal.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Validation d'une chaîne FEN par les expressions régulières
    Par Roland Chastain dans le forum Delphi
    Réponses: 10
    Dernier message: 01/10/2014, 20h27
  2. Réponses: 2
    Dernier message: 25/03/2008, 11h39
  3. Valider une page au format xml
    Par Naruto_kun dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 27/07/2006, 16h35
  4. Formater une chaîne de caractéres
    Par kgadhi dans le forum Langage
    Réponses: 9
    Dernier message: 19/06/2006, 12h09
  5. Comment formater une chaîne ?
    Par AsmCode dans le forum MS SQL-Server
    Réponses: 3
    Dernier message: 13/01/2006, 14h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo