Přidat otázku mezi oblíbenéZasílat nové odpovědi e-mailem Ako vyriešiť tento problém s funkciou v JS [hra]

Zdravím, pracujem na svojej hre v JS a potreboval by som radu ohľadom toho ako vyriešiť jeden problém.
V hre na ktorej pracujem je objekt ktorý chcem aby fungoval ako "elektrina".. Nastavite si kable a potrebujem vyriešiť to aby hra vedela ako tie kable pôjdu za sebou aby sa aktivovali.. Obrazok ako vyzerá "elektrina" od páčky ktorá to aktivuje.. goo.gl/YvfLzC

To čo chcem dosiahnut je ak stlacite pačku bude tento "obvod" vyzerat nejako takto.. aby sa kazdemu bloku nastavila hodnota "active" na 1.. napriklad.. goo.gl/9w8qqG

Ako to robím teraz by teoreticky malo fungovať ale hádže mi to error na každom prehliadači z dôvodu volania funkcie vo funkcii veľa krát..

Ked stlacim páčku{
abcd(0,x - 48,direction);
abcd(2,x - 48,direction);
abcd(3,x - 48,direction);
abcd(0,x - 48,y,direction);
abcd(1,x - 48,y,direction);
abcd(5,x - 48,y,direction);
abcd(1,x + 48,y,direction);
abcd(2,x + 48,y,direction);
abcd(4,x + 48,y,direction);
abcd(3,x,y + 48,direction);
abcd(4,x,y + 48,direction);
abcd(5,x,y + 48,direction);
} //Funkcia abcd ma parametre 1. - akým smerom sa ten blok otaca.. je 6 smerov od 0 - 5
2. x pozicia ktora sa ma checknut 3. y pozicia ktora sa ma checknut 4. tu sa len vlozi stav na aký sa má zmenit ten blok
ak sa najde.. ci sa ma aktivovat alebo deaktivovat..

Takže po tom ako sa stlaci pačka, checknu sa vsetky mozne bloky ktore by mali fungovat a ak sa najdu tak sa aktivuju..
Ak sa ale najdu a aktivuju tak sa znova spusti tato funkcia abcd ale od toho bloku ktory sa aktivoval.. Opäť sa hladaju bloky ktore by
boli vhodne a mali by fungovat a ak sa najdu tak sa znova aktivuje funkcia.. Jednoducho povedane to hlada vsetky mozne cesty az kym sa nezastavi.. Tu som sa to pokusil chaoticky nakreslit.. goo.gl/zkq3qw

Tu je kod funckie abcd

            abcd = function(id,x,y,d){
				for(var i = 0; i < nblocks[0].length; i += 1){
					if(nblocks[0][i].direction == id){
						if(nblocks[0][i].position[0] == x & //position[0] je vlastne X
						nblocks[0][i].position[1] == y){ //position[1] je vlastne Y v arrayi kde su tieto bloky zapisane
							nblocks[0][i].active = d;
							if(id == 0){
								abcd(1,x + 48,y,d);
								abcd(2,x + 48,y,d);
								abcd(4,x + 48,y,d);
								abcd(3,x,y + 48,d);
								abcd(4,x,y + 48,d);
								abcd(5,x,y + 48,d);
							}else if(id == 1){
								abcd(0,x - 48,y,d);
								abcd(1,x - 48,y,d);
								abcd(5,x - 48,y,d);
								abcd(1,x + 48,y,d);
								abcd(2,x - 48,y,d);
								abcd(4,x - 48,y,d);
							}else if(id == 2){
								abcd(0,x - 48,y,d);
								abcd(1,x - 48,y,d);
								abcd(5,x - 48,y,d);
								abcd(3,x,y + 48,d);
								abcd(4,x,y + 48,d);
								abcd(5,x,y + 48,d);
							}else if(id == 3){
								abcd(0,x,y - 48,d);
								abcd(2,x,y - 48,d);
								abcd(3,x,y - 48,d);
								abcd(3,x,y + 48,d);
								abcd(4,x,y + 48,d);
								abcd(5,x,y + 48,d);
							}else if(id == 4){
								abcd(0,x,y - 48,d);
								abcd(2,x,y - 48,d);
								abcd(3,x,y - 48,d);
								abcd(0,x - 48,y,d);
								abcd(1,x - 48,y,d);
								abcd(5,x - 48,y,d);
							}else if(id == 5){
								abcd(0,x,y - 48,d);
								abcd(2,x,y - 48,d);
								abcd(3,x,y - 48,d);
								abcd(1,x + 48,y,d);
								abcd(2,x + 48,y,d);
								abcd(4,x + 48,y,d);
							}
						}
					}
				}
			};

