Minimaler NetHack

64

NetHack ist ein schurkenhaftes Spiel, bei dem ein Spieler das Amulett der Helden aus dem untersten Level des Dungeons holen muss. Üblicherweise über Telnet gespielt, wird das gesamte Spiel mit ASCII-Grafiken dargestellt. Das Spiel ist extrem herausfordernd und erfordert Kenntnisse vieler Spielmechanismen, um erfolgreich zu sein.

Nehmen Sie für die Zwecke dieser Herausforderung an, dass der gesamte Dungeon aus einer Ebene und nur 5 × 16 Zeichen besteht. Nehmen Sie außerdem an, dass dies ein "sicherer" Dungeon ist oder dass Sie nur einen Prototyp implementieren - es wird keine Monster, Bedenken hinsichtlich des Hungers usw. geben. Tatsächlich müssen Sie nur die Position des Charakters, des Amuletts und des Spiels verfolgen wird effektiv beendet, wenn der Spieler am selben Ort wie das Amulett ankommt.

Herausforderungsanforderungen

  • Es wird einen 5 × 16 Dungeon geben (Single Level).
  • Geben Sie dem Spieler einen Startplatz (optional zufällig) und dem Amulett ein separates Startfeld im Dungeon (jedes Mal anders, wenn das Programm ausgeführt wird). Das heißt, das Amulett darf nicht auf demselben Feld wie der Spieler beginnen.
  • Akzeptieren Sie vier Eingabetasten, die den Spieler jeweils um ein Feld bewegen (vier Hauptrichtungen). Das Lesen / Verarbeiten anderer Eingaben ist zulässig (eine readline () - Funktion, die das Drücken der Eingabetaste usw. erfordert).
  • Reisen außerhalb des Kerkers sind nicht gestattet. Wenn sich der Spieler am rechten Rand des Dungeons befindet und nach rechts drückt, sollte dies nichts bewirken.
  • Drucken Sie nach der ersten Generierung und nach jeder Bewegung den Status des Spiels. Da dies Codegolf ist und das Drucken ziemlich uninteressant ist, ignorieren Sie die Zeichenanzahl für die Druckfunktion und den Funktionsaufruf, sofern sich der Status nicht ändert . Leere Zellen sollten als Punkt ( .), Amulett als Anführungszeichen ( ") und Zeichen als Symbol ( @) angezeigt werden .
  • Das Spiel ist beendet, wenn der Spieler das Amulett "entdeckt" (am selben Feld ankommt)

Gewinnen

Dies ist eine Code-Golf-Herausforderung. Der kürzeste Code, der eine Woche nach dem heutigen Tag die Anforderungen erfüllt, wird zum Gewinner erklärt.

Beispiel

Hier ist eine Beispiellösung in C # (ungolfed), um die grundlegenden Anforderungen und die Beispielausgabe zu zeigen.

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');
            }
        }
    }
}

Die Gesamtzahl der Zeichen beträgt 1474, aber ohne Berücksichtigung der Aufrufe der Druckfunktion und ihrer Definition beträgt die endgültige Zeichenanzahl 896.

Ausgabe beim Ausführen des Programms:

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

Ausgabe (einschließlich oben) nach zweimaligem Drücken der Taste 'a':

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

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

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

quelle
10
Ich habe das Gefühl, dass dies für @Doorknob von Interesse sein wird.
Alex A.
10
Rogue ist das originale Roguelike-Spiel, bei dem ein Spieler das Amulett der Helden aus dem untersten Level des Dungeons holen muss. Warum nennst du das nicht einen minimalen Schurken?
Gilles 'SO- hör auf böse zu sein'
5
@ Gilles Warum nennst du das nicht eine minimale Schlange?
Casey Kuball
26
Psshh, keine diagonale Bewegung? Kein yubnhjkl? Nicht einmal eine Treppe hinauf, um nach dem Amulett zu klettern? : P ( stimmt sowieso wütend )
Türklinke
2
@tolos: Mir ist noch unklar, was hier als zufällig gilt . Wenn das Programm 80-mal ausgeführt wird, ist es nicht wirklich möglich, die unterschiedlichen Anforderungen bei jedem Programmlauf zu erfüllen. In dieser Antwort kann das Amulett nur 9 von 79 möglichen Positionen belegen. Zählt das?
Dennis

