Pare de andar nas paredes!

16

Alguns gostos desonestos baseados em texto não permitem que você entre nas paredes e, se tentar, retrocede. Por que fazer isso quando você pode fazer o jogador se mover na direção válida mais próxima?

O desafio

Escreva um programa de função que, dada uma direção e uma grade de 3 por 3 caracteres, produz a mesma grade depois que o jogador der um passo.

Por exemplo,

9
#..
.@#
#.#

torna-se

#.@
..#
#.#

Entrada

  • A direção é dada por um único dígito de 1 a 9, cada um correspondendo a 8 direções cardinais e parado. Isso é derivado dos locais relativos dos números em um teclado:

    NW N NE
    .. \ | /
    ... 7 8 9
    W- 4 5 6 -E
    ... 1 2 3
    ../ \
    SW S SE
    
    No entanto, você também pode usar os números 123, 456, 789 em vez de 789, 456, 123. Em outras palavras, você pode trocar as 2 linhas ou os números superior e inferior, se assim desejar. Essas são as únicas 2 combinações de índice aceitáveis.

  • A grade 3 por 3 consistirá em 3 caracteres ASCII distintos e imprimíveis, representando piso, paredes e o player que podem ser percorridos. (Nos casos de teste, .é usado para piso, #s são paredes e @é o jogador)

  • Você pode escolher quais caracteres seu programa usa, mas você deve indicá-los em sua resposta e eles devem ser consistentes em várias tentativas.
  • O personagem que representa o personagem sempre estará no meio da grade 3 por 3, e a direção sempre estará entre 1 e 9 (incl.)
  • Você pode receber informações em qualquer ordem
  • A grade 3 por 3 pode ser inserida como uma matriz de caracteres, uma matriz de strings, uma string de 9 comprimentos ou outra alternativa razoável.

Resultado

  • Retorno de uma função ou saída para StdOut ou alternativa mais próxima
  • Espaços à direita e novas linhas são permitidos
  • Você deve usar as mesmas representações de caracteres que a entrada
  • Os mesmos formatos permitidos para entradas são permitidos para saídas

Como o jogador se move

Se a direção especificada estiver bloqueada por uma parede (por exemplo, se o exemplo acima tiver a direção 6), observe as 2 direções mais próximas:

  • Se uma (e apenas uma) direção estiver livre, mova o player nessa direção.
  • Se nenhuma direção estiver livre, observe as próximas 2 direções mais próximas (excluindo a direção 5). Se você deu a volta e não encontrou nenhuma direção aberta (jogador cercado por paredes), não mova o jogador
  • Se as duas direções estiverem abertas, escolha uma para mover aleatoriamente (embora não necessariamente uniformemente).

Se a direção dada for um 5, não mova o jogador

Casos de teste

( #= parede, .= piso, @= jogador)

Entrada:

9
# ..
. @ #
#. #

Resultado:

#. @
.. #
#. #


Entrada:

3
# ..
. @ #
#. #

Resultado:

# ..
.. #
# @ #


Entrada:

7
##.
# @ #
.. #

Resultado:

## @ ##.
#. # ou #. #
.. # @. #


Entrada:

5
...
. @.
...

Resultado:

...
. @.
...


Entrada:

2
###
# @ #
###

Resultado:

###
# @ #
###

Pontuação

Isso é , então a resposta mais curta em bytes vence.

MildlyMilquetoast
fonte
Não está usando yuhjklbn? DESCANSE EM PAZ.
Rɪᴋᴇʀ
Além disso, eu realmente não gosto muito da parte "escolha uma direção alternativa". É meio diferente da outra parte do desafio, que é "mover o jogador em uma direção e saída especificadas". Essa é apenas a preferência pessoal.
R
1
Esta parte é confusa: "Se nenhuma rota estiver livre, observe as próximas duas direções mais próximas".
Leaky Nun
1
Podemos atribuir um número em vez de um caractere ASCII para cada elemento, e então receber a entrada como uma lista bidimensional? Ou eles têm que ser cordas?
Scott Milner
2
Posso usar as instruções em 123;456;789vez de 789;456;123?
Leaky Nun

Respostas:

2

Pitão - 73 70 bytes

Kmsd"78963214"DPGJXXYt@K+xKQG\@4\.R?q/J\#/Y\#Jk=YwV5=GflTmPd(N_N)IGOGB

Tente

A entrada consiste em duas linhas:

1a linha: direção do movimento

2a linha: O tabuleiro (posições 123456789, com 123 sendo a linha superior)

Maria
fonte
3

JavaScript (ES6), 192 163 bytes

a=>b=>a[(a[4]=0)+--b]?(A=(c,d)=>c==b|(e=a[c])-(f=a[d])|!e?(a[c-b?(e?e<f:new Date&1)?c:d:4]=2,a):A(+g[c],+h[d]))(+(g="3016X2785")[b],+(h="1250X8367")[b]):(a[b]=2,a)

Notas

Esta função usa um formato de entrada especial. A primeira entrada é uma matriz de números inteiros ( 0para floor, 1para walle 2para player) representando o mapa. A segunda entrada é a direção (invertida): 1é noroeste, 2é norte, 3é nordeste, 4é oeste etc. As entradas devem ser fornecidas através da sintaxe de currying ( Z(a)(b)).

Casos de teste

Os mapas e direções foram modificados para se adequarem ao meu formato de entrada.

Z=
a=>b=>a[(a[4]=0)+--b]?(A=(c,d)=>c==b|(e=a[c])-(f=a[d])|!e?(a[c-b?(e?e<f:new Date&1)?c:d:4]=2,a):A(+g[c],+h[d]))(+(g="3016X2785")[b],+(h="1250X8367")[b]):(a[b]=2,a)

testcases = [
    [[1,0,0,0,2,1,1,0,1], 3],
    [[1,0,0,0,2,1,1,0,1], 9],
    [[1,1,0,1,2,1,0,0,1], 1],
    [[0,0,0,0,2,0,0,0,0], 5],
    [[1,1,1,1,2,1,1,1,1], 2]
]
for (test of testcases) {
    console.log(Z(test[0])(test[1]))
}

Lucas
fonte
1

Python 3, 120 104 153 176 175 bytes

def f(n,l):
 n-=1
 if n!=4and'.'in l:l[sorted(enumerate(l),key=lambda x:abs(x[0]%3-n%3+(x[0]//3-n//3)*1j)-ord(x[1])-__import__('random').random()/9)[1][0]],l[4]='@.'
 return l

Experimente online!

Este método obtém direção e lista de '.', '#' E '@'. Os índices começam com 1 a 9 (com 0 a 8 na lista). Então tem a forma

123 
456
789 

O método retorna uma nova lista com novas posições.

Está linha

sorted(enumerate(l),key=lambda x:abs(x[0]%3-n%3+(x[0]//3-n//3)*1j)-ord(x[1])-__import__('random').random()/9)

retorna uma lista deste tipo:

>>>n=7
>>> l=['#','#','#','.','@','#','.','#','.']
>>> sorted(enumerate(l),key=lambda x:abs(x[0]%3-n%3+(x[0]//3-n//3)*1j)-ord(x[1])-__import__('random').random()/9)
[(4, '@'), (8, '.'), (6, '.'), (3, '.'), (7, '#'), (5, '#'), (1, '#'), (0, '#'), (2, '#')]

Calculamos distâncias para liberar pontos e adicionamos aleatoriedade. Porque ord('#') <= ord('.') - 8 and ord('.') + 8 <= ord('@')podemos dizer que o mais próximo '.' para n = 7 (índice na lista) tem um índice de 8.

insira a descrição da imagem aqui

Exemplo:

>>> f(9, ['#','.','.','.','@','#','#','.','#'])
['#', '.', '.', '.', '.', '#', '#', '@', '#']
>>> f(3, ['#','.','.','.','@','#','#','.','#'])
['#', '.', '@', '.', '.', '#', '#', '.', '#']
>>> f(5, ['.','.','#','.','@','.','#','.','#'])
['.', '.', '#', '.', '@', '.', '#', '.', '#']
>>> f(7, ['#','#','#','#','@','#','#','#','#'])
['#', '#', '#', '#', '@', '#', '#', '#', '#']
>>> f(7, ['#','.','.','.','@','#','#','.','#'])
['#', '.', '.', '@', '.', '#', '#', '.', '#'] or ['#', '.', '.', '.', '.', '#', '#', '@', '#']
Кирилл Малышев
fonte
1) Isso não funciona nos casos de teste em que a direção que o jogador deseja seguir é ocupada e a posição correta não é a primeira ','(como é o caso dos casos de teste 2, 3 e 5). 2) Seu formato de E / S não parece ser o mesmo da pergunta. Por favor, mencione seu formato de E / S.
Luke
Seu exemplo f(9, ...não funciona - ele coloca o caractere em 2, mas as posições mais próximas de 9 são 6 e 8; portanto, um deles deve ser escolhido aleatoriamente (também não há aleatoriedade no seu código). Além disso, ele deve contornar o perímetro, encontrando o próximo mais próximo, então f(9,list("####@#.##"))deve colocar o personagem no único local possível (7 aqui).
Jonathan Allan
Obrigado por apontar erros. Para mim, a notícia é que o código l [4], l [l.index ('.')] = '. @' E l [l.index ('.')], L [4 ] = '@'. são diferentes
Кирилл Малышев
@ JonathanAllan, no começo eu não entendia bem as regras. Espero poder corrigir o código corretamente.
Кирилл Малышев
Ainda não está correto, não. 1. o exemplo f(9, ...deve retornar list("#....##@#")(porque 8 é gratuito e próximo a 9). 2. Algo como f(9,list("####@.#.#"))deve ter alguma chance de retornar list("####..#@#")(nem sempre list("####.@#.#")), conforme especificado "Se ambas as direções estiverem abertas, escolha uma para mover aleatoriamente".
Jonathan Allan