2009-08-06 11 views
6

Estoy tratando de escribir un modelo que contenga organismos digitales. Dentro del modelo, supongo que el entorno debe ser una matriz fija de 2 d, pero cada celda debe contener una lista de los organismos que contiene. Intenté usar una matriz dentada, pero como el número de elementos ocupados varía bastante durante la ejecución del programa, necesito usar algo más flexible que una matriz. Intenté hacer una matriz bidimensional de la lista de tipos, pero estoy recibiendo errores con ella.Intentando hacer una matriz 2D de listas

List<Creature>[,] theWorld; 


    public Environment() 
    { 
     List<Creature>[,] theWorld = new List<Creature>[100,100]; 
    } 

    public void addCreature(Creature c) 
    { 
     for (int x = 0; x < 100; x++) 
     { 
      for (int y = 0; y < 100; y++) 
      { 
       theWorld[x, y].Add (c); 

      } } } 

este es el segmento en el que i estoy tratando de declarar la matriz al principio, como un tipo que mantiene listas (de los organismos), y más tarde intento agregar una criatura (c) para cada uno de las listas en cada elemento de la matriz.

cuando lo funciono i obtener Mensaje- el siguiente error

"una excepción no controlada del tipo 'System.NullReferenceException' en HGT_sim_2.exe

Información adicional: Referencia a objeto no establecida en una instancia de un objeto."

y la línea "Mundo [x, y] .Add (c);" está resaltado.

Si alguien puede decirme qué estoy haciendo mal, y aún mejor, una forma de solucionar el problema, sería increíble. gracias ain por adelantado!

+0

Usualmente viene primero y luego x cuando mapeo una matriz 2d, pero creo que el orden es subjetivo. Hacerlo y luego x dará una salida visual precisa, aunque desde la esquina superior izquierda. –

Respuesta

2

Aquí está la solución:

List<Creature>[,] theWorld; 


public Environment() 
{ 
    theWorld = new List<Creature>[100,100]; // Remove the type, you were creating a new list and throwing it away... 

    for(int x = 0 ; x < 100 ; x++) 
     for(int y = 0 ; y < 100 ; y++) 
      theWorld[x,y] = new List<Creature>();  
} 

public void addCreature(Creature c) 
{ 
    for (int x = 0; x < 100; x++) 
    { 
     for (int y = 0; y < 100; y++) 
     { 
      theWorld[x, y].Add (c); 

     } } } 
+0

¿Dónde está la solución? –

+0

Agregué un comentario para decirte, en el constructor. – ConsultUtah

+0

Eché de menos que necesita una nueva lista, aunque ... – ConsultUtah

0

Se ha creado el objeto vector que mantiene sus listas, pero no se ha creado la propia lista. Usted tendrá que hacer lo siguiente en su constructor:

for (int x = 0; x < 100; x++) 
    for (int y = 0; y < 100; y++) 
     theWorld[x,y] = new List<Creature>(); 

Otro problema: también estaban definiendo theWorld como una variable local en su constructor, lo que significa que su campo de theWorld en Environment no se ha inicializado, tampoco.

