Je ne suis pas vraiment sûr que «labyrinthe» soit le terme correct. Fondamentalement, les utilisateurs démarrent dans un fichier unique Room
comportant 4 portes (N, S, E et W). Ils peuvent aller dans n’importe quelle direction et chaque pièce subséquente contient une autre pièce pouvant contenir de 1 à 4 portes menant à d’autres pièces.
Le "labyrinthe" est censé avoir une taille illimitée et se développer lorsque vous changez de pièce. Il y a un nombre limité de Rooms
disponibles, mais le nombre disponible est dynamique et peut changer.
Mon problème est, je ne suis pas sûr de la meilleure structure de données pour ce type de modèle
J'ai d'abord pensé à utiliser simplement un tableau d' Room
objets [X] [X] , mais je préférerais vraiment éviter cela, car l'objet est censé évoluer dans n'importe quelle direction et que seules les pièces "visitées" doivent être construites.
L’autre idée était de faire en sorte que chaque Room
classe contienne 4 Room
propriétés liées pour N, S, E et W et crée un lien vers la précédente Room
, mais le problème que je ne vois pas, c’est que je ne sais pas comment identifier si un utilisateur se rend dans une pièce a une pièce adjacente déjà "construite"
Par exemple,
--- --- ---------- | | | | Début 5 4 | | | | --- --- --- --- --- --- ---------- --- --- | | | | | | | 1 2 3 | | | | | | --- --- --- --- ----------
Si l'utilisateur quitte Start> 1> 2> 3> 4> 5, alors le Room
n ° 5 doit savoir que W contient la salle de départ, S est le local n ° 2 et, dans ce cas, ne doit pas être disponible, et N peut être un neuf Room
ou un mur (rien).
Peut-être ai-je besoin d'un mélange du tableau et des pièces liées, ou peut-être que je regarde cela de la mauvaise façon.
Existe-t-il un meilleur moyen de construire la structure de données pour ce type de "labyrinthe"? Ou suis-je sur la bonne voie avec mon processus de pensée actuel et manque-t-il juste quelques informations?
(Si cela vous intéresse, le projet est un jeu très similaire à Munchkin Quest )
Réponses:
Donnez les coordonnées de chaque pièce (le début serait (0,0)) et stockez chaque pièce générée dans un dictionnaire / hashmap par coordonnées.
Il est facile de déterminer les coordonnées adjacentes pour chaque pièce, que vous pouvez utiliser pour vérifier si une pièce existe déjà. Vous pouvez insérer des valeurs null pour représenter des emplacements où il est déjà déterminé qu'aucune pièce n'existe. (ou si ce n'est pas possible, je ne suis pas sûr que atm, un dictionnaire / hasmap séparé pour les coordonnées qui ne contiennent pas de salle)
la source
Room
pièce, cherchez les pièces adjacentes dans le dictionnaire et ajoutez leurs liens à l'Room
objet avant d'ajouter de nouvelles pièces aux côtés restants. Le seul moment où la recherche par le dictionnaire aurait lieu est lors de la création d'un nouvelRoom
objet, et non pas entre deux voyagesRooms
Room
objet. Si vous êtes dans la même pièce(x,y)
et que vous souhaitez parcourir le nord, vous consultez(x,y+1)
le dictionnaire et le créez s'il n'existe pas. Dictionnaire sont très lookups rapide,O(1)
.(x,y+1)
peut exister, mais ne pas être navigable depuis(x,y)
le nord. C'est-à-dire qu'un bord ne peut pas aller directement de(x,y)
à(x,y+1)
.Dans la plupart des cas, ce que vous décrivez ressemble à un graphique. Compte tenu de certaines de vos exigences (l'aspect croissant), je choisirais probablement une liste de contiguïté comme implémentation (l'autre option courante serait une matrice de contiguïté ).
Je ne suis pas sûr de la langue que vous utilisez, mais voici un bon tutoriel / explication avec les détails de l'implémentation d'un graphique implémenté avec une liste de contiguïté dans .NET .
la source
Quelques réflexions sur la mise en œuvre (j'ai pensé à Carcassonne qui présente un certain nombre d'aspects difficiles pour construire la matrice - c'était même une question d'entrevue que l'on m'avait déjà posée).
Certaines questions sont posées à cette structure:
Le problème avec les simples listes et graphiques
La difficulté avec les listes simples est qu’il faut parcourir la structure pour vérifier si quelque chose peut être placé à un endroit donné. Le système a besoin d’un moyen d’accéder à un emplacement arbitraire O (1).
Considérer:
Pour trouver l’information sur l’emplacement possible '?', Quand à 3, il faut parcourir tout le chemin pour aller à 4. La réponse de link avec des informations supplémentaires sur le nombre de nœuds sautés (de sorte que 3 soit lié à 4 avec un 'saut 1' supplémentaire) nécessite toujours des marches pour trouver la contiguïté de '*' à partir de 6 ou A.
Simple, grand, tableaux
S'il ne s'agit pas d'un nombre important, créez simplement un tableau de 2N x 2N et laissez-le là. Un tableau de 100 x 100 est 'seulement' 10 000 pointeurs et 50 objets. Index directement dans le tableau.
Cela pourrait être réduit à seulement NxN si des activités hors limites déplaçaient le tableau pour rester toujours dans les contraintes. Par exemple, si vous souhaitez ajouter une pièce qui submerge le tableau, demandez à la grille de décaler chaque élément d’une position afin qu’il n’y ait plus de débordement. À ce stade, la taille du monde pour 50 salles serait de 2 500 pointeurs et de 50 objets.
Tableaux et matrices clairsemés
Pour créer cela de manière plus optimale, examinez un tableau fragmenté dans lequel la majorité des éléments sont 0 ou nuls. Pour deux dimensions, il s’agit d’une matrice clairsemée . De nombreux langages de programmation ont différentes bibliothèques pour travailler avec cette structure. Si la bibliothèque se limite à des entiers, vous pouvez utiliser cet entier comme index dans un tableau fixe de pièces.
Mon approche préférée serait de disposer les pièces comme structure (pointeurs vers les pièces adjacentes et coordonnées) et que la pièce soit également un pointeur à partir d'une table de hachage hachée en coordonnées. Dans cette situation, demander quelle est la pièce [N / S / E / W] d'une pièce nulle, interrogerait la table de hachage. C'est d'ailleurs le format 'DOK' pour stocker une matrice fragmentée.
la source
Que dis-tu de ça..
Donnez à chaque cellule un lien vers chacun de ses voisins. Donnez à chaque cellule une sorte de nom (par exemple "0/0", "-10/0" (supposons que vous commenciez à 0,0)). Ajoutez un hachage contenant tous les noms. Lorsque vous essayez de passer à une autre cellule, vérifiez simplement que le voisin n'existe pas déjà dans le HashSet.
De plus, si vous créez une ouverture sur une autre pièce, cela signifie-t-il que les pièces existent? Vous créez donc un lien vers une pièce vide sans lien vers aucune pièce. Vous voudrez probablement aussi vérifier les nouvelles chambres des voisins. S'il en existe un et qu'il s'ouvrirait sur votre nouvelle pièce, ajoutez une porte à cette pièce.
HashSet = {0 | 0, 1 | 0, 2 | 0, 3 | 0, 0 | -1, 1 | -1 ....} 1,0: W = 0,0 / Porte; 1,0: N = 1,1 / vide; E = 2,0 / porte; S = 1, -1 / mur
Vous devez également vous assurer de donner à chaque nouvelle pièce au moins une porte non adjacente (vers une autre pièce) afin que le labyrinthe puisse croître dans cette direction.
la source
Ce que vous concevez ressemble beaucoup à un graphique.
Celles-ci sont souvent représentées par un ensemble d'états Q , un état initial q 0 ∈ Q et quelques transitions Δ . Donc, je vous suggère de le stocker comme ça.
La plupart des langues raisonnables ont à la fois des cartes et des ensembles.
la source
Vous pourriez envisager une liste chaînée 4 voies ...
Vous pouvez toujours utiliser un [] [] pour cela. La dynamique de croissance peut être lente, en particulier lors de l'ajout au début, mais peut-être pas si mal. Vous devriez profiler pour vérifier. Essayer de manipuler une liste ou une carte liée pourrait en fait être pire, et à un niveau constant plutôt qu'occasionnel.
Vous ne pouvez créer que des salles visitées en implémentant une évaluation paresseuse. Un objet peut contenir une pièce et ne pas construire cette pièce tant qu’il
room()
n’est pas appelé. Ensuite, il retourne simplement le même à chaque fois par la suite. Pas difficile à faire.la source
J'ai appris à le faire via le livre "Création de jeux d'aventure sur votre ordinateur". Si vous êtes prêt à fouiller dans le code BASIC (le livre est si vieux), allez lire ici:
http://www.atariarchives.org/adventure/chapter1.php
Pour le raccourci, ils ont un tableau de pièces, un élément de chaque tableau étant un pointeur vers une autre pièce où vous pouvez aller, 0 (je voudrais utiliser -1 ces jours-ci) pour indiquer que vous ne pouvez pas Va dans cette direction. Par exemple, vous feriez une structure de pièce (ou classe ou ce que vous avez)
Ensuite, vous pouvez avoir un tableau ou une structure de liste chaînée ou bien d’autre part vous souhaitez gérer vos salles. Pour un style de tableau (ou des vecteurs C ++), j'utiliserais ce code et les instructions contiendraient l'index de la pièce à laquelle elles sont liées; pour une liste chaînée, vous pouvez utiliser des pointeurs vers la pièce suivante.
Comme d'autres l'ont déjà dit, vous pouvez également le faire si vous devez générer de manière dynamique de nouvelles salles lorsque des personnes y entrent.
la source
N'essayez pas de résoudre tous les problèmes avec une seule structure.
Définissez votre objet room pour stocker des informations sur la pièce, pas ses relations avec les autres pièces. Ensuite, un tableau 1D, une liste, etc. peuvent croître à votre guise.
Une structure distincte peut contenir "l'accessibilité" - les pièces accessibles depuis la pièce dans laquelle je me trouve. Décidez ensuite si l'accessibilité transitive doit être un calcul rapide ou non. Vous voudrez peut-être un calcul de force brute et un cache.
Évitez l'optimisation précoce. Utilisez des structures très simples et des algorithmes stupides, faciles à comprendre, puis optimisez ceux qui sont utilisés.
la source