SCRABBLE FACILE...

Messages postés
1423
Date d'inscription
mardi 14 décembre 2004
Statut
Membre
Dernière intervention
29 décembre 2012
- - Dernière réponse : boscoauhunier
Messages postés
6
Date d'inscription
lundi 10 novembre 2003
Statut
Membre
Dernière intervention
18 mars 2010
- 24 janv. 2010 à 07:53
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/44665-scrabble-facile

Afficher la suite 
Teclis01
Messages postés
1423
Date d'inscription
mardi 14 décembre 2004
Statut
Membre
Dernière intervention
29 décembre 2012
4 -
hum
if($data['long'] <= 7)//Pour les mots <= à 7 (7 lettres par tirage au Scrabble)
$taille = $data['long'];

tant qu'a faire hein ;)
Mon dieu ce que c'est lourd... huhu j'aime les boucles mais il y a des limites ^^
Heureusement que tu as pas 27 boucles imbriquées sinon tu n'aurais plus de lettres pour tes compteurs de boucle :p
Non franchement je vais pas être chiant sur le typage mais au moins des variables explicites ...ça mange pas de pain
Ensuite je me demande si il n'y a pas plus simple ... du genre...
$iLettres=count($_POST);
$sQuery='select mot from dico where';
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
substr($sQuery,0,strlen($sQuery)-3)); //on vire le dernier and
mysql_query($sQuery);
(je peux me tromper puisque c'est une idée a vif)
audayls
Messages postés
373
Date d'inscription
samedi 9 juillet 2005
Statut
Membre
Dernière intervention
11 août 2008
-
Salut,
Je ne pense pas que ta méthode soit bonne Teclis01. Il se peut que tes 7 lettres ne puissent pas faire un mot de 7 lettres.

Ce qu'il faudrait faire, je pense vu la taille de la table, c'est deja d'améliorer la requête MySQL. Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres.
Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée.

Pour finir tu pourrais classer les mots possible en les classant selon les points qu'ils rapportent.
cs_spoonisback
Messages postés
72
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
5 février 2010
-
Salut
Heu...débutant je suis...bon c'est pas que je suis contre vos idées, mais y'a des trucs que je pige pas en fait..!

En fait Teclis01, je n'ai pas trouver d'autre moyen que l'imbriquage de boucle pour chercher tous les mots : 7 et inférieurs à 7 lettres. POur la suite de ton code...j'ai rein compris...désolé...je vois que tu a fabriquer un autre type de query, c'est à partir du 'foreach' que je pige pas..;
Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire...

Merci encore de ne pas m'avoir flagellé !!!
audayls
Messages postés
373
Date d'inscription
samedi 9 juillet 2005
Statut
Membre
Dernière intervention
11 août 2008
-
"Merci encore de ne pas m'avoir flagellé !!!" Bah pourquoi tant de haine ? XD
Regarde dans tes MP c'est noël avant l'heure =P
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Salut,

audayls : "Ensuite pour analyser les mots en selectionner ceux qui peuvent fonctionner, tu peux fortement simplifier ton code en utilisant la class "STRING ITERATOR" récemment postée."
=> Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?

audayls : "Au lieu de selectionner tous les mots il faudrait uniquement selectionner les mots contenant au moins une des 7 lettres."
=> Pour ça, il pourrait être pertinent de trier les lettres du tirage par ordre croissant de fréquence dans le vocabulaire français. Puisqu'il y a peu de mots avec Z, mais beaucoup plus avec E, si on trouve un Z, on limite au maximum les résultats, et ainsi de suite.

Teclis01 : "
foreach($_POST as $sNameInputLettre=>$sLettre{
$sQuery.=" mot=%'$lettre%' and";
}
"
=> J'aime pas trop. Je préfère utiliser implode(), c'est plus propre, et certainement plus rapide puisque c'est une fonction C.
Ca donnerait :
$sQuery = implode(' AND ', $_POST);
1 seule ligne au lieu d'une boucle... Je crois que y'a pas photo.

Mais je crois effectivement qu'une requête avec des AND n'est pas judicieuse.

Et avec une regexp dans la requête SQL, on devrait pouvoir faire des choses intéressantes...
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
@spoonisback :
"Audalys, je suis d'accord pour faire une requete qui contient au moins une des lettres mais, je ne vois pas quelle requete faire..."

Quelque chose qui ressemble à ça ?
// $lettres est un tableau des lettres du tirage du genre $lettres = array('a', 'e', 'n', 'b', 'o', 'j', 'n');
$motif = '(' . implode('|', $lettres) . ')';
$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'(%s)\' GROUP BY mot', $liste_lettres);

On peut faire une requête qui sort les mots qui ont deux lettres du tirage :
$motif = str_repeat('('.implode('|', $lettres).')', 2);

$sql = sprintf('SELECT mot FROM dico WHERE mot REGEXP \'%s\' GROUP BY mot', $liste_lettres);

Avec autant de lettres qu'on veut, même. Le seul problème, c'est que la requête ne tient pas compte d'une utilisation précédente d'une lettre.
Ainsi, si le tirage contient un seul E, la requête s'en cogne et sort tous les mots qui contiennent un E, ou deux, ou trois...

En répétant le motif de recherche 3 fois avec les lettres données en exemple, j'obtiens 4308 résultats sur la table que tu fournis, contre plus de 42000 s'il n'est recherché qu'une seule fois.
Par contre, le temps de traitement...

Affichage des enregistrements 0 - 29 (4 308 total, traitement: 0.9857 sec.)

Après, pour épurer ça, un FilteredIterator ça devrait faciliter le travail. Mais en terme de performances... Ca devrait déjà être mieux que ton script d'origine ;)
audayls
Messages postés
373
Date d'inscription
samedi 9 juillet 2005
Statut
Membre
Dernière intervention
11 août 2008
-
Aque Salut Neigedhiver =)

