6
votes

Méthode plus simple / plus efficace de nichée si ... d'autre flux?

Je travaille actuellement sur un serveur d'émulation pour un jeu basé sur un client flash, qui possède un "système d'animaux de compagnie", et je me demandais s'il y avait une façon plus simple de vérifier le niveau d'animaux de compagnie spécifiés.

Code actuel: P>

public int Level
{
    get
    {
        if (Expirience > 100) // Level 2
        {
            if (Expirience > 200) // Level 3
            {
                if (Expirience > 400) // Level 4 - Unsure of Goal
                {
                    if (Expirience > 600) // Level 5 - Unsure of Goal
                    {
                        if (Expirience > 1000) // Level 6
                        {
                            if (Expirience > 1300) // Level 7
                            {
                                if (Expirience > 1800) // Level 8
                                {
                                    if (Expirience > 2400) // Level 9
                                    {
                                        if (Expirience > 3200) // Level 10
                                        {
                                            if (Expirience > 4300) // Level 11
                                            {
                                                if (Expirience > 7200) // Level 12 - Unsure of Goal
                                                {
                                                    if (Expirience > 8500) // Level 13 - Unsure of Goal
                                                    {
                                                        if (Expirience > 10100) // Level 14
                                                        {
                                                            if (Expirience > 13300) // Level 15
                                                            {
                                                                if (Expirience > 17500) // Level 16
                                                                {
                                                                    if (Expirience > 23000) // Level 17
                                                                    {
                                                                        return 17; // Bored
                                                                    }
                                                                    return 16;
                                                                }
                                                                return 15;
                                                            }
                                                            return 14;
                                                        }
                                                        return 13;
                                                    }
                                                    return 12;
                                                }
                                                return 11;
                                            }
                                            return 10;
                                        }
                                        return 9;
                                    }
                                    return 8;
                                }
                                return 7;
                            }
                            return 6;
                        }
                        return 5;
                    }
                    return 4;
                }
                return 3;
            }
            return 2;
        } 
        return 1;
    }
}


6 commentaires

Il n'y a aucun moyen que ce n'est pas une question de blague.


Si vous n'êtes pas au courant de cela (ne pas dire que vous n'êtes pas ... essayez simplement d'être utile), «Mise à jour de tout» n'est pas un processus onéreux. Cliquez avec le bouton droit sur "Expirience"> Refactor> Renommer. Bon d'aller ..... la plupart du temps (les vues ne seront pas mises à jour).


@George - ou quelqu'un lit TDWTF pour les échantillons de code ...


@Bradley: Vous n'avez même pas besoin de le faire. Il suffit de le mettre en surbrillance, de le retaper, puis une petite balise intelligente de dropdown apparaîtra à la fin de celui-ci et une des options sera de renommer l'entité. Les étiquettes intelligentes dans l'IDE sont géniales.


@ Cerceau bon appel! C'est pourquoi j'aime tellement. J'apprends de nouvelles techniques tous les jours. Cela ne fonctionne cependant que dans la définition de l'entité. Vous pouvez refroidir à peu près n'importe où dans votre code à l'aide de la boîte de dialogue Réfacteur.


@Bradley: Je suis bien conscient, je n'avais que je ne suis pas arrivé à le faire. Je viens de recevoir cet extrait d'un autre membre du projet. Eh bien ... récemment comparativement à la date du poste.


7 Réponses :


22
votes

Utilisez un SIEDLIST CODE> et itérairez-le jusqu'à ce que vous trouviez une valeur supérieure à la valeur que vous recherchez. Vous pouvez le faire en utilisant une simple itération comme dans la réponse que vous avez déjà acceptée. Ou il peut être fait avec élégance à l'aide de LINQ (à un léger coût de performance):

List<int> levels = new List<int> { 0, 100, 200, 400, 600 /* etc... */ };

int index = levels.BinarySearch(Experience);
int level;
if (index < 0)
{
    level = ~index;
}
else
{
    level = index + 1;
}
return level;


3 commentaires

En effet, ma solution aussi. +1


Définitivement. Ceci s'appelle une approche axée sur une table. Ce que vous avez eu un tas de données que vous avez écrit en tant que relevés de contrôle. Écrivez-le comme des données à la place.


Peut-être corriger l'orthographe de leur variable? Cela me semble tellement bâclé pour moi.



2
votes

Vous allez de la plupart inclus à la plupart exclusifs. Si vous allez dans l'autre direction, vous n'avez pas besoin de tout le nidification.

if (Expirience > 23000) // Level 17
  {
    return 17; // Bored
  }
  else if (Expirience > 17500) // Level 16
  {
    return 16;
  }
  else if (Expirience > 13300) // Level 15
  {
    return 15;
  }
  ...


3 commentaires

Alternativement, utilisez cette même APRACH avec une instruction de commutation au lieu de toutes les déclarations ... d'autre.


@Alleng: C # 'S Switch La déclaration ne prend pas en charge les gammes IIRC.


