NetHack mínimo


64

NetHack é um jogo parecido com um roguel onde o jogador deve recuperar o Amuleto do Yendor do nível mais baixo da masmorra. Geralmente jogado via telnet, o jogo inteiro é representado com gráficos ASCII. O jogo é extremamente desafiador e requer conhecimento de muitas mecânicas do jogo para ter sucesso.

Para os propósitos deste desafio, suponha que o calabouço inteiro seja um nível único e apenas 5 × 16 caracteres. Além disso, suponha que este é um calabouço "seguro" ou que você está implementando apenas um protótipo - não haverá monstros, preocupações com a fome etc. Na verdade, você deve rastrear apenas a localização do personagem, do amuleto e do jogo terminará efetivamente quando o jogador chegar ao mesmo local que o amuleto.

Requisitos do desafio

  • Haverá uma masmorra 5 × 16 (nível único).
  • Dê ao jogador um local inicial (opcionalmente aleatório) e o amuleto um aleatório separado (diferente a cada vez que o programa for executado) começando dentro da masmorra. Ou seja, o amuleto não pode começar no mesmo quadrado que o jogador.
  • Aceite quatro teclas de entrada que movem o leitor um quadrado de cada vez (quatro direções cardinais). A leitura / processamento de outras entradas é permitida (uma função readline () que requer pressionar 'enter', etc).
  • Viajar para fora dos limites da masmorra não é permitido. Por exemplo, se o jogador estiver na borda direita da masmorra, pressionando a direita, não deverá fazer nada.
  • Após a geração inicial e após cada movimento, imprima o estado do jogo. Como esse é o código golf e a impressão é bastante desinteressante, ignore a contagem de caracteres para a função de impressão e a chamada de função, assumindo que não há alterações de estado . As células vazias devem ser mostradas como ponto ( .), amuleto como aspas duplas ( ") e caractere como símbolo ( @).
  • O jogo termina quando o jogador "descobre" o amuleto (chega ao mesmo quadrado)

Ganhando

Este é um desafio de código de golfe, o código mais curto para atender aos requisitos de uma semana a partir de hoje será declarado vencedor.

Exemplo

Aqui está um exemplo de solução em C # (ungolfed) para mostrar os requisitos básicos e a amostra de saída.

using System;

namespace nh
{
    class Program
    {
        static Random random = new Random();

        // player x/y, amulet x/y
        static int px, py, ax, ay;

        static void Main(string[] args)
        {
            px = random.Next(0, 16);
            py = random.Next(0, 5);

            // amulet starts on a position different from the player
            do { ax = random.Next(0, 16); } while (px == ax);
            do { ay = random.Next(0, 5); } while (py == ay); 

            print();

            do
            {
                // reads a single keypress (no need to press enter)
                // result is cast to int to compare with character literals
                var m = (int)Console.ReadKey(true).Key;

                // Move the player. Here standard WASD keys are used.
                // Boundary checks for edge of dungeon as well.
                if (m == 'W')
                    py = (py > 0) ? py - 1 : py;
                if (m == 'S')
                    py = (py < 5) ? py + 1 : py;
                if (m == 'A')
                    px = (px > 0) ? px - 1 : px;
                if (m == 'D')
                    px = (px < 16) ? px + 1 : px;

                // print state after each keypress. If the player doesn't
                // move this is redundant but oh well.
                print();

            // game ends when player is on same square as amulet
            } while (px != ax || py != ay);
        }

        static void print()
        {
            Console.Write('\n');
            for (int y=0; y<5; y++)
            {
                for (int x = 0; x < 16; x++)
                {
                    if (x == px && y == py)
                        Console.Write('@');
                    else if (x == ax && y == ay)
                        Console.Write('"');
                    else
                        Console.Write('.');
                }
                Console.Write('\n');
            }
        }
    }
}

A contagem total de caracteres é 1474, mas, ignorando as chamadas para a função de impressão e sua definição, a contagem final de caracteres é 896.

Saída quando o programa é executado:

................
...."...........
..........@.....
................
................

Saída (incluindo acima) depois que a tecla 'a' é pressionada duas vezes:

................
...."...........
..........@.....
................
................

................
...."...........
.........@......
................
................

................
...."...........
........@.......
................
................

10
Tenho a sensação de que isso será de interesse para @Doorknob.
Alex A.

10
Rogue é o jogo roguelike original em que um jogador deve recuperar o Amuleto do Yendor do nível mais baixo da masmorra. Por que não chamar isso de Rogue mínimo?
Gilles 'SO- stop be evil'

5
@ Gilles Por que não chamar isso de uma cobra mínima?
Casey Kuball 02/07/2015

26
Psshh, nenhum movimento diagonal? No yubnhjkl? Nem mesmo uma escada para subir depois de pegar o amuleto? : P ( furiosamente upvotes de qualquer maneira )
Maçaneta

2
@tolos: Ainda não estou claro o que conta como aleatório aqui. Não é realmente possível atender aos diferentes sempre que o programa for executado , se o programa for executado 80 vezes ... Especificamente, nesta resposta , o amuleto pode ocupar apenas 9 dos 79 locais possíveis. Isso conta?
Dennis

Respostas:


37

TI-BASIC, 42 41 38 36 35 bytes

Para a sua calculadora gráfica da série TI-83 ou 84+.

int(5irand→A                          //Randomize amulet position
6log(ie^(6→C                          //15.635 + 4.093i
Repeat Ans=A                          //Ans holds the player pos. (starts bottom right)
iPart(C-iPart(C-Ans-e^(igetKey-i      //Boundary check, after adjusting player position
prgmDISPLAY
End

----------
PROGRAM:DISPLAY
For(X,0,15
For(Y,0,4
Output(Y+1,X+1,".
If A=X+Yi
Output(Y+1,X+1,"¨
If Ans=X+Yi
Output(Y+1,X+1,"@
End
End

A direção que o jogador seguirá é uma função do código da tecla pressionada, mas quatro teclas que definitivamente funcionam são as seguintes na linha superior:

Key        [Y=]  [WINDOW]  [ZOOM]  [TRACE]  [GRAPH]
           -------------------------------------------
Key code    11      12       13               15
Direction  Left     Up     Right             Down

O amuleto começa em um dos cinco quadrados da primeira coluna e o jogador começa no canto inferior direito. Por exemplo, um arranjo possível é:

................
¨...............
................
................
...............@

Explicação

A posição do jogador é armazenada como um número complexo de 0+0ipara 15+4i, onde a parte real vai para a direita e a parte imaginária desce. Isso facilita a verificação fácil dos limites na parte superior e esquerda: simplesmente deslocamos o número levemente e arredondamos para zero. Por exemplo, se o deslocamento for 0.5e nossa posição for -1+3i(fora da tela à esquerda), a posição será corrigida para iPart(-0.5+3.5i)=0+3ionde deveria estar. Verificar os limites inferior e direito é um pouco mais complicado; precisamos subtrair o número de uma constante C, que é sobre 15.635 + 4.093i(é o menor que eu poderia encontrar entre 15+4ie 16+5i), arredondar, subtrair de Cnovo para virar o número de volta e arredondar novamente.

Quando uma tecla é pressionada, a posição do jogador não ajustado se move em 1 unidade em alguma direção, mas a parte inteira muda apenas quando certas teclas são pressionadas. Felizmente, as teclas que funcionam estão todas na linha superior. Abaixo está um gráfico das compensações nos casos em que as teclas 11, 12, 13 e 15 são pressionadas e quando nenhuma tecla é pressionada (Nenhuma pressão é o ponto dentro do quadrado central, fazendo com que as partes inteiras permaneçam inalteradas; as quatro teclas pressionam 'offsets' têm partes inteiras diferentes). Cé a cruz vermelha no centro do círculo.

insira a descrição da imagem aqui

Código antigo (42 bytes):

int(9irand→A                     // 0≤rand≤1, so int(9irand) = i*x where 0≤x≤8
1                                //set "Ans"wer variable to 1+0i
Repeat Ans=A                     
Ans-iPart(i^int(48ln(getKey-1    //add -i,-1,i,1 for WASD respectively (see rev. history)
Ans-int(Ans/16+real(Ans/7        //ensure player is inside dungeon
prgmDISPLAY                      //display on top 5 rows of the homescreen   
                                 //(for this version switch X+Yi with Y=Xi in prgmDISPLAY)
End

Limitações

Não há como escapar de um "caractere, portanto, cadeias com a "não podem ser geradas dentro de um programa. Portanto, isso usa a marca de trema em ¨vez de uma citação (se houvesse uma string já existente com uma marca de citação, eu poderia exibi-la). Para obter ¨e entrar @em um programa, é necessária uma ferramenta externa; no entanto, é válido TI-BASIC.


2
Apenas por diversão, criei esse trecho que coloca a diaerese e o símbolo @ em Str1 (em oposição a 'uma ferramenta externa'). Escolha a linha na parte superior que corresponde à sua calculadora, insira-a em um novo programa e execute-o com Asm (.
MI Wright

Ah, esqueci-me de codificar o código da máquina na calculadora. Não quero bater no meu com um erro de digitação, mas acredito que funcione.
precisa saber é o seguinte

44

CHIP-8 , 48 bytes

Isso pode não ser considerado legal, mas por que diabos não. Eu escrevi meu programa no CHIP-8, uma linguagem de programação baseada em bytecode para um console de jogos virtual. Você pode tentar o programa completo (99 bytes) no seu navegador usando um emulador / depurador que escrevi chamado Octo:

Captura de tela

http://johnearnest.github.io/Octo/index.html?gist=1318903acdc1dd266469

Um dump hexadecimal desse programa completo é o seguinte:

0x60 0x14 0x61 0x04 0xC4 0x3C 0xC5 0x08
0x22 0x36 0xF6 0x0A 0x22 0x52 0x40 0x00
0x12 0x16 0x46 0x07 0x70 0xFC 0x40 0x3C
0x12 0x1E 0x46 0x09 0x70 0x04 0x41 0x00
0x12 0x26 0x46 0x05 0x71 0xFC 0x41 0x10
0x12 0x2E 0x46 0x08 0x71 0x04 0x22 0x52
0x3F 0x01 0x12 0x0A 0x00 0xFD 0xA2 0x58
0xD4 0x54 0x22 0x52 0x62 0xFF 0xA2 0x5B
0xD2 0x34 0x72 0x04 0x32 0x3F 0x12 0x40
0x62 0xFF 0x73 0x04 0x33 0x14 0x12 0x40
0x00 0xEE 0xA2 0x5F 0xD0 0x14 0x00 0xEE
0xA0 0xA0 0x40 0x00 0x00 0x20 0x00 0xF0
0x90 0x90 0xD0

Você pode mover o player com as teclas ASWD ou 7589 no teclado CHIP-8 original. Se eu remover todo o código e dados para desenhar o plano de fundo e o player, recebo esse despejo de 48 bytes:

0x60 0x14 0x61 0x04 0xC4 0x3C 0xC5 0x08
0xF6 0x0A 0x40 0x00 0x12 0x12 0x46 0x07
0x70 0xFC 0x40 0x3C 0x12 0x1A 0x46 0x09
0x70 0x04 0x41 0x00 0x12 0x22 0x46 0x05
0x71 0xFC 0x41 0x10 0x12 0x2A 0x46 0x08
0x71 0x04 0x3F 0x01 0x12 0x08 0x00 0xFD

A forma completa e não-gasta do programa foi escrita em uma linguagem assembly de alto nível, da seguinte maneira:

:alias px v0
:alias py v1
:alias tx v2
:alias ty v3
:alias ax v4
:alias ay v5
:alias in v6

: main
    px := 20
    py := 4
    ax := random 0b111100
    ay := random 0b001000
    draw-board
    loop
        in := key
        draw-player
        if px != 0 begin
            if in == 7 then px += -4
        end
        if px != 0x3C begin
            if in == 9 then px +=  4
        end
        if py != 0 begin
            if in == 5 then py += -4
        end
        if py != 16 begin
            if in == 8 then py +=  4
        end
        draw-player
        if vf != 1 then
    again
    exit

: draw-board
    i := amulet
    sprite ax ay 4
    draw-player
    tx := -1
    i := ground
    : draw
    loop
        sprite tx ty 4
        tx += 4
        if tx != 63 then jump draw
        tx := -1
        ty += 4
        if ty != 20 then
    again
;

: draw-player
    i := player
    sprite px py 4  
;

: amulet  0xA0 0xA0 0x40
: ground  0x00 0x00 0x20 0x00
: player  0xF0 0x90 0x90 0xD0

Observe que os próprios bytes compilados são a linguagem de programação CHIP-8; o montador é simplesmente um meio mais conveniente de compor esses programas.


19
Ferramenta certa para o trabalho.
Dennis

6
+1 por me fazer perder muito tempo jogando seu jogo repetidamente.
Alex A.

4
@AlexA. se você quiser perder ainda mais tempo, tente o Cave Explorer . O movimento ASWD no mundo superior e o QE são usados ​​para redefinir / mover blocos nos níveis do jogo de plataformas.
#

4
Ótimo, bem, lá vai meu fim de semana.
Alex A.

11
Eu fiquei cético no começo, mas o Cave Explorer era divertido e o CHIP-8 existe há muito mais tempo do que eu imaginaria. Então acho que vou ter que aprender isso.

10

Python 3, 86 bytes

def d():
    import sys
    for y in range(5):
        line = []
        for x in range(16):
            line.append('@' if y*16+x == p else \
                        '"' if y*16+x == a else \
                        '.')
        print(''.join(line))
    print()
    sys.stdout.flush()

p=79;a=id(9)%p
while p-a:d();p+=[p%16<15,16*(p<64),-(p%16>0),-16*(p>15)][ord(input())%7%5]

Contando apenas as duas linhas inferiores e caindo d();.


Salvei outro byte iniciando o player no canto inferior direito (o "último" quadrado) e depois amostrando aleatoriamente os primeiros 79 quadrados.
Lynn

Opa, desculpe, consertado! Eu acho que não sou incrível em contar manualmente bytes. : <
Lynn

11
Eu acho que você pode salvar outro personagem substituindo a=id(9)%79por a=id(9)%p.
Kirbyfan64sos

@ kirbyfan64sos Brilliant! Obrigado.
Lynn

11
Além disso, se você fizer isso para o Python 3, poderá alterar a raw_inputchamada para just input.
Kirbyfan64sos

10

C, 122 121 115 104 102 101 bytes

#define o ({for(int t=0;t<80;++t)t%16||putchar(10),putchar(t^p?t^a?46:34:64);})
p;main(a){for(a=1+time(0)%79;p^a;o,p+=(int[]){-16*(p>15),16*(p<64),-!!(p%16),p%16<15}[3&getchar()/2]);}

Primeira postagem aqui! Espero que você goste :)

oé a função de impressão, erm. Nosso corajoso herói pode ser movido com 2, 4, 6 e 8, mas cuidado para não enviar nenhuma outra entrada (sem novas linhas!).

Atualização 1: trazido ae ipara dentro maindos parâmetros.

Atualização 2: OP tendo confirmado que uma única sequência de entrada está correta, me livrei scanf(da qual costumava pular a nova linha).

Atualização 3: Usou uma matriz composta literal e modificou o layout de entrada. O programa agora fica confuso se você digitar uma direção inválida;)

Atualização 4: Observe que a chamada para a função de impressão não conta. Tomou nota para ler as regras com mais cuidado.

Atualização 5: um byte salvo, graças a Mikkel Alan Stokkebye Christia.


Poderia !!(p%16)ser p%16>0? Não me lembro da minha ordem de operações.
lirtosiast

@ThomasKwa, é, mas esse unário -não pode deixar de se ater p, então parênteses são necessários de qualquer maneira. O duplo-bang é apenas ofuscação :)
Quentin

@Quentin 3 & getchar () / 2 <getchar () / 2-25
Mikkel Alan Stokkebye Christia

@MikkelAlanStokkebyeChristia thank you :)
Quentin

9

CJam, 46 45 44 40 39 37 bytes

{'.80*W$Gb'"t1$Gb'@tG/W%N*oNo}:P;
5,G,m*:Dmr~{P_l~4b2fm.+_aD&!$_W$=!}gP];

A primeira linha (define uma função que imprime o estado atual do jogo) e os Ps na segunda linha (chamam essa função) não contribuem para a contagem de bytes.

Tanto a posição inicial quanto a posição do amuleto são selecionadas pseudo-aleatoriamente. A distribuição é tão uniforme e o PRNG subjacente permite.

A entrada é E, 6, 9e Bpara cima , para baixo , esquerda e direita , com Caps Lockactivado, seguido por Enter.

Versão alternativa

{'.80*W$Gb'"t1$Gb'@tG/W%N*oNo}:P;
5,G,m*:Dmr~{P_ZYm*l~(=:(.+_aD&!$_W$=!}gP];

Ao custo de mais quatro bytes, o formato de entrada é aprimorado significativamente:

  • Esta versão aceita 8, 2, 4e 6para cima , para baixo , esquerda e direita , que coincide com as teclas de setas correspondentes no teclado numérico.
  • É também aceita 7, 9, 1e 3para os correspondentes movimentos diagonais.

Testando

Como a E / S é interativa, você deve tentar esse código com o interpretador Java .

Baixe a versão mais recente e execute o programa assim:

java -jar cjam-0.6.5.jar nethack.cjam

Para evitar pressionar Enterapós cada tecla e para atualizações no local da saída, você pode usar este wrapper:

#!/bin/bash

lines=5
wait=0.05

coproc "$@"
pid=$!

head -$lines <&${COPROC[0]}

while true; do
    kill -0 $pid 2>&- || break
    read -n 1 -s
    echo $REPLY >&${COPROC[1]}
    printf "\e[${lines}A"
    head -$lines <&${COPROC[0]}
    sleep $wait
done

printf "\e[${lines}B"

Invoque assim:

./wrapper java -jar cjam-0.6.5.jar nethack.cjam

Versão principal

5,G,   e# Push [0 1 2 3 4] and [0 ... 15].
m*:D   e# Take the Cartesian product and save in D.
mr~    e# Shuffle and dump the array on the stack.
       e# This pushes 80 elements. We'll consider the bottommost the amulet's
       e# position and the topmost the player's.
{      e# Do:
  P    e#   Call P.
  _    e#   Copy the player's position.
  l~   e#   Read and evaluate one line of input.
       e#      "6" -> 6, "9" -> 9, "B" -> 11, "E" -> 14 
  4b   e#   Convert to base 4.
       e#     6 -> [1 2], 9 -> [2 1], 11 -> [2 3], 14 -> [3 2]
  2f-  e#   Subtract 2 from each coordinate.
       e#     [1 2] -> [-1 0], [2 1] -> [0 -1], [2 3] -> [0 1], [3 2] -> [1 0]
  .+   e#   Add the result to the copy of player's position.
  _aD& e#   Push a copy, wrap it in an array and intersect with D.
  !    e#   Logical NOT. This pushes 1 iff the intersection was empty.
  $    e#   Copy the corresponding item from the stack.
       e#     If the intersection was empty, the new position is invalid
       e#     and 1$ copies the old position.
       e#     If the intersection was non-empty, the new position is valid
       e#     and 0$ copies the new position.
  _W$  e#   Push copies of the new position and the amulet's position.
  =!   e#   Push 1 iff the positions are different.
}g     e# While =! pushes 1.
P      e# Call P.
];     e# Clear the stack.

Versão alternativa

ZYm*   e# Push the Cartesian product of 3 and 2, i.e.,
       e#   [[0 0] [0 1] [0 2] [1 0] [1 1] [1 2] [2 0] [2 1] [2 2]].
l~     e#   Read and evaluate one line of input.
(=     e# Subtract 1 and fetch the corresponding element of the array.
:(     e# Subtract 1 from each coordinate.

Função P

'.80*  e# Push a string of 80 dots.
W$Gb   e# Copy the amulet's position and convert from base 16 to integer.
'"t    e# Set the corresponding character of the string to '"'.
1$Gb   e# Copy the player's position and convert from base 16 to integer.
'@t    e# Set the corresponding character of the string to '@'.
G/     e# Split into chunks of length 16.
W%     e# Reverse the chunks (only needed for the alternate program).
N*     e# Join the chunks, separating by linefeeds.
oNo    e# Print the resulting string and an additional linefeed.

2
Estou bem no seu caminho com o TI-BASIC! Vou postar assim que verificar minha solução.
lirtosiast

8

Java, 231 bytes (196 se função)

Aqui está o código completo do programa em 342:

class H{public static void main(String[]a){int p=0,y=79,c;y*=Math.random();y++;p(p,y);do p((p=(c=new java.util.Scanner(System.in).next().charAt(0))<66&p%16>0?p-1:c==68&p%16<15?p+1:c>86&p>15?p-16:c==83&p<64?p+16:p),y);while(p!=y);}static void p(int p,int y){for(int i=0;i<80;i++){System.out.print((i==p?'@':i==y?'"':'.')+(i%16>14?"\n":""));}}}

Sem a função de impressão, 231:

class H{public static void main(String[]a){int p=0,y=79,c;y*=Math.random();y++;p(p,y);do p((p=(c=new java.util.Scanner(System.in).next().charAt(0))<66&p%16>0?p-1:c==68&p%16<15?p+1:c>86&p>15?p-16:c==83&p<64?p+16:p),y);while(p!=y);}}

Se apenas uma função estiver correta (não estou claro nas especificações), então eu posso reduzir isso um pouco mais para 196:

void m(){int p=0,y=79,c;y*=Math.random();y++;p(p,y);do p((p=(c=new java.util.Scanner(System.in).next().charAt(0))<66&p%16>0?p-1:c==68&p%16<15?p+1:c>86&p>15?p-16:c==83&p<64?p+16:p),y);while(p!=y);}

E com algumas quebras de linha para um pouco de clareza ...

class H{
    public static void main(String[]a){
        int p=0,y=79,c;
        y*=Math.random();
        y++;p(p,y);
        do 
            p(
                (p=(c=new java.util.Scanner(System.in).next().charAt(0))<66&p%16>0?
                    p-1:
                    c==68&p%16<15?
                        p+1:
                        c>86&p>15?
                            p-16:
                            c==83&p<64?
                                p+16:
                                p)
                ,y);
        while(p!=y);
    }

    static void p(int p,int y){
        for(int i=0;i<80;i++){
            System.out.print((i==p?'@':i==y?'"':'.')+(i%16>14?"\n":""));
        }
    }
}

Observe que não estou contando a função de impressão em p(p,y)si, mas estou contando a chamada para ela, pois tenho coisas alterando dentro da instrução de chamada.

Funciona com letras maiúsculas ASDW. Devido à maneira como verifica essas letras, algumas outras letras também podem funcionar, mas as especificações não dizem nada sobre o que deve acontecer se eu pressionar teclas diferentes.


Prefiro formatar operadores ternários aninhados no mesmo nível de indentação, como você faria em uma cadeia de if / else if. É mais legível.
Julio

@ThomasKwa Sim, eu já fiz isso nos dois sentidos às vezes. É mais como instruções aninhadas se encadeadas. Parece-me melhor porque as duas metades de cada ternário estão no mesmo nível, mas distintas das outras.
Geobits

Se uma função anônima é aceitável você pode cortar a sua resposta para 192 bytes: void m()torna-se()->
Ankh-Morpork

@ dohaqatar7 Sim, mas eu não uso as funções anon do Java para código de golfe. Parece-me obscuro, em princípio, se os outros sentem o mesmo.
Geobits

Você pode fazer p+=?
Julio

5

Java, 574 bytes

import java.util.*;public class N{static Random r=new Random();static int v,b,n,m;public static void main(String[] a){v=r.nextInt(16);b=r.nextInt(5);n=r.nextInt(16);m=r.nextInt(5);p();do{Scanner e=new Scanner(System.in);char m=e.next().charAt(0);if(m=='w')b=b>0?b-1:b;if(m=='s')b=b<5?b+1:b;if(m=='a')v=v>0?v-1:v;if(m=='d')v=v<16?v+1:v;p();}while(v!=n || b!=m);}static void p(){System.out.println();for(int y=0;y<5;y++){for(int x=0;x<16;x++){if(x==z && y==x)System.out.print('@');else if(x==n && y==m)System.out.print('"');else System.out.print('.');}System.out.println();}}}

Basicamente, o mesmo que a versão C #, exceto ofuscada e minimizada.


tantos espaços desnecessários ...;)
Will

@Will eu estava apenas corrigindo isso: P
fase

11
Além disso, use nomes de uma letra e ternários.
lirtosiast

@ThomasKwa corrigido: D
phase

6
Há ainda muitos espaços desnecessários e falta de ternários;)
Will

5

Julia, 161 bytes

Usos w, a, s, e dpara mover para cima, esquerda, baixo, e direita, respectivamente.

Código completo, incluindo impressão (330 bytes):

B=fill('.',5,16)
a=[rand(1:5),rand(1:16)]
B[a[1],a[2]]='"'
c=[1,a==[1,1]?2:1]
B[c[1],c[2]]='@'
for i=1:5 println(join(B[i,:]))end
while c!=a
B[c[1],c[2]]='.'
m=readline()[1]
c[2]+=m=='a'&&c[2]>1?-1:m=='d'&&c[2]<16?1:0
c[1]+=m=='w'&&c[1]>1?-1:m=='s'&&c[1]<5?1:0
m∈"wasd"&&(B[c[1],c[2]]='@')
for i=1:5 println(join(B[i,:]))end
end

Código pontuado, exclui impressão (161 bytes):

a=[rand(1:5),rand(1:16)]
c=[1,a==[1,1]?2:1]
while c!=a
m=readline()[1]
c[2]+=m=='a'&&c[2]>1?-1:m=='d'&&c[2]<16?1:0
c[1]+=m=='w'&&c[1]>1?-1:m=='s'&&c[1]<5?1:0
end

A diferença aqui é que não salvamos o estado do jogo como uma matriz; todas as informações relevantes estão contidas nas matrizes ce a. E, claro, nada é impresso. O usuário não será mais solicitado a entrar quando o jogador atingir o amuleto.


Ungolfed + explicação (código completo):

# Initialize a 5x16 matrix of dots
B = fill('.', 5, 16)

# Get a random location for the amulet
a = [rand(1:5), rand(1:16)]

# Put the amulet in B
B[a[1], a[2]] = '"'

# Start the player in the upper left unless the amulet is there
c = [1, a == [1,1] ? 2 : 1]

# Put the player in B
B[c[1], c[2]] = '@'

# Print the initial game state
for i = 1:5 println(join(B[i,:])) end

# Loop until the player gets the amulet
while c != a

    # Put a dot in the player's previous location
    B[c[1], c[2]] = '.'

    # Read a line from STDIN, take the first character
    m = readline()[1]

    # Move the player horizontally within the bounds
    if m == 'a' && c[2] > 1
        c[2] -= 1
    elseif m == 'd' && c[2] < 16
        c[2] += 1
    end

    # Move the player vertically within the bounds
    if m == 'w' && c[1] > 1
        c[1] -= 1
    elseif m == 's' && c[1] < 5
        c[1] += 1
    end

    # Set the player's new location in B
    if m ∈ "wasd"
        B[c[1], c[2]] = '@'
    end

    # Print the game state
    for i = 1:5 println(join(B[i,:])) end

end

Eu acho que está tudo bem #

3
+1 para a versão compactada / ofuscada parecendo muito semelhante ao que eu lembro do código-fonte do nethack real.
Ben Jackson

Você pode salvar alguns bytes usando uma randomização pior:a=[rand(1:5),1] c=a+1
lirtosiast

@ThomasKwa: Que graça é essa se estiver sempre na primeira linha? :)
Alex A.

3

Lote, 329 bytes

@echo off
set e=goto e
set f= set/a
%f%a=0
%f%b=0
%f%c=%random%*3/32768+1
%f%d=%random%*16/32768+1
:et
call:p %a% %b% %c% %d%
if %a%%b% EQU %c%%d% exit/b
choice/C "wasd"
goto %errorlevel%
:1
%f%a-=1
%e%
:2
%f%b-=1
%e%
:3
%f%a+=1
%e%
:4
%f%b+=1
:e
if %a% GTR 4%f%a=4
if %a% LSS 0%f%a=0
if %b% GTR 15%f%b=15
if %b% LSS 0%f%b=0
%e%t

:p
setlocal enabledelayedexpansion
::creating a new line variable for multi line strings
set NL=^


:: Two empty lines are required here
cls
set "display="
for /l %%r in (0,1,4) do (
    set "line="
    for /l %%c in (0,1,15) do (
        set "char=."
        if %3 EQU %%r (
            if %4 EQU %%c (
                set char="
            )
        )
        if %1 EQU %%r (
            if %2 EQU %%c (
                set "char=@"
            )
        )
        set "line=!line!!char!"
    )
    set "display=!display!!line!!NL!"
)
echo !display!
exit /b

Isto é altamente impressionante. Estou surpreso que seja possível fazer isso.
eis

Isso não mostra a masmorra para mim, apenas uma série de linhas solicitando [W, A, S, D] ?. Parece "funcionar" - caminhar pela masmorra não exibida acaba saindo. win7 cmd.exe
Dan Pritts 06/07/2015

Ele funciona para mim witn Win7 cmd.exe - quando digito ver eu ficoMicrosoft Windows [Version 6.1.7601]
Jerry Jeremias

@ DanPritts Isso é estranho. Ele funciona perfeitamente para mim no Windows 8 ( Microsoft Windows [Version 6.2.9200])
Ankh-Morpork

doh, eu não tinha copiado e colado a coisa toda, não rolei para baixo na janela. Bem feito.
Dan Pritts 07/07/2015

3

Perl, 228 222 caracteres (sem contar as novas linhas que não fazem parte do funcionamento do código) - 207 se não contar as partes da instrução printe print ifque são usadas para impressão, mas não aumentam a lógica do jogo; 144 se também considerar o código de geração de representação de campo como parte da impressão, conforme sugerido por Yakk nos comentários)

Esse código usa wasd em minúsculas para controle; entrada deve ser confirmada com Enter. Testado com Perl 5.14.2.

($a=$==rand(79))+=($a>=($==rand(80)));
print $_=("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/gr;
%r=qw(w s/.(.{16})@/@\1./s a s/.@/@./ s s/@(.{16})./.\1@/s d s/@./.@/);
while(/"/){print if eval $r{getc STDIN}}

Observe que, para esse código, é impossível separar cálculo e impressão, pois as operações são feitas diretamente na representação impressa usando expressões regulares.

Explicação:

($a=$==rand(79))+=($a>=($==rand(80)));

Esta linha determina a posição do jogador e do amuleto. A posição do jogador é determinada $==rand(80)e é realmente fácil de entender: Em um tabuleiro 5 × 16, há 80 posições distintas onde o jogador pode estar. A posição é armazenada na $=variável que força o valor armazenado em número inteiro; isso economiza alguns bytes por não precisar converter explicitamente o resultado em número inteiro ( randfornece um valor de ponto flutuante).

Como uma das posições já está ocupada pelo jogador, restam apenas 79 posições para o amuleto e, portanto, a posição do amuleto $a=$==rand(79)é usada. Mais uma vez, a atribuição de $=forçar uma conversão para inteiro, no entanto, atribuo-a mais $apara reutilizar $=para a posição do jogador.

Agora, para evitar que o amuleto ocupe a mesma posição que o jogador, ele é avançado em uma posição se sua posição for pelo menos tão grande quanto a do jogador, fornecendo uma distribuição uniforme nos locais não ocupados pelo jogador. Isto é conseguido por $a = ($a >= $=)onde $=aqui ocupa a posição do jogador. Agora a primeira linha é gerada inserindo as duas atribuições iniciais em vez dos primeiros $a$ and the only$ = `nesta expressão.

print $_=("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/gr;

Isso gera o campo inicial e, posteriormente, as impressões são. ("."x80)apenas gera uma sequência de 80 pontos. =~s/(.{$=})./\1@/rentão substitui o $=th caractere por @, e =~s/(.{$=})./\1@/ro $ath caractere por ". Devido ao rmodificador, eles não tentam modificar no local, mas retornam a string modificada, por isso podem ser aplicados às expressões anteriores. Por fim, =~s/(.{16})/\1\n/grinsere uma nova linha a cada 16 caracteres. Observe que o campo é armazenado na variável especial $_que pode ser usada implicitamente em instruções posteriores.

%r=qw(w s/.(.{16})@/@\1./s a s/.@/@./ s s/@(.{16})./.\1@/s d s/@./.@/);

Isso cria um hash contendo as regras de substituição para as diferentes jogadas. Uma versão mais legível disso é

%r = ( 'w' => 's/.(.{16})@/@\1./s',
       'a' => 's/.@/@./',
       's' => 's/@(.{16})./.\1@/s',
       'd' => 's/@./.@/' );

As chaves são os caracteres para os movimentos e os valores são cadeias que contêm a regra de substituição correspondente.

while(/"/){print if eval"\$_=~$r{getc STDIN}"}

Este é o loop principal. while(/"/)verifica se ainda há um "caractere $_(ou seja, no campo). Se passarmos para o amuleto, seu personagem será substituído pelo personagem do jogador, desaparecendo do campo.

eval $r{getc STDIN}lê um caractere da entrada padrão, consulta a regra de substituição correspondente do has %re aplica-a $_ao campo. Isso avalia como verdadeiro se uma substituição foi realmente feita (ou seja, a chave foi encontrada no hash e a movimentação foi possível; uma movimentação impossível não corresponderá à regra de substituição). Nesse caso, printé executado. Como é chamado sem argumento, ele imprime $_, ou seja, o campo modificado.


11
Só porque você inclui feeds de linha para facilitar a leitura não significa que você deve contá-los. Eu vejo 228 bytes. Além disso, de acordo com as regras específicas desta pergunta, a parte de impressão do seu código não contribui para a contagem de bytes.
214 Dennis

@Dennis: Para a parte de impressão, veja a explicação que eu adicionei: Você não pode separar significativamente a impressão e a avaliação no meu código. Agora mudei a contagem, como você sugeriu.
Celtschk 04/07/2015

Há alguma alteração de estado no seu código de impressão? Não? Bem, na minha opinião, reutilizar a saída do código de impressão para sua lógica não deve penalizá-lo. O código de movimento (que é distinto!) Deve contar, mas o código que gera a "string de exibição" não deve contar.
Yakk 6/07/2015

@Yakk: Qual parte do meu código você considera o código de impressão? (Na verdade, minha opinião é que a exclusão do código de impressão a partir de contagem foi uma má idéia, exatamente porque não é sempre bem definida, o que "código de impressão" é.)
celtschk

@celtschk ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grestá bem próximo à primeira vista, mas meu perl-fu está alguns anos enferrujado. Eu poderia ter perdido uma mudança de estado lá.
Yakk 6/07/2015

2

C #, 256 248 234 227 226 225 bytes

Usa as setas do NumPad com o NumLock ativado para se mover.

Recuado e comentado para maior clareza:

using System;
class P{
    static void Main(){
        int a=0,b=0,c,d,e;
        var r=new Random();
        while(0<((c=r.Next(16))&(d=r.Next(5))));
        Draw(a,b,c,d); // Excluded from the score.
        while(a!=c|b!=d){
            e=Console.ReadKey().KeyChar-48;
            a+=e==4&a>0?-1:e==6&a<15?1:0;
            b+=e==8&b>0?-1:e==2&b<4?1:0;
            Draw(a,b,c,d); // Excluded from the score.
        }
    }
    // The following method is excluded from the score.
    static void Draw(int a, int b, int c, int d){
        Console.Clear();
        for (int y = 0; y < 5; y++)
        {
            for (int x = 0; x < 16; x++)
            {
                Console.Write(
                    x == a && y == b ? '@' :
                    x == c && y == d ? '"' :
                                       '.'
                );
            }
            Console.WriteLine();
        }
    }
}

11
Eu acho que C # ints implicitamente iniciam em zero. Além disso (não é possível verificar no momento) se a transmissão não é um problema, você pode converter literais de caracteres em ints, ou pelo menos o 'a' para 97 (eu acho), embora os outros tenham três dígitos.

Somente campos de classe são inicializados por padrão, e isso requer que eles sejam declarados estáticos neste caso. As variáveis ​​de método devem ser inicializadas antes do primeiro uso. Isso leva menos caracteres: 4 vs 7.
Mão-E-Food

Obrigado @tolos pela dica sobre como converter implicitamente char para int! Melhor ainda, se eu usar o enum ConsoleKey convertido como int, posso usar valores de 2 dígitos.
Hand-E-Food

Tecnicamente, o Mainmétodo não precisa ser chamado Main, para que você possa cortar outros três caracteres.
Luaan

@Luaan, acho que você está enganado. C documentação #: msdn.microsoft.com/en-us/library/acy3edy3.aspx
Mão-E-Food

2

Html + JavaScript (ES6), pontuação talvez 217

Muito longo, mas jogável online nos trechos abaixo.

A linha 6 (T.value ...) é para saída e não é contada (mas, por simplicidade, contei a área de texto nas tags de abertura e fechamento, mesmo que também seja de saída)

Quanto à aleatoriedade: o amuleto está sempre na metade direita da grade e o jogador sempre começa na metade esquerda.

Clique na área de texto (após ampliá-la) para iniciar e reiniciar o jogo.

<textarea id=T onclick='s()' onkeyup='m(event.keyCode)'></textarea>
<script>
R=n=>Math.random()*n|0,
s=e=>m(y=R(5),x=R(8),a=R(5)*17+R(8)+8),
m=k=>(x+=(x<15&k==39)-(x>0&k==37),y+=(y<4&k==40)-(y>0&k==38),p=y*17+x,
T.value=p-a?(t=[...('.'.repeat(16)+'\n').repeat(5)],t[a]='X',t[p]='@',t.join('')):t='Well done!'
)
</script>

Snippet do EcmaScript 6 (somente Firefox)

R=n=>Math.random()*n|0
s=e=>m(y=R(5),x=R(8),a=R(5)*17+R(8)+8)
m=k=>(
  x+=(x<15&k==39)-(x>0&k==37),
  y+=(y<4&k==40)-(y>0&k==38),
  p=y*17+x,
  T.value=p-a?(t=[...('.'.repeat(16)+'\n').repeat(5)],t[a]='"',t[p]='@',t.join('')):t='Well done!'
)
<textarea id=T onclick='s()' onkeyup='m(event.keyCode)'></textarea>

Fragmento EcmaScript 5 (testado no Chrome)

function R(n) { return Math.random()*n|0 }

function s() { m(y=R(5),x=R(8),a=R(5)*17+R(8)+8) }

function m(k) {
  x+=(x<15&k==39)-(x>0&k==37)
  y+=(y<4&k==40)-(y>0&k==38)
  p=y*17+x
  T.value=p-a?(t=('.'.repeat(16)+'\n').repeat(5).split(''),t[a]='"',t[p]='@',t.join('')):t='Well done!'
}
<textarea id=T onclick='s()' onkeyup='m(event.keyCode)'></textarea>


2

ActionScript 3: 267 bytes

Um exemplo de trabalho está online

var a:int,p:int,t;function g(){var r=Math.random;while(p==a){a=r()*80;p=r()*80}addEventListener("keyDown",function(e){if(a==p)return;if(e.keyCode==87&&p>15)p-=16if(e.keyCode==83&&p<64)p+=16if(e.keyCode==65&&p%16>0)p--if(e.keyCode==68&&(p+1)%16>0)p++print()});print()}

Aqui está um programa completo (espaços em branco incluídos para facilitar a leitura) usando a função de jogo:

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFormat;

    public class MiniRogue extends Sprite
    {
        var a:int, p:int, t;

        public function MiniRogue()
        {
            g();
        }

        function g(){
            var r=Math.random;
            while(p==a){
                a=r()*80;
                p=r()*80
            }
            addEventListener("keyDown",function(e){
                if(a==p)
                    return;
                if(e.keyCode==87&&p>15)
                    p-=16
                if(e.keyCode==83&&p<64)
                    p+=16
                if(e.keyCode==65&&p%16>0)
                    p--
                if(e.keyCode==68&&(p+1)%16>0)
                p++
                print()
            });
            print()
        }

        var old:int = -1;
        private function print():void {
            if (!t) {
                t = new TextField()
                t.defaultTextFormat = new TextFormat("_typewriter", 8)
                t.width=500;
                t.height=375;
                addChild(t)
            }
            var board:String = "";
            for (var i:int=0; i<80;i++) {
                if (i == p) {
                    board += "@";
                } else if (i == a) {
                    board += '"';
                } else {
                    board += ".";
                }
                if ((i + 1) % 16 == 0) {
                    board += "\n";
                }
            }
            if (a==p) {
                board += "Win!";
            }
            if (p == old) {
                board += "Bump!";
            }
            old = p;
            t.text = board;
        }
    }
}

2

Javascript: 307 216

Você pode jogar no trecho abaixo! Os números à esquerda são apenas para que o console (pelo menos um no Chrome) não mescle as linhas.

Para executar o código:

  1. clique em "snippet de código de execução"
  2. pressione ctrl-shift-j para abrir o console
  3. clique na seção de resultados
  4. use as setas e toque

var x=y=2,m=Math,b=m.floor(m.random()*5),a=14,i,j,t,c=console,onload=d;function d(){c.clear();for(i=0;i<5;i++){t=i;for(j=0;j<16;j++){t+=(i==y&&j==x)?"@":(i==b&&j==a)?'"':".";if(a==x&&b==y)t=":)";}c.log(t);}}onkeydown=function(){switch(window.event.keyCode){case 37:if(x>0)x--;break;case 38:if(y>0)y--;break;case 39:if(x<15)x++;break;case 40:if(y<4)y++;break;}d();};

Sem golfe:

var px=py=2,m=Math,ay=m.floor(m.random()*5),ax=14,i,j,t,c=console,onload=draw;
function draw() {
  c.clear();
  for(i=0;i<5;i++) {
    t=i;
    for(j=0;j<16;j++) {
      t+=(i==py&&j==px)?"@":
         (i==ay&&j==ax)?'"':".";
      if(ax==px&&ay==py)t=":)";
    }
    c.log(t);
  }
}
onkeydown=function() {
  switch (window.event.keyCode) {
    case 37:
      if(px>0)px--;
      break;
    case 38:
      if(py>0)py--;
      break;
    case 39:
      if(px<15)px++;
      break;
    case 40:
      if(py<4)py++;
      break;
  }
  draw();
};

Editar 1: leia as regras com mais cuidado e reescreva meu código de acordo

  • o valor do amuleto y agora é randomizado
  • jogador não pode mais escapar da sala
  • Já não conto os caracteres na função de desenho ou chamo para ela

1

SpecBAS - 428 402 (excluindo impressão, 466 425 quando contados)

Usa Q / A / O / P para mover para cima / baixo / esquerda / direita, respectivamente.

A linha para imprimir a masmorra na linha 1 é a única linha que pode ser ignorada, mas também diminuiu um pouco.

1 PRINT ("."*16+#13)*5
2 LET px=8: LET py=3
3 LET ax=INT(RND*16): LET ay=INT(RND*5): IF ax=px AND ay=py THEN GO TO 3
4 PRINT AT ay,ax;#34;AT py,px;"@": LET ox=px: LET oy=py: PAUSE 0: LET k$=INKEY$
5 LET px=px+(k$="p")-(k$="o")
6 IF px<0 THEN LET px=0
7 IF px>15 THEN LET px=15
8 LET py=py+(k$="a")-(k$="q")
9 IF py<0 THEN LET py=0
10 IF py>4 THEN LET py=4
11 PRINT AT oy,ox;"."
12 IF SCREEN$(px,py)<>#34 THEN GO TO 4

A referência ao # 34 é apenas uma maneira abreviada de colocar CHR $ (34) no código.

Obrigado @ Thomas Kwa, eu não tinha notado que a posição inicial do jogador era aleatória era opcional. Também usei instruções SE separadas para eliminar alguns caracteres.


Você pode salvar alguns caracteres aleatoriamente menos: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)e também usando IF instead of ELSE IF.
lirtosiast

1

Outro C #, 221 171 170

Aqui está outra maneira em C # com ambas as posições aleatórias. Queria mostrar isso mesmo que essa parte tenha 7 bytes a mais que a solução da Hand-E-Food.
A resposta do Hand-E-Food será mais curta, é claro, assim que ele usar o Console.Read ().
A desvantagem do Consol.Read é que pressionar o Enter necessário faz com que o campo seja impresso mais duas vezes.
Mas acho que não é necessário imprimir apenas com entrada (real).

A navegação é feita pelo 8426 como na solução Hand-E-Foods.

using System;
class P
{
static void Main()
{
Func<int> n=new Random().Next;
int x=n()%16,y=n()%5,a=n()%16,b,m;
while(y==(b=n()%5));

while(x!=a|y!=b)
{
Printer.Print(a, b, x, y);  // Excluded from the score.
m=Console.Read()-48;
y+=m==8&y>0?-1:m==2&y<4?1:0;
x+=m==4&x>0?-1:m==6&x<15?1:0;
}
}
}


Edit: (adicionada nova solução e movido o PrinterClass para o final)
Edit2: (alterado de 14 para 15 e salvo o byte iniciando no canto inferior direito)

Adaptando a técnica do Mauris, é possível derreter para 171 bytes em C # (é claro que agora sem as duas posições aleatórias):

using System;
class P
{
static void Main()
{
int p=79,a=new Random().Next()%p,m;
while(p!=a){
Printer.Print(p,a);  // Excluded from the score.
m=Console.Read()-48;
p+=m==4&p/5>0?-5:m==6&p/5<15?5:m==8&p%5>0?-1:m==2&p%5<4?1:0;
}
}
}

A classe Printer é quase a mesma, apenas uma nova sobrecarga de impressão ...

class Printer
{
    public static void Print(int ax, int ay, int px, int py)
    {
        Console.Write('\n');
        for (int y = 0; y < 5; y++)
        {
            for (int x = 0; x < 16; x++)
            {
                if (x == px && y == py)
                    Console.Write('@');
                else if (x == ax && y == ay)
                    Console.Write('"');
                else
                    Console.Write('.');
            }
            Console.Write('\n');
        }
    }

    public static void Print(int p, int a)
    {
        Print(p/5,p%5,a/5,a%5);
    }
}

1

Ruby, 185

Aqui está um exemplo de Ruby também.
Eu sou muito novo em Ruby, talvez alguém saiba como fazer isso melhor :)

Contei lineFeeds como 1, pois o Programa falhará caso contrário ...

A navegação é feita pelo 8462. Você precisa enviar entradas sempre que pressionar enter.

def display(ax,ay,px,py)
    puts
    for y in 0..4
        for x in 0..15
            if (x == px && y == py)
                print "@"
            elsif (x == ax && y == ay)
                print '"'
            else
                print '.'
            end
        end
        puts
    end
end


x=y=0
a=Random.rand(16) while y==(b=Random.rand(5))
while x!=a or y!=b
display(a,b,x,y)  # Excluded from the score.
m=gets.chomp.to_i
y-=m==8?1:0 if y>0
y+=m==2?1:0 if y<4
x-=m==4?1:0 if x>0
x+=m==6?1:0 if x<15
end

0

QBasic, 103 bytes

De acordo com as regras do desafio, o Showsubprograma não é incluído na contagem de bytes nem é a Show p, q, a, bchamada (com a nova linha a seguir).

b=1+TIMER MOD 9
1Show p, q, a, b
INPUT m
p=p-(m=2)*(p>0)+(m=4)*(p<4)
q=q-(m=1)*(q>0)+(m=3)*(q<15)
IF(p<>a)+(q<>b)GOTO 1


SUB Show (playerRow, playerCol, amuletRow, amuletCol)
CLS
FOR row = 0 TO 4
  FOR col = 0 TO 15
    IF row = playerRow AND col = playerCol THEN
      PRINT "@";
    ELSEIF row = amuletRow AND col = amuletCol THEN
      PRINT CHR$(34);    ' Double quote mark
    ELSE
      PRINT ".";
    END IF
  NEXT
  PRINT
NEXT
END SUB

Para mover, digite um número e pressione Enter: 1para ir para a esquerda, 2para subir, 3para a direita e 4para baixo.

Este código não gera o estado do jogo no final, quando o jogador encontra o amuleto. Para fazer isso, adicione outro Show p, q, a, bapós a IFdeclaração.

Explicação

Vamos a, brepresentam as coordenadas do amuleto e p, qas coordenadas do jogador. O jogador começa em (0, 0) e o amuleto começa na linha 0, com uma coluna entre 1 e 9, inclusive, com base no dígito 1 do tempo atual.

O resto é apenas um monte de matemática com condicionais. O importante é lembrar que condicionais no QBasic retornam 0para falso, -1para verdadeiro. Vejamos a instrução de atualização da linha do jogador:

p=p-(m=2)*(p>0)+(m=4)*(p<4)

Se m=2, queremos subir subtraindo 1 de p, desde que p>0. Da mesma forma, se m=4quisermos descer adicionando 1 a p, desde que p<4. Podemos obter o comportamento desejado multiplicando. Se os dois fatores forem -1, o produto deles será 1, do qual podemos subtrair ou adicionar p. Se um dos condicionais for 0, o produto será 0, sem efeito.

Da mesma forma, a condição para determinar se o jogador encontrou o amuleto é:

IF(p<>a)+(q<>b)GOTO 1

Se qualquer um dos condicionais for verdadeiro, sua soma será diferente de zero (ou -1ou -2) e, portanto, verdadeira, e o programa retornará à linha 1. Uma vez que piguais ae qiguais b, ambos os condicionais serão 0, então sua soma será 0e o fluxo de controle poderá alcançar a final do programa.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.