Sin embargo, 10,000 List s puede ser excesivo para lo que realmente necesita. Si su Entorno necesita realmente un Creature en cada punto, y algunas Criaturas pueden moverse a otros puntos (donde hay más de uno en un punto, entonces puede tener más sentido usar un Dictionary<Point, IList<Creature>> como su modelo en comparación con 10,000 listas.

public void Add(Creature c, Point at) 
{ 
    IList<Creature> list; 
    if (!theWorld.TryGetValue(at)) { 
     list = theWorld[at] = new List<Creature>(); 
    } 
    list.Add(c); 
} 

a continuación, puede aplicar Move y Remove métodos de manera similar. Además, tenga en cuenta que está agregando el misma criatura en cada punto, el cual (mayo) significa que hay una criatura en todos los puntos en su entorno. es probable que desee para crear un new Creature() para cada punto, si eso es lo que realmente está modelando.

+0

Parcialmente cierto, pero no funcionaría sin arreglar el código en el constructor – ConsultUtah

+0

Editado para incluir esa y otra sugerencia. – Jason

7

Toda su matriz contiene inicialmente muchos nulos. Es necesario crear en realidad las listas ...

for(int x = 0 ; x < 100 ; x++) 
    for(int y = 0 ; y < 100 ; y++) 
     theWorld[x,y] = new List<Creature>(); 

Personalmente, sin embargo, espero que esta será una manera costosa de hacer las cosas ...

Depende en parte de si el dato es "escasa "- es decir, ¿la mayoría de las células generalmente se toman? Un enfoque simple (pero posiblemente más eficiente), por ejemplo, sería usar algo como multi-mapa; es decir

Point pt = new Point(x,y); 
theWorld.Add(pt, someCreature); 

donde theWorld podría ser algo así como EditableLookup<Point, Creature> (usando EditableLookup<,> de "MiscUtil"). De esta manera, aún puede consultarlo por coordenadas, y tener varias criaturas en una coordenada, pero no tiene que asignar espacio para cada celda. Y debido a que funciona como un diccionario, todavía es rápido. No como rápido como una matriz plana, pero escalará a grillas más grandes (dispersas) ... por supuesto, si la grilla tiene criaturas en cada celda, podría ser más ¡cara! De ahí la necesidad de comprender tus datos.

+0

iba a decir algo similar, así que obtuvo mi voto positivo –

+0

PowerCollections contiene un MultiDictionary que ayudará a – ShuggyCoUk

+0

De hecho. Si no ha escrito su propio mapa múltiple en algún momento no lo ha estado intentando ;-p –

3

Debe inicializar cada miembro de su matriz, p.

for (int x = 0; x < 100; x++) 
    { 
     for (int y = 0; y < 100; y++) 
     { 
      theWorld[x, y] = new List<Creature>(); 

     } } 
+1

PD ... hágalo ANTES del código que ha publicado que se agrega a la lista ;-) –

+0

¡Encontré el uso de esto! :) ¡Gracias! – adeelx

0

Al hacer esto:

List<Creature>[,] theWorld = new List<Creature>[100,100]; 

va a crear una serie de referencias List<Creature>, pero están todas vacías (que apunta a null, no una lista válida). Es necesario para inicializar cada elemento individual:

for (int x = 0; x < 100; x++) { 
    for (int y = 0; y < 100; y++) { 
     theWorld[i,j] = new List<Creature>(); 
    } 
} 

Una vez que hayas hecho esto, podrás llamar .Add sobre los miembros individuales.

0

Lo estás haciendo casi correctamente. Su variable es una matriz 2D de List<Creature>. Ahora, List<Creature> es un tipo de referencia, por lo que la matriz se inicializa para contener null en todos sus miembros. Así obtienes el NullReferenceException. La línea

theWorld[x, y].Add (c); 

es básicamente equivalente a

null.Add (c); 

Todo lo que necesita hacer es inicializar todos los miembros para contener los casos de List<Creature>. La mejor forma de hacerlo sería en el constructor. Simplemente vuelva a escribirlo así:

public Environment() 
{ 
    theWorld = new List<Creature>[100,100]; 
    for(int x = 0 ; x < 100 ; x++) 
     for(int y = 0 ; y < 100 ; y++) 
      theWorld[x,y] = new List<Creature>(); 
} 

Ahora todas las operaciones funcionarán como se esperaba.

También tenga en cuenta que en su ejemplo está creando una variable local con el mismo nombre que el miembro de la clase. De esta forma, no inicializa el miembro de la clase en absoluto; permanece nulo.

+1

¿Un voto a favor? ¿Para qué? –

+0

No, idea.Usted dijo lo mismo que yo. Pero más comprensible ... – ConsultUtah

Cuestiones relacionadas