monoski
Messages postés132Date d'inscriptionmercredi 15 avril 2009StatutMembreDernière intervention13 mai 2013
-
29 déc. 2010 à 17:39
monoski
Messages postés132Date d'inscriptionmercredi 15 avril 2009StatutMembreDernière intervention13 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 !
TychoBrahe
Messages postés1309Date d'inscriptionsamedi 31 janvier 2009StatutMembreDernière intervention 5 juin 201312 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 :
TychoBrahe
Messages postés1309Date d'inscriptionsamedi 31 janvier 2009StatutMembreDernière intervention 5 juin 201312 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.
Vous n’avez pas trouvé la réponse que vous recherchez ?
TychoBrahe
Messages postés1309Date d'inscriptionsamedi 31 janvier 2009StatutMembreDernière intervention 5 juin 201312 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.
monoski
Messages postés132Date d'inscriptionmercredi 15 avril 2009StatutMembreDernière intervention13 mai 20131 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.
TychoBrahe
Messages postés1309Date d'inscriptionsamedi 31 janvier 2009StatutMembreDernière intervention 5 juin 201312 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.
monoski
Messages postés132Date d'inscriptionmercredi 15 avril 2009StatutMembreDernière intervention13 mai 20131 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.