Antworten:

37

TI-BASIC, 42 41 38 36 35 Bytes

Für Ihren Grafikrechner der Serie TI-83 oder 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

Welche Richtung der Spieler einschlagen wird, hängt vom Tastencode der gedrückten Taste ab, aber vier Tasten, die definitiv funktionieren, befinden sich in der oberen Reihe:

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

Das Amulett beginnt auf einem der fünf Felder in der ersten Spalte, und der Spieler beginnt am unteren rechten Feld. Eine mögliche Anordnung ist beispielsweise:

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

Erläuterung

Die Position des Spielers wird als komplexe Zahl von 0+0ibis gespeichert 15+4i, wobei der Realteil nach rechts und der Imaginärteil nach unten geht. Dies erleichtert die einfache Grenzüberprüfung oben und links: Wir versetzen die Zahl einfach leicht und rund in Richtung Null. Wenn beispielsweise der Versatz 0.5und unsere Position -1+3i(außerhalb des Bildschirms links) sind, wird die Position dahin korrigiert iPart(-0.5+3.5i)=0+3i, wo sie sein sollte. Das Überprüfen der unteren und rechten Grenzen ist etwas komplizierter. Wir müssen die Zahl von einer Konstanten subtrahieren C, die ungefähr 15.635 + 4.093i(die kürzeste, die ich zwischen 15+4iund finden konnte 16+5i) ist, runden, von Cerneut subtrahieren , um die Zahl zurückzudrehen, und erneut runden.

Wenn eine Taste gedrückt wird, bewegt sich die nicht angepasste Spielerposition um 1 Einheit in eine Richtung, aber der ganzzahlige Teil ändert sich nur, wenn bestimmte Tasten gedrückt werden. Zum Glück befinden sich die Tasten, die funktionieren, alle in der obersten Reihe. Nachfolgend sehen Sie eine grafische Darstellung der Offsets in den Fällen, in denen die Tasten 11, 12, 13 und 15 gedrückt werden und wenn keine Taste gedrückt wird (Kein Drücken ist der Punkt innerhalb des mittleren Quadrats, wodurch die ganzzahligen Teile unverändert bleiben; die vier Tastendrücke) 'Offsets haben unterschiedliche ganzzahlige Teile). Cist das rote Kreuz in der Mitte des Kreises.

Bildbeschreibung hier eingeben

