Pathfinding Roguelike


21

Pathfinding Roguelike

Il tuo compito sarà, dato un array bidimensionale degli elementi descritti di seguito, che rappresenta un dungeon, di produrre o restituire un singolo numero che rappresenta la quantità di pezzi d'oro che il ladro può raccogliere senza svegliare alcun mostro.

Gli elementi dell'array sono i seguenti:

  1. Gli spazi vuoti sono rappresentati da uno .o uno spazio, la tua chiamata;
  2. La posizione iniziale di Rogue è rappresentata da, ovviamente @,;
  3. Un pezzo d'oro è rappresentato da $;
  4. Le pareti sono rappresentate da #;
  5. I mostri sono rappresentati da personaggi della seguente espressione regolare: [a-zA-Z*&].

L'array non deve contenere alcun personaggio non elencato sopra, quindi puoi presumere che tutto ciò che non è un muro, uno spazio vuoto, il ladro o un pezzo d'oro sia un mostro.

Le regole per l'individuazione dei percorsi sono:

  1. Il ladro può attraversare solo celle vuote o celle contenenti oro;
  2. Ci vuole una svolta per spostarsi in una cella adiacente o diagonalmente adiacente;
  3. Raccogliere l'oro è istantaneo;
  4. Il ladro non può rimanere adiacente o in diagonale ad un mostro per più di un turno senza svegliarlo, il che è proibito;
  5. Il ladro può entrare nell'area di consapevolezza di un mostro un numero qualsiasi di volte, il mostro si sveglia solo se il ladro trascorre due turni consecutivi vicino ad esso.

Regole di input e output

È possibile ottenere l'input in qualsiasi formato ragionevole, incluso un array bidimensionale, un array piatto, una stringa o quant'altro. Se ti semplifica la vita, puoi anche prendere le dimensioni dell'array.

È garantito che il ladro non sarà vicino a un mostro all'inizio.

Un programma completo o una funzione vanno bene.

punteggio

Questo è , il punteggio è il conteggio dei byte della tua presentazione con meno essere migliore.

Casi test

Uso i punti per gli spazi vuoti qui a fini di leggibilità, se lo desideri puoi usare gli spazi (vedi sopra). Nota anche che questa è una pura coincidenza che il ladro si trova sempre nell'angolo in alto a sinistra, il tuo codice dovrebbe gestire anche qualsiasi altra posizione valida.

1)
@..
.$.
...  -> 1

Solo un test di sanità mentale.

2)
@....
...g$
.....  -> 0

Ancora una volta, un test di sanità mentale.

3)
@....
...$g
.....  -> 1

Il ladro può afferrare l'oro spostandosi da sinistra.

4)
@....g..
.......$
........
.....h..  -> 1

Il ladro può zigzagare tra i mostri, senza mai fermarsi per più di un turno vicino a ciascuno.

5)
@....z..
.......$
.....b..  -> 0

Le tattiche del precedente caso di test non funzionano qui: le aree di sensibilità dei mostri si sovrappongono.

6)
@$#.
###$
....  -> 1

Test di sanità mentale.

7)
@..#..
$.$g.$
...#..  -> 2

Idem.

8)
@#.d#$
$...##
e.....
..$...
##..$b
.#..g$  -> 3

Di tutto l'oro qui, solo tre possono essere raggiunti in sicurezza: l'oro vicino alla posizione di partenza può essere ottenuto spostandone verso il basso e poi di nuovo alla posizione di partenza. Per fuggire dall'angolo in alto a sinistra, il ladro deve muoversi due volte in diagonale in basso a destra. L'oro nel mezzo non rappresenta una sfida. L'oro esterno sorvegliato ge bpuò essere ottenuto spostandosi diagonalmente dal punto a destra dell'oro medio e poi indietro. Il resto non può essere ottenuto: l'oro in alto a destra è bloccato dai muri e l'oro in basso a destra richiede due turni nelle aree di sensibilità dei mostri.