Takto podľa toho čo si myslim by to malo fungovať.. no je to ako som pochopil dost dementne riesenie ked to hadze chybu.. zrejme nieje vhodne volat vlastnu funkciu vo funkcii niekolko-desat-krát..

Vedel by mi niekto poradiť ako by som to mohol efektivne spravit??
Bloky su zapisane normalne ako array takto

0
:
Block {position: Array(2), id: 13, damage: 120, direction: 2, active: 1}
Block {position: Array(2), id: 13, damage: 120, direction: 0, active: 1}
Block {position: Array(2), id: 13, damage: 120, direction: 4, active: 0}....
Předmět Autor Datum
Ta funkce neustále volá sama sebe, ale nevidím, že by to někde přestalo.
Wikan 12.09.2017 20:24
Wikan
Prestane keď už nebude ziaden blok nablizku
Papier 12.09.2017 21:07
Papier
A to je zajištěné jakou částí toho kódu?
Wikan 12.09.2017 21:13
Wikan
Nieje.. netuším ako to mám zaistit.. :/
Papier 12.09.2017 21:26
Papier
No to bys ale měl, když jsi ten kód psal.
Wikan 12.09.2017 21:34
Wikan
Prečo sa asi pýtam na poradni? halo.. len som sa spytal ludi o nejake rozumnejsie a efektivnejsie ri…
Papier 13.09.2017 14:32
Papier
Ale já fakt netuším, jakou máš datovou strukturu a teda ani, jak se z ní dá poznat, jestli má ta fun…
Wikan 13.09.2017 15:17
Wikan
Nechápem zadaniu. 6 smerov akým sa blok otáča - akých 6 smerov? Treba vôbec hľadať cestu, keď je ten…
moose 13.09.2017 04:56
moose
Tu je 6 smerov ako moze byt "kabel" otoceny.. https://i.imgur.com/B3Evh3D.png A ano musi to byt v t…
Papier 13.09.2017 14:30
Papier
Nerozumiem, čo znamená, že to musí byť takto. Konkrétne, čo znamená "takto", lebo z toho kódu sa prí…
moose 13.09.2017 16:19
moose
Ďakujem za rozsiahlu odpoveď! :) Konkrétne, čo znamená "takto" som myslel tak, že chcem aby progra…
Papier 13.09.2017 17:15
Papier
Ten veľký if pre každý typ "smeru otočenia" by sa pri rozumnejšom návrhu dal zjednodušiť a zefektívn… poslední
moose 13.09.2017 18:28
moose
Pokud dělám rekurzivní funkci (která volá sama sebe), tak VŽDY musí obsahovat podmínku pro ukončení…
dsa 13.09.2017 16:30
dsa

Prečo sa asi pýtam na poradni? halo.. len som sa spytal ludi o nejake rozumnejsie a efektivnejsie riesenie.. Tento spôsob sa inak spraviť nedá, nedá sa ukončiť funckia.. ak vieš ako, rad si to precitam.. ak nie tak nepotrebujem aby si ma tu poučoval o tom že čo by som mal vedieť a čo nie.. ďakujem.

Nerozumiem, čo znamená, že to musí byť takto. Konkrétne, čo znamená "takto", lebo z toho kódu sa príliš pochopiť nedá. Ten kód a použité štruktúry sú dosť chaotické.

Čo je v premennej nblocks? Vidím, že sa pracuje vždy s nblocks[0]. Vyzerá to, že v nblocks sú bloky toho obvodu? Znamená to, že v nblocks[1] je ďalší obvod?