Alter Code (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

Einschränkungen

Es gibt keine Möglichkeit, einem "Zeichen zu entkommen. Daher können Zeichenfolgen mit einem "nicht in einem Programm generiert werden. Daher wird hier das Umlautzeichen ¨anstelle eines Anführungszeichens verwendet (wenn bereits ein String mit einem Anführungszeichen vorhanden wäre, könnte ich das anzeigen). Um ¨und @in ein Programm zu bekommen, ist ein externes Tool erforderlich; es ist jedoch gültig TI-BASIC.

Lirtosiast
quelle
2
Aus Spaß habe ich dieses Snippet erstellt , in dem das Diaeresis-Symbol und das @ -Zeichen in Str1 eingefügt sind (im Gegensatz zu "einem externen Tool"). Wählen Sie die Zeile oben aus, die zu Ihrem Rechner passt, geben Sie sie in ein neues Programm ein und führen Sie dieses Programm mit Asm (.
MI Wright
Oh, ich habe vergessen, den Maschinencode auf dem Taschenrechner einzugeben. Ich möchte meine nicht mit einem Tippfehler zum Absturz bringen, aber ich vertraue darauf, dass es funktioniert.
Lirtosiast
44

CHIP-8 , 48 Bytes

Dies kann nicht als legal angesehen werden, aber warum zum Teufel nicht. Ich habe mein Programm in CHIP-8 geschrieben, einer bytecode-basierten Programmiersprache für eine virtuelle Spielekonsole. Sie können das vollständige Programm (99 Bytes) in Ihrem Browser mit einem von mir geschriebenen Emulator / Debugger namens Octo testen:

Bildschirmfoto

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

Ein hexadezimaler Speicherauszug dieses vollständigen Programms lautet wie folgt:

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

Sie können den Player mit den ASWD-Tasten oder den 7589-Tasten auf der ursprünglichen CHIP-8-Tastatur bewegen. Wenn ich den gesamten Code und die Daten zum Zeichnen des Hintergrunds und des Players entferne, erhalte ich stattdessen diesen 48-Byte-Speicherauszug:

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

Die ungelöste, vollständige Form des Programms wurde in einer höheren Assemblersprache wie folgt geschrieben:

: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

Beachten Sie, dass die kompilierten Bytes selbst die Programmiersprache CHIP-8 sind. Der Assembler ist einfach ein bequemeres Mittel zum Erstellen solcher Programme.

JohnE
quelle
19
Richtiges Werkzeug für den Job.
Dennis
6
+1 dafür, dass ich viel Zeit damit verschwendet habe, dein Spiel immer und immer wieder zu spielen.
Alex A.
4
@AlexA. Wenn Sie noch mehr Zeit verschwenden möchten, sollten Sie Cave Explorer ausprobieren . ASWD-Bewegung in der Überwelt und QE werden zum Zurücksetzen / Verschieben von Blöcken in den Platformer-Ebenen verwendet.
JohnE
4
Toll, na da geht mein Wochenende.
Alex A.
1
Anfangs war ich skeptisch, aber Cave Explorer hat Spaß gemacht und CHIP-8 gibt es schon viel länger, als ich gedacht hätte. Also muss ich das wohl lernen.
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]

Nur die beiden untersten Zeilen zählen und fallen lassen d();.

Lynn
quelle
Ich habe ein weiteres Byte gespeichert, indem ich den Player in der unteren rechten Ecke (das "letzte" Quadrat) gestartet und dann zufällig von den ersten 79 Quadraten abgetastet habe .
Lynn
Ups, sorry, behoben! Ich denke, ich bin nicht erstaunlich bei der manuellen Zählung von Bytes. : <
Lynn
1
Ich denke , dass Sie ein anderes Zeichen speichern kann durch den Austausch a=id(9)%79mit a=id(9)%p.
kirbyfan64sos
@ kirbyfan64sos Genial! Vielen Dank.
Lynn
1
Wenn Sie dies für Python 3 vornehmen, können Sie den raw_inputAufruf auch in "Nur" ändern 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]);}

Zum ersten Mal hier posten! Ich hoffe du magst es :)

oist das Drucken, erm, Funktion. Unser tapferer Held kann mit 2, 4, 6 und 8 bewegt werden, aber achten Sie darauf, keine anderen Eingaben zu senden (keine Zeilenumbrüche!).

Update 1: gebracht aund iin maindie Parameter.

Update 2: Nachdem OP bestätigt hat, dass eine einzelne Zeichenfolge in Ordnung ist, wurde ich los scanf(was ich zum Überspringen der neuen Zeile verwendet habe).

Update 3: Verwendete ein zusammengesetztes Array-Literal und änderte das Eingabe-Layout. Programm geht jetzt drunter und drüber, wenn du eine ungültige Richtung eingibst;)

Update 4: Es wurde festgestellt, dass der Aufruf der Druckfunktion nicht zählt. Ich habe mir die Regeln genauer angesehen.

Update 5: Ein Byte gespart dank Mikkel Alan Stokkebye Christia.

QUentin
quelle
Könnte !!(p%16)sein p%16>0? Ich erinnere mich nicht an meine Arbeitsreihenfolge.
Lirtosiast
@ThomasKwa es ist, aber das Unary -kann nicht anders, als zu bleiben p, so dass Klammern in beiden Richtungen benötigt werden. Der Doppelknall ist nur Verschleierung :)
Quentin
@Quentin 3 & getchar () / 2 <getchar () / 2-25
Mikkel Alan Stokkebye Christia
@ MikkelAlanStokkebyeChristia Danke :)
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];

