Salut!
J'essaye d'écrire un solveur pour le jeu du solitaire en Haskell.
Vous savez, ce jeu ou des billes sont disposées en croix sur un plateau, le but étant de manger toutes les billes pour n'en avoir plus qu'une à la fin, si possible au milieu du plateau...
Je rencontre quelques problèmes de design, j'aimerais que vous me donniez votre avis!
Il me faut décrire le plateau, les coups possibles et l'arbre des jeux:
Ensuite, j'essaye de trouver tous les coups jouables à partir d'une position donnée.
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 --les emplacements: bille, trou ou interdit data Emplacement = B | T | I deriving Eq --le plateau data Plateau = Plateau { deconsPlat :: [[Emplacement]]} --les coups possibles newtype Coup = Coup { coup :: ([[Emplacement]], [[Emplacement]])} newtype ListeCoups = ListeCoups { coups :: [Coup]} --l'arbre des jeux data Tree = Null | Node Plateau [Tree] deriving Eq -- list of legal moves coupsLegaux = ListeCoups [ Coup ([[B, B, T]], [[T, T, B]]), Coup ([[T, B, B]], [[B, T, T]]), Coup ([[B], [B], [T]], [[T], [T], [B]]), Coup ([[T], [B], [B]], [[B], [T], [T]])] --the initial board initial = Plateau [[I, I, B, B, B, I, I], [I, I, B, B, B, I, I], [B, B, B, B, B, B, B], [B, B, B, T, B, B, B], [B, B, B, B, B, B, B], [I, I, B, B, B, I, I], [I, I, B, B, B, I, I]]
Je souhaite écrire:
qui me donne tous les plateaux possibles à partir d'un plateau et d'un coup donné.
Code : Sélectionner tout - Visualiser dans une fenêtre à part listePlat :: Plateau -> Coup -> [Plateau]
Cette recherche ressemble au problème classique du rechercher/remplacer d'une sous-chaine dans une chaine...
J'ai donc écrit:
Ces deux fonctions me parraissent bien compliquées pour le résultat... Mais je n'ai pas trouvé plus simple après beaucoup beaucoup de grattage de tête!! D'autres idées?
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 --recherche la première occurence de "find" dans "s" et la remplace par "repl" --si trouvé, retourne le résultat et le reste (pour application itérative) replReste :: Eq a => [a] -> [a] -> [a] -> Maybe ([a], [a]) replReste _ _ [] = Nothing replReste [] _ s = Just (s, []) replReste find repl s = if take (length find) s == find --si on trouve, on effectue le remplacement et on renvoie le reste then Just (repl ++ (drop (length find) s), drop (length find) s) --sinon on appelle récursivement en accumulant les caractères else case replReste find repl (tail s) of Nothing -> Nothing Just (a, b) -> Just ([head s] ++ a, b) --recherche les occurences de "find" dans "s" et les remplaces par "repl" --retourne la liste des chaines résultats (un remplacement à chaque fois). repls :: Eq a => [a] -> [a] -> [a] -> [[a]] repls rech rempl s = unfoldr (compl . (replReste rech rempl)) s where compl Nothing = Nothing -- on est obligé de compléter le début des chaines car sinon elles commencent par les caractères remplacés compl (Just (a,b)) = Just (take ((length s) - ((length a) + (length rech) -(length rempl))) s ++ a, b)
Ensuite je voudrais écrire la fonction:
Mais je bloque!
Code : Sélectionner tout - Visualiser dans une fenêtre à part listePlat :: Plateau -> Coup -> [Plateau]
Il faudrais appliquer "repls" à chaque lignes du plateau et tout reconstituer... Je ne trouve pas de solution élégante.
Partager