Vous n'avez même pas besoin du sinon



13
votes
int[] levelCutoffs = new int[] {0, 100, 200, 400, 600 /*...*/};

for (int level = 0; level < levelCuttoffs.size; ++level) {
    if (Experience < levelCuttofs[level])
        return level;
}
return levelCuttoffs.size;
Edit: altered to use  Bradley Mountford's suggestion.

9 commentaires

C'est probablement la manière la plus évolutive.


Au lieu de retourner 17 pour la relevette, vous voudrez probablement revenir de niveau cutttoff.size afin qu'il échoue de manière dynamique.


Oui, cela ressemble à la meilleure solution à mon problème pour le moment, car je n'ai besoin que de retourner des entiers, pas des cordes. Merci Tredubzedd.


La version de Lbushkin a O (journal n) de temps de recherche. celui-ci a O (n) qui est moins évolutif.


@David: C'est vrai si n est énorme. Pour les petites tableaux, une simple recherche linéaire pourrait être meilleure qu'une recherche binaire. Je ne pense pas qu'un jeu devrait offrir 1 000 niveaux. (Cela dit, il est plus sûr d'utiliser des fonctions intégrées que d'écrire une boucle explicitement vous-même).


@KennyTM: Le pire des cas pour la recherche binaire est toujours O (log n) tandis que le pire cas d'itération est O (n). Je pense que vous parlez de «insertion» sur le dessus de la construction d'un arbre de recherche binaire. Une fois les listes initiales créées, BinarySearch doit avoir la même performance ou mieux que l'itération, même avec un seul noeud. Je ne sais pas si la méthode BinarySearch reconstruit l'arborescence de chaque appel.


@David: Je ne parle pas de la "surcharge d'insertion". La liste est déjà triée afin qu'il n'y ait pas besoin de construire une BST. Je parle de la constante cachée et de la localité de l'accès à la mémoire.


Compte tenu du plus que je aurais toujours besoin de 20 niveaux (en raison d'une restriction du client dans le jeu), je suis sûr que cela suffira. À la recherche plus de vitesse que d'évolutivité.


@Scott: Soit fonctionnera bien depuis que le n est trivial, mais le point est Binaryssearch est plus rapide que l'itération, il échoue donc mieux pour la N.



4
votes

La suggestion de Mark est raisonnable. Vous pouvez également inverser l'ordre d'évaluation de l'expérience d'un-nid pour NI-NIVEZ LES IFS:

int[] levelThresholds = new[] { 100, 200, 400, 600, 1000, ..., 23000 };

int experience = 11403;
int index = Array.BinarySearch( levelThresholds, experience );
// returns either the index, or the 2's complement of the 
// first index greater than the value being sought
int level = index < 0 ? ~index : index+1;


3 commentaires

+1 BinarySearch est O (journal n) et compte tenu des marques de niveau sont corrigés, cela fonctionnera mieux que de simplement itération d'une liste des IFS ou d'une liste de marques de niveau.


-1. Il y a 17 articles, pas 17k. Je doute qu'il y aurait une différence de synchronisation pour cela qui pourrait apparaître avec moins de millions de "animaux chargés", si même alors. Il doit faire une classe Binarysearch, faire toutes sortes de vérification de l'exécution, faire plus classes, etc. Considérant qu'il le rend plus compliqué que la solution simple et claire, pourquoi le faire?


@Andrew Backer: Binaryssearch n'est pas une classe. C'est une méthode de tableau (ainsi que liste ) et elle ne crée aucun objet supplémentaire. En outre, toute la complexité est encapsulée dans la mise en œuvre .NET. Si nous devions écrire notre propre algorithme de recherche binaire, je suis d'accord avec vous - mais pourquoi ne pas utiliser quelque chose déjà fourni par la BCL? Gardez à l'esprit, une partie de la valeur des questions de réponse est que les personnes qui examinent cela à l'avenir peuvent aider à atteindre des solutions à leurs propres problèmes similaires. Donc, démontrer des approches alternatives a son propre mérite.



2
votes

Je prendrais que Mark Byers répondit plus loin. Puisque est légèrement déroutant (j'oublierais que INT est lequel) crée une liste triée de xxx

de cette façon, vous pouvez définir beaucoup plus qu'un nombre de points d'expérience requis à chaque niveau. Vous pouvez également attribuer un nom, c'est-à-dire «Uber Elite Super Niveau» et peut-être même un message de bienvenue personnalisé à chaque niveau.


0 commentaires

2
votes

Si l'algorithme d'expérience peut être réduit à une fonction, il doit utiliser le calcul fonctionnel, c'est-à-dire:

return
 (Expirience > 23000) ? 17 :
 (Expirience > 17500) ? 16 :
 (Expirience > 13300) ? 15 : 
 .. etc ..
 (Expirience > 100) ? 2 : 1;


0 commentaires

3
votes

Que diriez-vous d'une formule simple, basée sur une fonction logarithmique?

quelque chose comme xxx


0 commentaires