Die erste Zeile (definiert eine Funktion, die den aktuellen Spielstatus ausgibt) und die Ps in der zweiten Zeile (rufen Sie diese Funktion auf) tragen nicht zur Byteanzahl bei.

Sowohl die Startposition als auch die Position des Amuletts werden pseudozufällig ausgewählt. Die Verteilung ist so gleichmäßig und das zugrunde liegende PRNG erlaubt.

Die Eingabe ist E, 6, 9und Bfür Up , unten , links und rechts , mit Caps Lockaktiviert, gefolgt von Enter.

Alternative Version

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

Auf Kosten von vier weiteren Bytes wird das Eingabeformat erheblich verbessert:

  • Diese Version übernimmt 8, 2, 4und 6für Up , unten , links und rechts , die die entsprechenden Pfeiltasten auf dem Numpad übereinstimmt.
  • Es akzeptiert 7auch 9, 1und 3für die entsprechenden diagonalen Bewegungen.

Testen

Da die E / A interaktiv ist, sollten Sie diesen Code mit dem Java-Interpreter ausprobieren .

Laden Sie die neueste Version herunter und führen Sie das Programm folgendermaßen aus:

java -jar cjam-0.6.5.jar nethack.cjam

Um zu vermeiden, dass Enternach jeder Taste eine Taste gedrückt wird, und um die Ausgabe direkt zu aktualisieren, können Sie diesen Wrapper verwenden:

#!/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"

Rufen Sie wie folgt auf:

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

Hauptversion

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.

Alternative Version

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.

Funktion 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.
Dennis
quelle
2
Mit TI-BASIC bin ich genau richtig für dich! Ich poste, sobald ich meine Lösung überprüft habe.
Lirtosiast
8

Java, 231 Bytes (196 wenn Funktion)

Hier ist der vollständige Programmcode bei 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":""));}}}

Ohne die Druckfunktion 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);}}

Wenn nur eine Funktion in Ordnung ist (mir ist aus der Spezifikation nicht klar), kann ich dies ein bisschen weiter auf 196 reduzieren:

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);}

Und mit einigen Zeilenumbrüchen für ein bisschen Klarheit ...

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":""));
        }
    }
}

Beachten Sie, dass ich nicht die Druckfunktion Zählen p(p,y)selbst, aber ich bin Zählen der Anruf an sie, weil ich Sachen in der Call - Anweisung zu ändern haben.

Es funktioniert mit Großbuchstaben ASDW. Aufgrund der Art und Weise, wie nach diesen gesucht wird, funktionieren möglicherweise auch einige andere Buchstaben, aber die Spezifikation sagt nichts darüber aus, was passieren soll, wenn ich verschiedene Tasten drücke.

Geobits
quelle
Ich bevorzuge das Formatieren verschachtelter ternärer Operatoren auf derselben Einrückungsebene wie eine Kette von if / else if. Es ist besser lesbar.
Lirtosiast
@ThomasKwa Ja, ich habe es manchmal in beide Richtungen gemacht. Dies ist eher eine verschachtelte if-Anweisung als eine verkettete. Es fühlt sich für mich besser an, weil beide Hälften eines Ternärs auf derselben Ebene liegen, sich aber von den anderen unterscheiden.
Geobits
Wenn eine anonyme Funktion akzeptabel ist, können Sie Ihre Antwort auf 192 Bytes void m()()->
kürzen
@ dohaqatar7 Ja, aber ich benutze Javas anon-Funktionen nicht für Code-Golf. Es fühlt sich für mich grundsätzlich zwielichtig an, ob es anderen genauso geht oder nicht.
Geobits
Schaffst du das p+=?
Lirtosiast
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();}}}

Grundsätzlich das Gleiche wie die C # -Version, außer verschleiert und minimiert.

Phase
quelle
so viele unnötige Leerzeichen ...;)
Will
@Wird ich gerade beheben, dass: P
Phase
1
Verwenden Sie auch Einbuchstabennamen und Ternären.
Lirtosiast
@ ThomasKwa behoben: D
Phase
6
Es gibt immer noch viele unnötige Leerzeichen und fehlende Ternäre;)
Will
5

