SCRABBLE FACILE...

Teclis01 Messages postés 1423 Date d'inscription mardi 14 décembre 2004 Statut Membre Dernière intervention 29 décembre 2012 - 11 nov. 2007 à 18:26
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

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
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>
benlaminefradj Messages postés 1 Date d'inscription vendredi 4 mai 2007 Statut Membre Dernière intervention 18 novembre 2007
18 nov. 2007 à 22:16
mot de passe pour le fichier Mysql
opossum_farceur Messages postés 147 Date d'inscription lundi 16 août 2004 Statut Membre Dernière intervention 14 novembre 2009
14 nov. 2007 à 22:12
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.
cs_spoonisback Messages postés 72 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 5 février 2010
13 nov. 2007 à 13:18
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 !!)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 23:55
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 ?
malalam Messages postés 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
12 nov. 2007 à 23:44
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 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 23:27
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 10839 Date d'inscription lundi 24 février 2003 Statut Membre Dernière intervention 2 mars 2010 25
12 nov. 2007 à 23:18
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!
audayls Messages postés 373 Date d'inscription samedi 9 juillet 2005 Statut Membre Dernière intervention 11 août 2008
12 nov. 2007 à 22:27
Je vais essayer de mon côté et je te tiens au courant ;-)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 21:57
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...
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 21:43
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...
audayls Messages postés 373 Date d'inscription samedi 9 juillet 2005 Statut Membre Dernière intervention 11 août 2008
12 nov. 2007 à 20:53
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 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 14:11
"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
12 nov. 2007 à 11:51
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 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 05:31
@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 ;)
neigedhiver Messages postés 2480 Date d'inscription jeudi 30 novembre 2006 Statut Membre Dernière intervention 14 janvier 2011 19
12 nov. 2007 à 05:16
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...
audayls Messages postés 373 Date d'inscription samedi 9 juillet 2005 Statut Membre Dernière intervention 11 août 2008
11 nov. 2007 à 23:16
"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
cs_spoonisback Messages postés 72 Date d'inscription vendredi 14 mai 2004 Statut Membre Dernière intervention 5 février 2010
11 nov. 2007 à 19:09
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
11 nov. 2007 à 18:45
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.
Teclis01 Messages postés 1423 Date d'inscription mardi 14 décembre 2004 Statut Membre Dernière intervention 29 décembre 2012 4
11 nov. 2007 à 18:26
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)
Rejoignez-nous