"Ouhaaaaaaaa alors elle peut vraiment servir à quelque chose !?" J'arriverai bien à lui trouver une utilité à ta classe parce que perso je la trouve chouette XD

Sinon je suis assez content car le code que j'ai envoyé par MP contient pas mal de tes recommandations =P
J'effectue une recherche dans la base de donnée en enlevant toutes les lettres qui ne sont pas parmis les 7 lettres (grâce à un REGEXP), puis je trie les résultats en vérifiant si on a assez de lettres pour former le mot.

Bon je n'ai pas utiliser FilteredIterator (puisque ce code n'est pas une classe) mais c'est vrai que celà aurait été plus pratique =P

Par contre je ne comprends pas ton exemple avec la fréquence d'apparition de lettre... Comment peut-on faire celà ?
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
"Par contre je ne comprends pas ton exemple avec la fréquence d'apparition de lettre... Comment peut-on faire celà ?"
Ben justement, je cherche aussi...
On pourrait faire une regexp avec toutes les possibilitées permutations sans répétition des lettres (ça fait 7! , soit 5040). Je pense pas que ce soit pertinent...

Peut-être que la base de données telle qu'elle est conçue ne permet pas d'optimiser à mort le traitement.
Je suis en train de penser que si les mots étaient stockées sous forme d'anagrammes, les lettres de ces anagrammes étant par ordre croissant, ça pourrait peut-être faciliter les choses. Il faudrait alors deux tables, une pour les anagrammes, une pour les mots (à un même anagramme peut correspondre plusieurs mots)
Ainsi le mot bonjour serait associé à l'anagramme bjnoour
salut et talus => alstu
A partir de là, la fonction native de recherche de MySQL en texte intégral (AGAINST) pourrait permettre de faire de bonnes choses (mais j'ai pas trop creusé, donc je me gourre peut-être complètement)
http://dev.mysql.com/doc/refman/5.0/fr/fulltext-search.html
http://dev.mysql.com/doc/refman/5.0/fr/fulltext-query-expansion.html
audayls
Messages postés
373
Date d'inscription
samedi 9 juillet 2005
Statut
Membre
Dernière intervention
11 août 2008
-
Hum pas mal l'idée de l'anagramme ^^ Mais je ne sais pas si la recherche MySQL en texte intégral sera interessante puisqu'elle effectue une double recherche...

A la rigueur on peut utiliser les anagramme avec une recherche de type REGEXP du genre "a{0,1}d{0,1}e{0,2}i{0,1}r{0,1}v{0,1}" cela permettra de récupérer uniquement les mots ayant tes lettres en bonne quantité.

Enfin faudrais bencher pour savoir si c'est AGAINST ou REGEXP qui remporte le concours parce que j'en ai aucune idée XD
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Cette regexp sort tous les enregistrements... Puisqu'ils correspondent tous... Si aucune lettre demandée n'est présente, ils sont quand même retournés...

Vais faire quelques tests avec AGAINST, histoire de voir...
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Bon en fait, MATCH(...) AGAINST(...) n'est à utiliser qu'avec des mots à chercher dans des phrases, des textes entiers...
En plus, il faut que le moteur soit MyISAM, la recherche FULL-TEXT ne fonctionne pas avec une table InnoDB...
Moi, je cale...
audayls
Messages postés
373
Date d'inscription
samedi 9 juillet 2005
Statut
Membre
Dernière intervention
11 août 2008
-
Je vais essayer de mon côté et je te tiens au courant ;-)
malalam
Messages postés
10844
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
Hello,