I seguenti casi di test sono stati generosamente donati da mbomb007.

9)
  12345678
a @....g.D
b .......$
c ......#.
d .....h..  -> 1

Questo è difficile. Un percorso è b4-b5-c6-b7-c8-b8(grab).

10)
  12345678
a @....g.D
b .......$
c .......#
d .....h..  -> 1

Un percorso è [bc]4-c5-b6-c7-b8(grab).

11)
  12345678
a @....g.D
b ......#$
c .......#
d .....h..  -> 1

Il muro extra in realtà non cambia nulla, [bc]4-c5-b6-c7-b8(grab)è ancora una soluzione.


Dovresti aggiungere un esempio più grande e più complesso. Inoltre, quali sono le dimensioni minime e massime del sotterraneo? Il dungeon 1x1 è @un input valido?
mbomb007,


@ mbomb007 Ho aggiunto un nuovo esempio. Per quanto riguarda le dimensioni della griglia, penso che limitarlo ad almeno 3x3 sia ragionevole.
Michail,

@ mbomb007 Ti dispiace se modifico i tuoi esempi in? Una volta compresi, mostrano molto bene la logica.
Michail,

Sentiti libero. Questo è quello per cui li ho fatti. Si potrebbe anche notare che la rotazione di un caso di test non dovrebbe avere alcun impatto sul suo risultato.
mbomb007,

Risposte:


5

le soluzioni precedenti (parte di esse) si trovano nel contenitore piè di pagina nel collegamento tio (probabilmente sono più leggibili)

JavaScript (Node.js) , 883 436 411 360.345 311 byte

g=>g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A
P=(g,x,y,m={},p={},I=i=9,M={})=>{if(/[.$]/.test(c=(g[y]||0)[x])){for(;i--;)if(/^[^.@$#]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])){if(m[C])return
M[C]=1}for(;I--;)if(!p[(X=x+~-(I/3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return 1}return c=="@"}

Provalo online!

Spiegazione -

invece di passare dal giocatore al denaro sono passato dal caso al @. penso che dovrei essere più veloce perché so quando smettere di cercare (raggiungere la @) e quando cerchi denaro devi sempre muoverti finché non hai coperto tutti i punti (e i modi per raggiungerli). quindi l'algo è piuttosto semplice in questo modo - la funzione principale g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A: trova contanti -> se l'hai trovato -> inizia a cercare il giocatore -> se l'hai trovato -> l'incremento A ora consente di trovare il path finder aka P if(/[.$]/.test(c=(g[y]||[])[x]))basta controllare se la cella corrente è "speciale" -> se è così vogliamo tornare se è un giocatore. casi speciali: @ # (mostro)

for(;i--;) if(/^[a-zA-Z*&]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])) -> if my neighbor is a monster {if(m[C])return false -> and it already was in the previous turn - this path is not value M[C]=1} -> if not just add it to the neighbors monsters for(;I--;) if(!p[(X=x+~-(I / 3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return true iterare di nuovo i vicini - se non ero già lì (p è il percorso preso) continuare il percorso (chiamare P)


Bel golf! Alcune cose che ho notato: (1) il tuo codice ha spazi vuoti finali superflui sulla 2a e 7a riga e la maggior parte delle interruzioni di riga sono inutili (solo le righe 1 e 6 necessitano di un'interruzione) e I / 3ha spazio inutile. Elimina quello spazio bianco e il tuo punteggio è in realtà 324! (2) return true può essere return 1(un valore di verità) e return falsepuò essere semplicemente return(implicito undefined, un valore di falsità). (3) La regex ^[^.@$#]$per verificare la presenza di non-mostri è più breve di quella ^[a-zA-Z*&]$per verificare la presenza di mostri. Bel lavoro!
apsillers

Sì, lo so, posso renderlo molto più breve :)
DanielIndie,

@apsillers aggiornato alla soluzione degli spazi liberi :)
DanielIndie,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.