2012-08-06 16 views
7

Sto facendo un gioco con un mondo che si estende all'infinito in ogni direzione. Ciò significa che puoi trovarti in posizione X:50, Y:50 o X:-50, Y:-50. Ma ... non posso farlo con un normale C# Lista ...Implementazione di array con indici negativi

Tutte le idee che mi è venuta in mente sembrano essere troppo complicato/inefficiente per lavorare ...

+0

Normalmente è implementato con la cura operatore modulo –

+0

di elaborare un po 'più – Entity

+0

Nevermind mio commento sopra, stavo pensando a qualcos'altro.Vedi invece la mia risposta.I computer –

risposta

14

Il metodo più semplice il modo per implementare una griglia infinita è utilizzare una matrice sparsa con un dizionario con una coppia x, y come chiave e i dati che si desidera memorizzare come valori. Questo è veloce, facile da implementare e compatibile con la memoria se la tua rete è scarsa.

Un altro modo è una griglia collegata (simile alla lista collegata, ma con puntatori a 4 direzioni), o un approccio a tessere per ridurre il sovraccarico della griglia collegata (una tessera è una griglia collegata di matrici NxN). L'implementazione di tiles è piuttosto complicata, ma è un buon compromesso tra memoria e performance per griglie molto dense.

Ma il mio approccio preferito è utilizzare la trasformazione dispari. Quindi gli indici dispari sono positivi, mentre i numeri pari sono negativi. Per trasformare dall'indice virtuale all'indice fisico, utilizzare la formula p = abs(v * 2) - (v > 0 ? 1 : 0) e convertire l'indice fisico in virtuale che si fa v = (p % 2 == 1 ? +1 : -1) * ((2*p + 3)/4). Questa relazione nasce perché c'è uno a uno e sulla relazione (biiezione) tra numeri naturali e numeri interi (0 <-> 0), (1 <-> 1), (2 <-> -1), (3 <-> 2), (4 <-> -2), (5 <-> 3), (6 <-> -3), .... Questo approccio è veloce, semplice ed elegante, ma non di grande memoria se si dispone di una griglia molto sparsa con elementi estremamente lontani dalla linea centrale.

+0

Penso che l'approccio pari-dispari funzionerà bene per quello che sto facendo . Grazie :) – Entity

1

Se non si dispone di un TON (sì, un numero di bit ...) di celle, è possibile utilizzare i dizionari. Che si combinano con un System.Drawing.Point come la chiave, e si ottiene una buona cosa sta succedendo:

Dictionary<Point,YourGridObject> myMap = new Dictionary<Point,YourGridObject>(); 

Edit: oltre al dizionario, ogni cella può avere un riferimento ad esso è celle adiacenti, in questo modo è possibile utilizzare il dizionario per andare direttamente "da qualche parte", ma poi navigare con l'adiacente. Ho usato in questo modo per implementare un algoritmo di pathfinder A * in una griglia esadecimale.

Edit 2: Ad esempio, se poi si desidera accedere a una coordinata specifica, si può semplicemente

var myTile = myMap[new Point(25, -25)]; 

Poi, si desidera ottenere la tessera East, è possibile

var eastTile = myTile.East; 

Il tuo oggetto griglia potrebbe anche implementare un metodo di offset in modo da ottenere la tessera 'West 2, North 5' di

var otherTile = myTile.Offset(-2, 5); 
+0

Quindi diciamo che volevo trovare quello che era in posizione '25',' -25' ... dovrei usare la funzione '.Where (...)'? – Entity

+0

Invece di aggiungere un riferimento alle celle adiacenti, potrebbe essere più semplice memorizzare il riferimento all'oggetto Punto, è possibile trovare i vicini aggiungendo/sottraendo/dalla coordinata del Punto. A seconda della struttura del programma, questa denormalizzazione potrebbe essere molto utile o complicare inutilmente. –

+0

@TheAdamGaskins Ho aggiunto alcuni elementi nella mia risposta, ma sono solo suggerimenti. Non so esattamente cosa vuoi fare con il tuo tile, ma il modo migliore per implementarlo dipende molto da come lo userai. – Tipx

0

Come utilizzare l'Elenco due sotto per le espansioni in due direzioni diverse?

0

Non sono sicuro se questo è più complicato di quanto si voglia gestire, ma hai considerato di utilizzare coordinate polari invece di cartesiano? Non ci sono numeri negativi in ​​quel sistema di coordinate. Mi rendo conto che la coverion è difficile all'inizio, ma una volta che ti avvolgi in testa, diventa una seconda natura.

0

È possibile utilizzare Dizionario, che ha tutte le funzionalità di un array, ad eccezione ovviamente di indici negativi.

0

I computer non possono memorizzare array infiniti. Ci deve essere un limite per l'array, ricorda che da qualche parte nel codice hai dichiarato una dimensione specifica durante l'inizializzazione dell'array. Forse lo ridimensionate da qualche parte, ma questo lascia comunque un intervallo di numeri da 0 a .. max.

Quindi, cosa si dovrebbe fare, scrivere una funzione che consente il posizionamento relativamente in tale mappa. Quindi memorizzi la tua mappa attuale [x, y] come posizione. E in grado di salire, avendo una funzione che aggiunge/substrati dalla posizione corrente in modo relativo. Ciò rende il tuo codice più facile da capire.

Se non si tratta di mappe di gioco ma di intervalli di numeri, diciamo i vettori è possibile creare un elenco di n punti o un dizionario 2D.

Lo sto postando qui, perché il tuo problema potrebbe portare le persone a scrivere codice errato.

Aggiungendo anche per altre persone in situazioni in cui vi è un bordo attorno a una mappa (tipico nello scenario di gioco e manipolazione delle immagini. dove i dati vanno da [-1 .. larghezza + 1], basta quotarlo come [0 , larghezza + 2] quindi ciclo attraverso essa di partenza 'for (int x = 1; x < larghezza + 1; x ++)'?

Problemi correlati