Julia, 161 Bytes

Uses w, a, s, und dnach oben, links, unten, bzw. rechts.

Vollständiger Code, einschließlich Drucken (330 Byte):

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

Scored Code, ohne Drucken (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

Der Unterschied besteht darin, dass wir den Spielstatus nicht als Matrix speichern. Alle relevanten Informationen sind in den Arrays cund enthalten a. Und natürlich wird nichts gedruckt. Der Benutzer wird nicht mehr zur Eingabe aufgefordert, sobald der Spieler das Amulett erreicht hat.


Ungolfed + Erklärung (vollständiger Code):

# 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
Alex A.
quelle
Ich denke, das ist in Ordnung
3
+1 für die komprimierte / verschleierte Version, die meiner Erinnerung an den aktuellen Nethack-Quellcode sehr ähnlich sieht.
Ben Jackson
Sie können ein paar Bytes sparen, indem Sie eine schlechtere Randomisierung verwenden:a=[rand(1:5),1] c=a+1
Lirtosiast
@ThomasKwa: Was für ein Spaß ist das, wenn es immer in der ersten Zeile steht? :)
Alex A.
3

Batch, 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
Ankh-Morpork
quelle
Das ist sehr beeindruckend. Ich bin überrascht, dass dies möglich ist.
Eis
Hiermit wird der Dungeon für mich nicht angezeigt, sondern nur eine Reihe von Zeilen mit der Aufforderung [W, A, S, D] ?. Es scheint zu "funktionieren" - wenn man den nicht gezeigten Dungeon betritt, verlässt man ihn schließlich. win7 cmd.exe
Dan Pritts
Es funktioniert für mich mit Win7 cmd.exe - wenn ich ver eingebe, bekomme ichMicrosoft Windows [Version 6.1.7601]
Jerry Jeremiah
@ DanPritts Das ist seltsam. Es funktioniert perfekt für mich unter Windows 8 ( Microsoft Windows [Version 6.2.9200])
Ankh-Morpork
doh, ich hatte das Ganze nicht kopiert und eingefügt, ich habe nicht im Fenster nach unten gescrollt. Gut gemacht.
Dan Pritts
3

Perl, 228 222 Zeichen (ohne die Zeilenumbrüche, die für die Funktionsweise des Codes nicht von Belang sind) - 207 wenn die Teile printund print ifAnweisungen, die zum Drucken verwendet werden, nicht mitgezählt werden, aber nicht zur Spielelogik hinzugefügt werden; 144, wenn auch der Generierungscode der Felddarstellung als Teil des Drucks berücksichtigt wird, wie von Yakk in den Kommentaren vorgeschlagen)

Dieser Code verwendet zur Steuerung die Kleinbuchstaben wasd. Die Eingabe muss mit Enter bestätigt werden. Getestet mit 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}}

Beachten Sie, dass es für diesen Code nicht möglich ist, Berechnung und Druck zu trennen, da die Vorgänge mit regulären Ausdrücken direkt auf der gedruckten Darstellung ausgeführt werden.

Erläuterung:

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

Diese Linie bestimmt die Position des Spielers und des Amuletts. Die Spielerposition wird von bestimmt $==rand(80)und ist eigentlich leicht zu verstehen: Auf einem 5 × 16-Brett gibt es 80 verschiedene Positionen, an denen sich der Spieler befinden kann. Die Position wird in der $=Variablen gespeichert , wodurch der gespeicherte Wert in eine Ganzzahl umgewandelt wird. Dies spart einige Bytes, da das Ergebnis nicht explizit in eine Ganzzahl umgewandelt werden muss ( randliefert einen Gleitkommawert).

Da eine der Positionen bereits vom Spieler besetzt ist, sind nur noch 79 Positionen für das Amulett übrig, daher wird für die Position des Amuletts $a=$==rand(79)verwendet. Auch die Zuordnung zu $=zwingt , eine Umwandlung in Ganzzahl jedoch zu I weisen sie weiter , $aum wieder zu verwenden $=für die Position des Spielers.