Čo je id v bloku? Identifikátor bloku to nebude, keďže v uvedenom príklade majú všetky 3 bloky id 13. Je to identifikátor obvodu? Všetky bloky v nblocks[0] majú id rovné 13?

Čo je damage? Prečo ju tu vôbec dávate, keď nesúvisí s problémom?

Direction je predpokladám ten "smer otočenia", správne?

Active je predpokladám, či je daný blok obvodu zapnutý alebo nie.

Sú tie bloky v nejakom poradí? V príklade vidím za sebou 2, 0, 4, takže teoreticky by to mohlo znamenať, že obvod ide zdola-vľavo, sprava-dole, zhora-vľavo - je to tak?

Ak sú tie bloky umiestnené v poradí, stačí len ísť od začiatku a aktivovať ich. Ak sú náhodne, tak si spravte funkciu napr. getElectricalBlock(x, y), ktorý vráti daný blok na danej pozícii, nech sa v tom kóde dá orientovať.

Pomenúvajte premenné rozumnejšie, takto sa v tom nedá vyznať. Názov funkcie abcd, to má byť čo. Hádam toggleElectricity by bol vhodnejší názov. Argument id, keď blok má svoje id, je tiež mätúci. Argument d (a premenná direction), to sa dá snáď pomenovať ako activate a hneď bude zrejmé, o čo ide.

Problém je ten, že vždy idete oboma smermi. Takže ak by boli vedľa seba 3 horizontálne čiary a začínate strednou, tak v prvom kroku aktivujete tú vľavo aj tú vpravo. V druhom kroku aktivujete z oboch strán tú strednú a to sa tam potom zacyklí. Buď si budete pamätať pozície (posielať si ich v ďalšom argumente), ktoré ste už aktivovali a tie budete ignorovať, alebo si budete posielať smer, ktorým elektrinu aktivujete.

Ja by som na to šiel pri náhodnom usporiadaní tých blokov tak, že by som mal funkciu, ktorá berie pozíciu políčka (x, y) a zdrojovú pozíciu elektriny v políčku (zhora, sprava, zdola, zľava) a podľa "smeru otočenia" na danej pozícii vráti ďalšiu pozíciu políčka a zdrojovú pozíciu elektriny, ktorú treba skontrolovať. Pre každý "smer otočenia" a zdrojovú pozíciu elektriny je jednoznačné, kam elektrina ide ďalej, takže netreba prehľadávať celý priestor. Ak sú k dispozícii len dané bloky, tak slučka sa dá spraviť iba taká, ktorá prechádza cez všetky bloky. Takže si stačí zapamätať pozíciu prvého bloku a prerušiť hľadanie v prípade, že sa elektrina dostane znova na tú istú pozíciu.

Pri usporiadanom poradí blokov by som šiel len postupne a aktivoval ich. Bolo by to oveľa jednoduchšie. Možno by stálo zvážiť usporiadať tie bloky.

Ďakujem za rozsiahlu odpoveď! :)

Konkrétne, čo znamená "takto"

som myslel tak, že chcem aby program cestu našiel podľa "zákrut" toho káblu..
Nechcem to mať tak aby to bol čiste jeden blok a od neho sa všetky pustupne aktivovali..

Čo je v premennej nblocks?

nblocks[0] Je blok kábku/prúdu/elektriny/akokolvek to nazvete.. v tejto hodnote su ulozene vsetky bloky typu kablu..
nblocks[1] je hodnota do ktorej ukladam vsetky bloky Páčky ktora spusta obvody..
Je to v podstate to iste akoby som to mal ulozene ako elektrina = []; a packy = [];

Čo je id v bloku?

Zle som nazval "direction" vo funkcii ako ID.. nemal som to nazvat ako ID ale napriklad dir.. ID maju bloky tiez ale to sa v tejto casti
kodu vobec nevyuziva.. sluzi to na rozpoznanie toho aky hrac blok drzi v ruke.. A ano viem že ked je to teda 13ty blok, ako je mozne ze hodnota nieje nblocks[12], kde je tých 11 blokov pred týmto? Takto som začal oznacovat bloky len nedávno.. preto sa hodnota DOCASTNE volá "n"blocks ako new blocks.. ostatne bloky su ulozene VSETKY od 1-12 v JEDNEJ hodnote blocks = []; .. co bolo velmi neefektivne z dovodu optimalizacie.. ked som chcel zistit aky typ bloku to je, ci to je trava, kamen atd.. tak som musel prejst všetkými blokmi a postupne zistovat cez if či blok je tráva, kamen atd.. Casom prerobim vsetky bloky takto..

