Diskuze: C# - automatické dosazování do špatného pole

C# .NET .NET (C# a Visual Basic) C# - automatické dosazování do špatného pole American English version English version

Avatar
Petr Stastny
Redaktor
Avatar
Petr Stastny:

Zdravím, mám problém. Píšu appku, která obsahuje 2 rozměrné pole o délce několika desítek až stovek. Abych to vykresloval (zatím to dělám prozatímně do console) lépe a bez toho problikávání, když to až moc často clearuji, rozhodl jsem se použít SetCursorPosition. Jenže mám problém.

Při každém vykreslení porovnávám pole a zjišťuji, které prvky se liší a pouze ty vykresluji. Po každém vykreslení do dalšího pole uložím stav, takže to je takhle:

  1. Změním pole
  2. Vykreslím to, co je rozdílné s kontrolním polem
  3. Překopíruju pole do kontrolního pole
  4. Opakuji

Jenže když změním pole, změní se i kontrolní pole, samo! Bez jakéhokoli setteru nebo něčeho podobného. Přikládám části kódu:

// ...
private MapObject[,] map;
private MapObject[,] mapThatWas;
// ...


// Zanasim do pole:
map[x, y] = mapObject;  // Po projiti TOHOTO radku se zanese hodnota nejen do [ map ], ale i do [ mapThatWas ]
// ...
DrawMap();



// DrawMap:

for (int x = 0; x < map.GetLength(0); x++)
            {
                for (int y = 0; y < map.GetLength(1); y++)
                {
                    // If there was no change
                    if (map[x, y] == mapThatWas[x, y])
                        continue;

                    if(x == 15 && y == 20) { }


                    Console.SetCursorPosition(x, y);

                    if (map[x, y] == null)
                        Console.Write(' ');
                    else
                        Console.Write(map[x, y].mapChar);
                }
            }
            mapThatWas = map;

Ještě něco: Toto se děje, až když měním hodnoty pole podruhé, při prvním dosazení to funguje bez problémů.

 
Odpovědět 7. října 21:05
Avatar
Honza
Člen
Avatar
Honza:

No jasně, protože map[x, y] = mapObject; ti udělá to, že do pole map uloží referenci na mapObject. Jinými slovy máš pořád jeden mapObject ale máš na něj reference v obou polích. A tedy pokud změniš hodnotu v jednom poli, ukáže se ti nový hodnota i ve druhém poli.
Řešením je nepř. vytořit nový objekt MapObject a naplnit ho daty z kontrolního pole. Ale celkově ta implementace mi příjde trochu divoká.

Navíc nevím jak je přesně myšlený řádek map[x, y] == mapThatWas[x, y] Pokud to má být kontrola toho zda se rovnají např. souřadnice v mapObject tak to ti fungovat nebude. Tak jak to máš napsané projde jen v případě, že obě pole ukazují na stejný objekt v paměti, ale neporovnáváš jejich hodnoty.

Akceptované řešení
+20 Zkušeností
+1 bodů
Řešení problému
Nahoru Odpovědět 7. října 21:20
Snadnou cestou se daleko nedostanete, je tam velká tlačenice...
Avatar
Petr Stastny
Redaktor
Avatar
Odpovídá na Honza
Petr Stastny:

Ok, dik. V podstate chci zjistit, jestli se ten dany radek v poli zmenil, nebo ne, abych ho znovu nevykresloval zbytecne. Neporadil bys mi, jak to co nejlepe udelat? :-)

 
Nahoru Odpovědět 7. října 21:28
Avatar
Petr Stastny
Redaktor
Avatar
Petr Stastny:

Nebylo by nejjednodussi si udelat pole integeru, do ktereho jenom budu ukladat souradnice pri kazde zmene pole a po vykresleni to pole promazu? Nebo mas jiny napad? :-)

Editováno 7. října 21:30
 
Nahoru Odpovědět 7. října 21:30
Avatar
Honza
Člen
Avatar
Odpovídá na Petr Stastny
Honza:

No ono záleží na tom co si představuješ pod pojmem

chci zjistit, jestli se ten dany radek v poli zmenil

Znamená to že je v obou polích uložena jiná instance proměnné a shodují se nějaké souřadnice na mapě, nebo chceš kontrolovat že obě pole ukazují na ten samý objekt? :)

Nahoru Odpovědět 7. října 21:46
Snadnou cestou se daleko nedostanete, je tam velká tlačenice...
Avatar
Petr Stastny
Redaktor
Avatar
Odpovídá na Honza
Petr Stastny:

Chci zjistit, na kterých souřadnicích jsou v polích různé objekty a na kterých jsou stejné.

Taky mě napadlo, že bych si při každé úpravě pole někam uložil souřadnice, kde bylo něco upraveno. Ke konci bych projel ty souřadnice a vypsal. Myslíš, že je to dobré řešení?

 
Nahoru Odpovědět 7. října 22:24
Avatar
Marian Benčat
Redaktor
Avatar
Marian Benčat:

V okamžiku, kdy chceš trackovat efektivně změny, bys měl zapřemýšlet nad "identitou objektu" .. třeba takovým typickým příkladem je Bod v 2D prostoru (v 2D poli).. pokud tomu bodu zmenim souradnici, uz to neni ten samy bod...

Ty chceš možná něco podobného? V tom okamžiku bys měl přemýšlet o Immutable objektu..

To ti zaručí právě to, že pokud bys chtěl editovat objekt, tak musíš vytvořit nový.. Díky tomudle se ti zmení ta reference... jinak to ani nejde. Udělej si tedy ten prvek toho pole immutable.. jsi schopný tedy před každým "tickem" udělat kopii předešlého pole a pak po "ticku" (po provedených změnách) projet to nové pole a porovnat jen reference.. pokud zjistis ze se zmeni, tak zaneses zmeny.. pseudo kod:

List<ImmtableObject> oldList = ....

tick() {
  List <ImmutableObject> newList = oldList.Copy();
   DoChanges(newList);

  for(int i=0; i<newList.Count; i++) {
     if (newList[i] != oldList[i]) // doslo k nejake zmene, prekreslit
     {
       redraw(newList[i]);
     }
   }
   oldList = newList;
}
 
Nahoru Odpovědět  +1 8. října 11:16
Avatar
Luboš Běhounek (Satik):

Místo classy pro reprezentaci MapObjectu můžeš použít struct, takže se ti to bude chovat tak, jak čekáš - kdykoliv někam pošleš MapObject, pošle se tam kopie jeho hodnoty a ne reference.

Nahoru Odpovědět  +1 8. října 11:28
:)
Avatar
Marian Benčat
Redaktor
Avatar
Odpovídá na Luboš Běhounek (Satik)
Marian Benčat:

A když už používáš struct, tak VŽDY ho udělej immutable, jinak se střelíš do nohy ;-)

 
Nahoru Odpovědět  +1 8. října 11:44
Avatar
Petr Stastny
Redaktor
Avatar
Petr Stastny:

Ok diky vsem :-)

 
Nahoru Odpovědět 8. října 11:57
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.