Um zu vermeiden, dass das Amulett dieselbe Position wie der Spieler einnimmt, wird es um eine Position weitergeschoben, wenn seine Position mindestens so groß ist wie die des Spielers, wodurch eine gleichmäßige Verteilung auf die nicht vom Spieler eingenommenen Stellen erfolgt. Dies wird dadurch erreicht , $a = ($a >= $=)wo $=hier hält die Position des Spielers. Jetzt wird die erste Zeile durch Einfügen der beiden Anfangszuweisungen anstelle des ersten $a$ and the only$ = `in diesen Ausdruck generiert .

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

Dadurch wird das Anfangsfeld generiert und anschließend gedruckt. ("."x80)generiert nur eine Zeichenfolge von 80 Punkten. =~s/(.{$=})./\1@/rErsetzt dann das $=th Zeichen mit @und =~s/(.{$=})./\1@/rdas $ath Zeichen mit ". Aufgrund des rModifikators versuchen sie nicht, Änderungen vorzunehmen, sondern geben die geänderte Zeichenfolge zurück. Aus diesem Grund können sie auf die vorherigen Ausdrücke angewendet werden. Schließlich =~s/(.{16})/\1\n/grfügt ein Newline alle 16 Zeichen. Beachten Sie, dass das Feld in der speziellen Variablen gespeichert $_ist, die implizit in späteren Anweisungen verwendet werden kann.

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

Dadurch wird ein Hash erstellt, der die Ersetzungsregeln für die verschiedenen Züge enthält. Eine besser lesbare Version davon ist

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

Die Tasten sind die Zeichen für die Züge, und die Werte sind Zeichenfolgen, die die entsprechende Ersetzungsregel enthalten.

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

Dies ist die Hauptschleife. while(/"/)prüft, ob noch ein "Zeichen in $_(dh im Feld) vorhanden ist. Wenn wir uns dem Amulett nähern, wird sein Charakter durch den Spielercharakter ersetzt, sodass er vom Spielfeld verschwindet.

eval $r{getc STDIN}Liest ein Zeichen aus der Standardeingabe, sucht die entsprechende Ersetzungsregel aus dem hat %rund wendet sie auf $_das Feld an. Dies wird als wahr gewertet, wenn tatsächlich eine Ersetzung durchgeführt wurde (dh, der Schlüssel wurde im Hash gefunden und die Verschiebung war möglich; eine unmögliche Verschiebung entspricht nicht der Ersetzungsregel). In diesem Fall printwird ausgeführt. Da es ohne Argument aufgerufen $_wird, gibt es das geänderte Feld aus.

Celtschk
quelle
1
Nur weil Sie Zeilenvorschübe zur besseren Lesbarkeit hinzufügen, müssen Sie sie nicht zählen. Ich sehe 228 Bytes. Gemäß den spezifischen Regeln dieser Frage trägt der druckende Teil Ihres Codes nicht zur Byteanzahl bei.
Dennis
@ Tennis: Für den Druckteil siehe die Erklärung, die ich jetzt hinzugefügt habe: Sie können Drucken und Auswertung in meinem Code nicht sinnvoll trennen. Ich habe jetzt die Zählung geändert, wie Sie vorgeschlagen haben.
Celtschk
Gibt es Statusänderungen in Ihrem Druckcode? Nein? Nun, meiner Meinung nach sollte die Wiederverwendung der Ausgabe Ihres Druckcodes für Ihre Logik Sie nicht bestrafen. Der Bewegungscode (der eindeutig ist!) Sollte zählen, aber der Code, der die "Anzeigezeichenfolge" generiert, sollte nicht zählen.
Yakk
@Yakk: Welchen Teil meines Codes betrachten Sie als Druckcode? (Meiner Meinung nach war der Ausschluss des
Druckcodes
@celtschk ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grist auf den ersten Blick ziemlich nah, aber mein Perl-Fu ist ein paar Jahre rostig. Ich hätte dort einen Zustandswechsel verpassen können.
Yakk
2

C #, 256 248 234 227 226 225 Bytes

Verwendet die NumPad-Pfeile, wenn NumLock aktiviert ist, um sich zu bewegen.

Zur Verdeutlichung eingerückt und kommentiert:

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();
        }
    }
}
Hand-E-Food
quelle
1
Ich denke, C # -Ints implizit auf Null initialisieren. Auch (kann im Moment nicht überprüfen), ob Casting kein Problem ist, können Sie Zeichenliterale in Ints konvertieren, oder zumindest das 'a' in 97 (ich denke), obwohl die anderen drei Ziffern sind.
Standardmäßig werden nur Klassenfelder initialisiert, die in diesem Fall als statisch deklariert werden müssen. Methodenvariablen müssen vor der ersten Verwendung initialisiert werden. Das braucht weniger Zeichen: 4 gegen 7.
Hand-E-Food
Vielen Dank an @tolos für den Tipp, implizit char to int zu setzen! Besser noch, wenn ich die ConsoleKey-Enumeration als int verwende, kann ich zweistellige Werte verwenden.
Hand-E-Food
Technisch muss die MainMethode nicht aufgerufen werden Main, sodass Sie drei weitere Zeichen abschneiden können.
Luaan
@Luaan, ich glaube du liegst falsch. C # -Dokumentation: msdn.microsoft.com/en-us/library/acy3edy3.aspx
Hand-E-Food
2

HTML + JavaScript (ES6), Score vielleicht 217

Zu lang, aber in den folgenden Ausschnitten online spielbar.

Zeile 6 (T.value ...) ist für die Ausgabe und nicht gezählt (aber der Einfachheit halber habe ich die Tags zum Öffnen und Schließen des Textbereichs gezählt, auch wenn es auch ausgegeben wird)

Was die Zufälligkeit betrifft: Das Amulett befindet sich immer in der rechten Hälfte des Gitters und der Spieler beginnt immer in der linken Hälfte.

Klicken Sie auf den Textbereich (nachdem Sie ihn vergrößert haben), um das Spiel zu starten und neu zu starten.

<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>

EcmaScript 6-Snippet (nur 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>

EcmaScript 5-Snippet (in Chrome getestet)

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>

edc65
quelle
2

Actionscript 3: 267 Byte

Ein Arbeitsbeispiel ist 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()}

Hier ist ein vollständiges Programm (Leerzeichen zur besseren Lesbarkeit enthalten), das die Spielfunktion verwendet:

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;
        }
    }
}
Brian
quelle
2

Javascript: 307 216

Du kannst im Snippet unten spielen! Die Zahlen auf der linken Seite sind nur so, dass die Konsole (mindestens Chrom) die Zeilen nicht zusammenführt.

So führen Sie den Code aus:

  1. drücke "Code-Schnipsel ausführen"
  2. drücke ctrl-shift-j um die konsole zu öffnen
  3. Klicken Sie in den Ergebnisbereich
  4. benutze die Pfeiltasten und spiele

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();};

Nicht golfen:

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();
};

Edit 1: Lies die Regeln genauer durch und schreibe meinen Code entsprechend um

  • Der Amulett-Wert ist jetzt zufällig
  • Spieler kann nicht mehr aus dem Raum entkommen
  • Ich zähle die Zeichen in der Zeichenfunktion nicht mehr und rufe sie nicht mehr an
Eric Vincent
quelle
1

SpecBAS - 428 402 (ohne Druck, 466 425 wenn gezählt)

Bewegt sich mit Q / A / O / P nach oben / unten / links / rechts.

Die Zeile zum Drucken des Dungeons in Zeile 1 ist die einzige Zeile, die ignoriert werden kann.

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

Der Verweis auf # 34 ist nur eine kurze Möglichkeit, CHR $ (34) in den Code einzufügen.

Danke @Thomas Kwa, ich hatte nicht bemerkt, dass die Startposition des Spielers zufällig ist. Verwenden Sie auch separate IF-Anweisungen, um einige Zeichen zu entfernen.

Brian
quelle
Möglicherweise können Sie einige Zeichen speichern, indem Sie weniger gut randomisieren: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)und auch verwenden IF instead of ELSE IF.
Lirtosiast
1

Ein weiteres C #, 221 171 170

Hier ist ein anderer Weg in C # mit beiden Positionen zufällig. Wollte dies auch zeigen, wenn dieser Teil 7 Byte länger ist als die Lösung von Hand-E-Food.
Die Antwort von Hand-E-Food wird natürlich kürzer sein, sobald er Console.Read () verwendet.
Der Nachteil von Consol.Read ist, dass durch Drücken der Eingabetaste das Feld noch zweimal gedruckt wird.
Ich glaube jedoch nicht, dass es erforderlich ist, nur auf (echten) Eingaben zu drucken.

Die Navigation erfolgt mit 8426 wie in der Hand-E-Foods-Lösung.

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;
}
}
}


Bearbeiten: (neue Lösung hinzugefügt und PrinterClass an das Ende
verschoben ) Bearbeiten2: (eine 14 in eine 15 geändert und das Byte durch Beginnen von rechts unten gespeichert) Durch

Anpassen der Mauris-Technik ist es möglich, es in C # auf 171 Byte herunterzuschmelzen. (natürlich jetzt ohne beide Positionen zufällig):

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;
}
}
}

Die Druckerklasse ist fast gleich, nur eine neue Überladung von Druckern ...

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);
    }
}
Phil
quelle
1

Rubin, 185

Hier ist auch ein Ruby-Beispiel.
Ich bin sehr neu bei Ruby, vielleicht weiß jemand, wie man das besser macht :)

Ich habe lineFeeds als 1 gezählt, da das Programm sonst abstürzt ...

Die Navigation erfolgt über 8462. Sie müssen jedes Mal Eingaben mit der Eingabetaste senden.

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
Phil
quelle
0

QBasic, 103 Bytes

Gemäß den Regeln der Challenge ist das ShowUnterprogramm nicht in der Byte-Zählung enthalten, ebenso wenig wie der Show p, q, a, bAufruf (mit der folgenden neuen Zeile).

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

Um sich zu bewegen, geben Sie eine Zahl ein und drücken Sie die Eingabetaste: 1um nach links zu gehen, 2um nach oben 3zu gehen , um nach rechts 4zu gehen und um nach unten zu gehen.

Dieser Code gibt den Spielstatus am Ende nicht aus, wenn der Spieler das Amulett gefunden hat. Fügen Sie dazu Show p, q, a, bnach der IFAnweisung eine weitere hinzu .

Erläuterung

Lassen Sie a, bdie Koordinaten des Amuletts und p, qdie Koordinaten des Spielers. Der Spieler beginnt bei (0, 0), und das Amulett beginnt in Zeile 0 mit einer Spalte zwischen 1 und 9 (einschließlich), basierend auf der Ziffer 1 der aktuellen Zeit.

Der Rest ist nur ein Haufen Mathe mit Bedingungen. Es ist wichtig, sich daran zu erinnern, dass Bedingungen in QBasic 0für falsch, -1für wahr zurückgegeben werden. Sehen wir uns die Update-Anweisung für die Player-Zeile an:

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

Wenn m=2, wollen wir nach oben gehen, indem wir 1 von abziehen p, solange p>0. In ähnlicher Weise m=4möchten wir nach unten gehen, indem wir 1 zu hinzufügen p, solange p<4. Wir können das gewünschte Verhalten durch Multiplikation erhalten. Wenn beide Faktoren zutreffen -1, ist ihr Produkt das 1, von dem wir subtrahieren oder das wir addieren können p. Wenn eine der beiden Bedingungen erfüllt ist 0, hat das Produkt 0keine Auswirkung.

Ebenso lautet die Bedingung, um festzustellen, ob der Spieler das Amulett gefunden hat:

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

Wenn eine der Bedingungen wahr ist, ist ihre Summe ungleich Null (entweder -1oder -2) und somit wahr, und das Programm kehrt zu Zeile 1 zurück. Sobald sie pgleich aund qgleich sind b, sind beide Bedingungen erfüllt 0, so dass ihre Summe ist 0und der Kontrollfluss den erreichen kann Ende des Programms.

DLosc
quelle