Čo je damage? Prečo ju tu vôbec dávate, keď nesúvisí s problémom?

Damage som uviedol len ako ukazku toho ako ukladam bloky v arrayi.. Sluzi to na nicenie blokov.

Direction je predpokladám ten "smer otočenia", správne?

ano

Active je predpokladám, či je daný blok obvodu zapnutý alebo nie.

ano

Nazov funkcie "abcd" som napisal len tu na poradni, realne v kode sa to vola inak, funkciu som "vyčistil" a teraz vyzerá oveľa krajšie.. Funguje v podstate rovnako no vyriesil som problem ako zistit ci daný blok uz bol aktivovany touto páčkou.. Ak ano tak ho bude ignorovat, uz to nehadze chyby..

Ďakujem! :)

Inak ak sa mozem spytat este.. dá sa nejako efektivnejsie zistit napriklad to
ze napriklad z tohto for

for(var i = 0; i < nblocks[0].length; i += 1){

nechcem for na všetky bloky ktore su v tomto arrayi ale len tie ktore maju napriklad active == 1...
samozrejme ze ak dam do for if tak to fungovať bude bez problemov.. ide mi skôr o to ci sa to da zapisat
nejak viac efektivne.. aby bola lepsia optimalizacia hry.. aby for bralo hned len tie bloky ktore maju danu hodnotu rovnu niecomu

nechcem

for(var i = 0; i < nblocks[0].length; i += 1){
if(nblocks[0][i].active == 1){......bla bla

chcem nieco taketo

for(var i = 0; i < nblocks[0]{activate == 1}.length; i += 1){
.
.
bla bla

Ten veľký if pre každý typ "smeru otočenia" by sa pri rozumnejšom návrhu dal zjednodušiť a zefektívniť. Ale keď to funguje, tak to už nechám tak.

Filtrovať pole sa dá napríklad takto:

nblocks[0].filter(function(x) { return x.active === 1})

V prípade, že stačí, aby to fungovalo v moderných prehliadačoch (alebo použijete TypeScript), tak sa dá použiť zápis so šípkou:

nblocks[0].filter(x => x.active === 1)

V prípade, že sa rozhodnete ukladať true/false (alebo hodnota active nemusí byť len 1, ale stačí že je "truthy", t.j. po pretypovaní na boolean to bude true), stačí:

nblocks[0].filter(x => x.active)

Tá funkcia môže byť samozrejme definovaná aj mimo, takže sa to dá zapísať pekne aj pre staršie prehliadače:

nblocks[0].filter(isActive)

Ak stači, aby to fungovalo v moderných prehliadačoch (alebo použijete TypeScript), môžete iterovať cez for..of:

for (const code of nblocks[0].filter(x => x.active)) { ... }

Prípadne môžete iterovať funkciou forEach:

nblocks[0].filter(x => x.active).forEach(...)

Efektívnosť si treba zmerať, ale tak odhadom bude ten základný cyklus for+if najrýchlejší. Ostatné budú asi pomalšie, aj keď možno prehľadnejšie.

Inak ak máte v nblocks rôzne typy blokov, tak by možno stálo za úvahu ich pomenovať, aby to bolo prehľadnejšie. Buď namiesto nblocks[0] použiť nblocks.electricity (resp. nblock.levers), alebo použiť konštantu namiesto indexu nblocks[BlocksType.ELECTRICITY] (resp. nblocks[BlocksType.LEVERS]).

Pokud dělám rekurzivní funkci (která volá sama sebe), tak VŽDY musí obsahovat podmínku pro ukončení ... jinak se bude volat "do nekonečna".

Pokud prohledávám nějaké "bludiště", musím si dělat "značky", abych poznal, kde už jsem byl.

Zpět do poradny Odpovědět na původní otázku Nahoru