je m'incruste :-)
Moi je pense qu'en l'état, avec une simple liste de mots, on ne peut pas s'en sortir facilement et surtout rapidement.
L'idée de Neige sur les anagrammes est une bonne idée.
Mais il y a mieux je pense. Il faut représenter le dico sous forme d'arbre.
Par exemple : talus et tasse commence par la même syllable (ta, pour ceux qui n'auraient pas suivi ;-)).
On aurait donc un chemin t -> a -> l...
ou t -> a -> s...
Difficile de représenter un arbre ici hein...mais bon, la racine est la même pour les deux mots, et leur chemin se sépare vers d'autres feuilles à partir de la 3ème lettre.
salut et talus ne sont du coup plus du tout sur le même chemin.
Par contre, cela permet d'une part d'économiser beaucoup de place, et d'autre part cela accélère les traitements ! il suffit de commencer par chercher les débuts possible pour chaque lettre, puis d'avancer et d'abandonner (ou d'afficher si on a un mot complet) en fonction des lettres suivantes.
Je pense que c'est rapide, en tous cas dans un langage applicatif...
Par contre cela impose de se passer de base de données (je me vois mal représenter un arbre avec une bdd relationnelle).
C'est un algorithme connu, écrit il y a fort longtemps...et si c'était efficace il y a fort longtemps, il y a des chances pour que ça le soit toujours ;-) Il me semble d'ailleurs que c'était pour le scrabble!
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Au scrabble, on peut aussi rajouter des lettres avant et après. Autour donc. Parfois, on connait les lettres du milieu.

ENTENDU => MALENTENDUES

Donc l'idée de l'arbre, ouais, mais c'est applicable dans ce cas là ?

Perso, c'est pas que le jeu de scrabble m'intéresse à développer en PHP, mais je trouve que la problématique est fichtrement intéressante.
malalam
Messages postés
10844
Date d'inscription
lundi 24 février 2003
Statut
Modérateur
Dernière intervention
2 mars 2010
17 -
Tout dépend du but : non ce n'est pas -facilement- applicable dans ce cas-là. cet algo ne trouve pas tous les mots, clairement. Mais il en trouvera beaucoup, et au fil de l'avancement du jeu, il en trouvera de plus en plus (parce que plus on avance dans le jeu, plus il est difficile de placer un mot ne commençant ni ne terminant par une lettre déjà placée sur le plateau de jeu).
Enfin, ce cas là est tendancieux en fait lol...
si j'ai "entendu" et que je veux faire "malentendues", il le trouvera sans doute si on fait du backward.
Ce qu'il ne trouvera sans doute pas c'est à partir de "entendu", placer "malus" sur le "u".
Mais encore une fois, tout dépend de comment on le gère. On peut partir à gauche ou à droite...ou les deux (en fait il faut faire les deux, il faut faire du backward). Ca n'a pas vraiment d'importance.
Il est facile dans le 1er cas, de partie de "entendu" et d'arriver à "malentendues" : je vérifie à gauche mon chemin : lentendu, j'ai le "l". Je continue "alentendu", j'ai le a. je continue...malentendu, j'ai le m. Je vérifie si le chemin peut continuer : à gauche, non. A droite ; j'ai le e..j'ai le s. Evidemment, on fera sans doute les deux (gauche - droite) alternativement...c'est à tester.
neigedhiver
Messages postés
2483
Date d'inscription
jeudi 30 novembre 2006
Statut
Membre
Dernière intervention
14 janvier 2011
13 -
Plusieurs choses quant à ce que tu dis...

