Bug fonction créée par mes soins

Résolu
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 - 29 déc. 2010 à 17:39
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 - 31 déc. 2010 à 12:40
Je développe un mini jeu de rôle.
Voici une esquisse de fonction permettant de voir si au cours d'un déplacement, un de mes personnages tombe sur un objet :


<? session_start();
include 'include/bdd.php';
mysql_query("SET NAMES UTF8");
function loot()
{
$pseudo = $_SESSION['username'];
$chance_not_to_loot = 0;// 5% de chance de looter par déplacement ! On peut éventuellement rajouter une boucle pour donner une chance de looter plusieurs objets mais bon, j'ai pas envie !
$chance_the_loot_is_conso = 1;// 10% de chance pour que ce soit un objet et // 90% de chance pour que ce soit un consommable
$lootable = rand(1,100);
if ($lootable > $chance_not_to_loot) 
{
$prerequis $recup mysql_query("SELECT xp FROM elfik_user WHERE username='$pseudo'") or die('Erreur SQL !'.$sql.'
'.mysql_error());
$fetch = mysql_fetch_array($prerequis); 		
$user_xp = $fetch['xp'];
$item_type = rand(1,100);
if ($item_type > $chance_the_loot_is_conso) 
{
$consommable=1;
$quality_rand= rand(1,1000);
if ($quality_rand <= 800)
{
$quality = "uncommon";
$backup = "It is ".$quality."... Maybe you should keep it, a vendor will certainly buy it...";
}
elseif ($quality_rand > 800 AND $quality_rand<= 950)
{
$quality = "rare";
$backup = "It is ".$quality." ! It looks great !!!!";
}
elseif ($quality_rand > 950 AND $quality_rand<= 995)
{
$quality = "epic";
$backup = "It is ".$quality." ! Hell yeahhh !";
}
elseif ($quality_rand > 995)
{
$quality = "legendary";
$backup = "It is legen wait for it ... dary, LEGENDARY ! Motha fucka !!!!!!";

}
$items_lootable = mysql_query("SELECT name FROM T_items WHERE quality='$quality' AND (item_lvl > ('$user_xp' - 300) AND item_lvl <= ('$user_xp' + 300))") or die('Erreur SQL !'.$sql.'
'.mysql_error());
}
else
{
$consommable=1;
$backup = "It looks disgusting!";
$items_lootable = mysql_query("SELECT name FROM T_items WHERE item_lvl > ('$user_xp' - 300) AND item_lvl <= ('$user_xp' + 300) AND consommable='$consommable'") or die('Erreur SQL !'.$sql.'
'.mysql_error());
}//seuil de tolérance entre xp requis de l'objet et xp du joueur de 300XP (300 de moins et 300 de plus) !


$total = mysql_num_rows($items_lootable);
$item_looted_rand = rand(0,$total - 1);
while ($afficher = mysql_fetch_array($items_lootable))
{
$item_name = $afficher[$item_looted_rand];
}
//Faire un array avec les objets potentiels et faire un rand à partir de ces objets
$compte_rendu = "You found " .$item_name. ". ".$backup." Do you want to keep it ?"; // Le joueur veut-il garder l'objet ?

}
else
{
$compte_rendu = "What a beautiful day today, isn't it ?"; // Pas de loot
}
echo $compte_rendu; // On renvoit le compte rendu !
return $item_name; //On renvoit le nom de l'objet looté
}
loot();
?>



Bon alors tout se passe à peu près comme je veux, d'ailleurs si vous avez des critiques ou un moyen d'optimiser ça, je suis un gros noob en programmation :p, seul problème je pensais utiliser "$afficher = mysql_fetch_array($items_lootable)" un peu comme un array numéroté de php, et faire un random pour définir in fine, le nom de l'objet trouvé en affichant par exemple $afficher[1] (le 1 correspondant au résultat du random, seulement parfois cela fonctionne parfois non... Est-ce que vous voyez une erreur quelque part ?

L'erreur provient-elle de ma bdd ou bien le mysql_fetch_array ne fonctionne pas comme un array numéroté ?


PS : Les pourcentage établis au début ne correspondent pas avec les commentaires, c'est pour tester la fonction plus en détail !

9 réponses

TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
30 déc. 2010 à 14:46
Salut,

L'erreur provient-elle de ma bdd ou bien le mysql_fetch_array ne fonctionne pas comme un array numéroté ?

Aucun des deux. La réponse est que tu n'as pas très bien compris ce que renvoie mysql_fetch_array().

Je cite la doc :
mysql_fetch_array — Retourne une ligne de résultat MySQL sous la forme d'un tableau associatif, d'un tableau indexé, ou les deux

Sachant que par défaut c'est les deux.

Bref, à chaque appel de mysql_fetch_array() sur uen ressource MySAL valide, ça te retourne une ligne d'un tableau associatif dont les clés correspondent au nom et numéros des champs de ta table, et les valeurs à al valeur de ces champs pour l'entrée courante. Ici tu sélectionne donc un champ aléatoire, ce qui n'est pas ce que tu veux faire. Ce que tu veux c'est une entrée aléatoire.

Une correction rapide et moche vite fait sans tester :
<?php
      $total = mysql_num_rows($items_lootable);
      $item_looted_rand = rand(0,$total - 1);
      $item_list = array();
      while ($afficher = mysql_fetch_array($items_lootable))
        {
          $item_list[] = $afficher[$item_looted_rand];
        }
      $item_name = $item_list[$item_looted_rand]['name'];
?>
3
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 1
30 déc. 2010 à 15:52
Merci, ce post est un doublon mais je tiendrai compte à l'avenir de ta science :-)

J'ai trouvé une solution plus optimisée je crois : je fais dans ma requête un ORDER BY RAND() LIMIT 1 !

Ca me renvoit une seule requête (limit 1) aléatoire (ORDER BY RAND()) !

Voilàààà :-)
0
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 1
30 déc. 2010 à 15:53
D'autre part, si t'as quelque chose à me conseiller pour otpimiser cette fonction, bon elle est pas très grosse mais je suis ouvert à tout conseil !
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
30 déc. 2010 à 16:01
J'ai trouvé une solution plus optimisée je crois : je fais dans ma requête un ORDER BY RAND() LIMIT 1 !

C'est en effet bien plus efficace et surtout bien plus élégant, après si j'ai gardé ton ancienne méthode c'est surtout par intérêt pédagogique afin que tu puisse mieux comprendre le fonctionnement de mysql_fetch_array() que tu avais du mal à maîtriser.

D'autre part, si t'as quelque chose à me conseiller pour otpimiser cette fonction, bon elle est pas très grosse mais je suis ouvert à tout conseil !

Avant de penser performant il faut penser élégant, et là ya pas mal de travail à faire ^^ Au fait, pour moi elle est bien grosse ta fonction.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 1
30 déc. 2010 à 19:37
Bien, aide moi à rendre plus élégante ma fonction dans ce cas, elle est obligatoirement de cette taille c'est primordial dans mon apply.

Enfin je sais pas si tu comprends à quoi ça correspond.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
30 déc. 2010 à 22:41
Et bien pour faire plus élégant, plus maintenable etc, tu peux commencer par séparer les différentes couches logicielle. Ici la couche accès aux données (avec les fonctions mysql_*) est complètement mélangée à la couche métier, c'est assez moche. En parlant de la couche accès aux données, on ne vois ici aucune abstraction sur le moyen de stockage, c'est pas cool si un jour tu en changes.

Enfin bref, ya pas mal de bons bouquins sur l'architecture logicielle ainsi que sur les design patterns (enfin là c'est plus pour faire de l'objet), c'est fort intéressant et je t'en recommande la lecture.
0
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 1
30 déc. 2010 à 23:47
Oui mais avec les 3 couches c'est plus du tout optimisé comme code si tu sépares complètement les requêtes du métier dans une fonction, elles vont se réaliser quoi qu'il advienne. Enfin il me semble, tandis que dans mon architecture, la requête n'intervient que si les randoms le permettent.

Il me semble dis moi si je me trompe, comme je te l'ai dis je suis autodidacte personne ne m'a rien appris et je développe sur le tas, mais il me semble que cette organisation bien que facilitant le codage de groupe nuit à l'optimisation de la charge serveur. Là encore, si tu me démontres le contraire je serai bien heureux d'appliquer ce système qui est somme toute bien plus lisible pour quelqu'un d'autre.
0
TychoBrahe Messages postés 1309 Date d'inscription samedi 31 janvier 2009 Statut Membre Dernière intervention 5 juin 2013 12
31 déc. 2010 à 01:29
Non, il n'y a aucun rapport entre la séparations en couches distinctes et le nombres de requêtes effectuées (enfin dans le cas présent). Et puis, si c'était vraiment le cas, faut-il vraiment chercher à faire des économies à tout prix ? Des projets mal organisés et de grande envergure j'en ai vu, et franchement ça fout les boulles. Bugs impossibles à retrouver, ajout de fonctionnalités extrêmement difficiles, cas foireux, failles de sécurité et j'en passe... on y gagne énormément à bien faire les choses, ça évite bien des tracas et au final ça risque même d'être bien plus performant.
0
monoski Messages postés 132 Date d'inscription mercredi 15 avril 2009 Statut Membre Dernière intervention 13 mai 2013 1
31 déc. 2010 à 12:40
Un exemple de séparation de couche en PHP serait : MYSQL -> Métier -> Affichage

Ce qui implique en l'espèce et à titre d'exemple que ceci :

$prerequis $recup mysql_query("SELECT xp FROM elfik_user WHERE username='$pseudo'") or die('Erreur SQL !'.$sql.'
'.mysql_error());


Soit interprété par le serveur quoi qu'il advienne alors que dans mon script cela ne sera fais que dans 5% des cas il me semble. Enfin peut être que j'ai mal compris l'articulation des 3 couches.
0
Rejoignez-nous