Effectivement, le fait que ton algo ne trouve pas tous les mots peut être vu comme une limitation. J'ai bien dit, PEUT, parce que c'est proche de ce que fait l'humain : rares sont les personnes capables de trouver TOUS les mots possibles avec un tirage en moins de XX secondes. Cependant, ce n'est peut-être pas ce qu'on attend d'un logiciel.

Tu dis qu'il ne trouvera pas malus à mettre sur le u de entendu. Certes. Mais était-ce bien là le but de cette source ? Si j'ai bien compris ce que j'ai vu, elle sert surtout à dire quels sont les mots possibles avec un tirage. Après, ce serait à l'humain de voir lesquels peuvent être placés, combien de points chacun rapporte, comment gêner l'adversaire en prenant le mot compte triple avant lui, etc.

Pour la construction de malentendu à partir de entendu, je ferais pas comme ça... Partant de ce mot, je cherche ceux qui existent qui le contiennent. Je vérifie pour chaque mot quelles sont les lettres nécessaires et une simple regex me dit si je les ai ou pas. Je ne comprends pas ton histoire d'alternance gauche/droite... C'est pas de la politique au moins ?
cs_spoonisback
Messages postés
72
Date d'inscription
vendredi 14 mai 2004
Statut
Membre
Dernière intervention
5 février 2010
-
Salut
Merci de tous ces commentaires.
Pour pouvoir completer un mot tel que entendu, il faudrai entrer tous les mots présents sur le plateau de jeux...ca risque d'etre assez bazard à la fin tout ça, ou alors il faut faire tout le jeux en php, avec le plateau, les lettres les cases triple..Etc...
Vu le newbie que je suis je pense que d'ici 15 ou 20 ans j'y serai arrivé ;-)
En fais j'ai fais ce code pour ma copine qui me saoule quand elle joue genre 'tu voit pas un mot avec ca !?' donc le but premier est en fait de 'tricher' au scrabble, mais si on devai faire un jeux complet en php, il ne faudrait surtout pas reprendre mon code, mais comme je l'ai dis ce n'était pas mon attention non plus !!
Merci encore de vos commentaire (PS: en tant que Newbie, l'utilisation des classes est encore floue pour moi !!)
opossum_farceur
Messages postés
148
Date d'inscription
lundi 16 août 2004
Statut
Membre
Dernière intervention
14 novembre 2009
-
Pour améliorer le rendement, il faudrait peut-être commencer par supprimer les doublons de la table; en entrant les lettres du mot "memoire", on obtient 3 fois "meme", 2 fois "memoire", 3 fois "mer", etc...
Ensuite, puisque seuls les mots comportants 7 caractères au plus sont intéressants, pourquoi ne pas les sélectionner directement dans ta requête :
SELECT * FROM `dico` WHERE length(mot)<8
Cas extrême, si ta table ne sert que pour cette requête, tu peux même envisager la suppression de tous les mots de longeur supérieure à 7 caractères.
benlaminefradj
Messages postés
1
Date d'inscription
vendredi 4 mai 2007
Statut
Membre
Dernière intervention
18 novembre 2007
-
mot de passe pour le fichier Mysql
boscoauhunier
Messages postés
6
Date d'inscription
lundi 10 novembre 2003
Statut
Membre
Dernière intervention
18 mars 2010
-
Hello
Qui a une solution pour supprimer les doublons dans les résultats et en compter le nombre. Merci par avance.
Cordialement à tous les phpistes.

CODE index.html ça peut intéresser quelqu'un !
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns= "http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SCRABBLE</title>
<STYLE>

.over{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFF00}
.down{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FF0000}
.out{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.btn{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input{text-align:center;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.nx{text-align:center;font-size:14;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFFFF}
textarea{text-align:left;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#F0F0F0;background:#000000}
HR {color:#FFFF00}
</STYLE>

</head>

<center>


<form action="scrabble.php" method="get">
<fieldset>
<legend>TIRAGE</legend>
<label> Entrez vos 7 lettres : </label>

Tirage minimum <select name="mini">

<option value='2'>2 lettres</option>
<option value='3'>3 lettres</option>
<option value='4'>4 lettres</option>
<option value='5'>5 lettres</option>
<option value='6'>6 lettres</option>
<option value='7'>Scrabble</option>

</select>
</fieldset>


</form>

</html>

CODE scrabble.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>SCRABBLE</title>
<style>
a:link {color: #FFEFB5; text-decoration: none}
a:visited {color: #000000; text-decoration: none}
a:hover {color: #ffffff; text-decoration: none}
</style>
<script type="text/javascript">
/*
SCRIPT DE L'EDITEUR JAVASCRIPT
http://www.editeurjavascript.com
*/
go_visibility = new Array;

function goblink()
{
if(document.getElementById && document.all)
{
blink_tab = document.getElementsByTagName('blink');
for(a=0;a
<STYLE>
.over{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFF00}
.down{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FF0000}
.out{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.btn{font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input{text-align:center;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#FFFFFF;background:#000000}
input.nx{text-align:center;font-size:14;font-weight:demi-bold;font-family:Verdana;color:#000000;background:#FFFFFF}
textarea{text-align:left;font-size:12;font-weight:demi-bold;font-family:Verdana;color:#F0F0F0;background:#000000}
HR {color:#FFFF00}
</STYLE>
</head>

<center>
<center>
<?php

include('conf/mysql.php');//Inclusion du script de connexion
$lettre[0] = $_GET['lettre1'];
$lettre[1] = $_GET['lettre2'];
$lettre[2] = $_GET['lettre3'];
$lettre[3] = $_GET['lettre4'];
$lettre[4] = $_GET['lettre5'];
$lettre[5] = $_GET['lettre6'];
$lettre[6] = $_GET['lettre7'];
$mini = $_GET['mini'];

?>

<?php

$maxi=8;
$qry = "SELECT DISTINCT mot FROM dico WHERE length(mot)<$maxi and length(mot)>=$mini order by length(mot) ";
$requete = mysql_query($qry) or die('Erreur MySQL :
' . mysql_error());
$nb_resultats = mysql_num_rows($requete);

$lettre1= $lettre[0];
$chaine1 = strtoupper("$lettre1");

$lettre2= $lettre[1];
$chaine2 = strtoupper("$lettre2");

$lettre3= $lettre[2];
$chaine3 = strtoupper("$lettre3");

$lettre4= $lettre[3];
$chaine4 = strtoupper("$lettre4");

$lettre5= $lettre[4];
$chaine5 = strtoupper("$lettre5");

$lettre6= $lettre[5];
$chaine6 = strtoupper("$lettre6");

$lettre7= $lettre[6];
$chaine7 = strtoupper("$lettre7");

echo'Recherche parmis '.$nb_resultats.' mots
avec les lettres

<table align="middle" valign="middle" border="0" cellspacing="0" cellpadding="0">----, <center>'.$chaine1.' </td>
<center>'.$chaine2.',
<center>'.$chaine3.',
<center>'.$chaine4.',
<center>'.$chaine5.',
<center>'.$chaine6.',
<center>'.$chaine7.'

| [javascript:history.go(-1) Retour] |';
echo'

Mots trouvés, Nombre de lettre, Points, ';
while($data = mysql_fetch_array($requete))
{

$taille = strlen($data['mot']);//Détermination de la longeur du mot
if($taille == 7)//Pour les mots de 7 lettres par tirage affiche scrabble
{
$scrabble=' scrabble ';
}
elseif($taille ! =7)
{
$scrabble=$taille; //affiche la taille
}

for($i=0;$i<$taille;$i++)
{
$dico[$i] = substr($data['mot'],$i,1);//Création de l'array du mot du dico
}
$nbjuste = 0;
for($j=0;$j<7;$j++)
{
for($h=0;$h<$taille;$h++)//Pour chaque lettre de chaque mot puis on compare a l'array envoyé en POST
{
if($lettre[$j] == $dico[$h])
{
$dico[$h] = \"0\";
$nbjuste = $nbjuste + 1;
$h = $taille + 1;
}
}

$mot= $data['mot'];

$chaine = strtoupper(\"$mot\");

if ($nbjuste==$taille)
{

echo '----
' . $chaine.', '.$scrabble.' , , ';//On crée une ligne de tableau par mot trouvé...
}

}
}

?>

</td></tr></table>

</html>