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':
................
...."...........
..........@.....
................
................
................
...."...........
.........@......
................
................
................
...."...........
........@.......
................
................
Antworten:
TI-BASIC,
4241383635 BytesFür Ihren Grafikrechner der Serie TI-83 oder 84+.
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:
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+0i
bis gespeichert15+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 Versatz0.5
und unsere Position-1+3i
(außerhalb des Bildschirms links) sind, wird die Position dahin korrigiertiPart(-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 subtrahierenC
, die ungefähr15.635 + 4.093i
(die kürzeste, die ich zwischen15+4i
und finden konnte16+5i
) ist, runden, vonC
erneut 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).
C
ist das rote Kreuz in der Mitte des Kreises.Alter Code (42 Bytes):
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.quelle
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:
http://johnearnest.github.io/Octo/index.html?gist=1318903acdc1dd266469
Ein hexadezimaler Speicherauszug dieses vollständigen Programms lautet wie folgt:
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:
Die ungelöste, vollständige Form des Programms wurde in einer höheren Assemblersprache wie folgt geschrieben:
Beachten Sie, dass die kompilierten Bytes selbst die Programmiersprache CHIP-8 sind. Der Assembler ist einfach ein bequemeres Mittel zum Erstellen solcher Programme.
quelle
Python 3, 86 Bytes
Nur die beiden untersten Zeilen zählen und fallen lassen
d();
.quelle
a=id(9)%79
mita=id(9)%p
.raw_input
Aufruf auch in "Nur" änderninput
.C,
122121115104102101 BytesZum ersten Mal hier posten! Ich hoffe du magst es :)
o
ist 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
a
undi
inmain
die 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.
quelle
!!(p%16)
seinp%16>0
? Ich erinnere mich nicht an meine Arbeitsreihenfolge.-
kann nicht anders, als zu bleibenp
, so dass Klammern in beiden Richtungen benötigt werden. Der Doppelknall ist nur Verschleierung :)CJam,
464544403937 BytesDie 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
Auf Kosten von vier weiteren Bytes wird das Eingabeformat erheblich verbessert:
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:
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:
Rufen Sie wie folgt auf:
Hauptversion
Alternative Version
Funktion P
quelle
Java, 231 Bytes (196 wenn Funktion)
Hier ist der vollständige Programmcode bei 342:
Ohne die Druckfunktion 231:
Wenn nur eine Funktion in Ordnung ist (mir ist aus der Spezifikation nicht klar), kann ich dies ein bisschen weiter auf 196 reduzieren:
Und mit einigen Zeilenumbrüchen für ein bisschen Klarheit ...
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.quelle
void m()
()->
p+=
?Java, 574 Bytes
Grundsätzlich das Gleiche wie die C # -Version, außer verschleiert und minimiert.
quelle
Julia, 161 Bytes
Uses w, a, s, und dnach oben, links, unten, bzw. rechts.
Vollständiger Code, einschließlich Drucken (330 Byte):
Scored Code, ohne Drucken (161 Bytes):
Der Unterschied besteht darin, dass wir den Spielstatus nicht als Matrix speichern. Alle relevanten Informationen sind in den Arrays
c
und enthaltena
. 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):
quelle
a=[rand(1:5),1] c=a+1
Batch, 329 Bytes
quelle
Microsoft Windows [Version 6.1.7601]
Microsoft Windows [Version 6.2.9200]
)Perl,
228222 Zeichen (ohne die Zeilenumbrüche, die für die Funktionsweise des Codes nicht von Belang sind) - 207 wenn die Teileprint
undprint if
Anweisungen, 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.
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:
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 (rand
liefert 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 ,$a
um 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 .Dadurch wird das Anfangsfeld generiert und anschließend gedruckt.
("."x80)
generiert nur eine Zeichenfolge von 80 Punkten.=~s/(.{$=})./\1@/r
Ersetzt dann das$=
th Zeichen mit@
und=~s/(.{$=})./\1@/r
das$a
th Zeichen mit"
. Aufgrund desr
Modifikators 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/gr
fü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.Dadurch wird ein Hash erstellt, der die Ersetzungsregeln für die verschiedenen Züge enthält. Eine besser lesbare Version davon ist
Die Tasten sind die Zeichen für die Züge, und die Werte sind Zeichenfolgen, die die entsprechende Ersetzungsregel enthalten.
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%r
und 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 Fallprint
wird ausgeführt. Da es ohne Argument aufgerufen$_
wird, gibt es das geänderte Feld aus.quelle
("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/gr
ist auf den ersten Blick ziemlich nah, aber mein Perl-Fu ist ein paar Jahre rostig. Ich hätte dort einen Zustandswechsel verpassen können.C #,
256 248 234 227 226225 BytesVerwendet die NumPad-Pfeile, wenn NumLock aktiviert ist, um sich zu bewegen.
Zur Verdeutlichung eingerückt und kommentiert:
quelle
Main
Methode nicht aufgerufen werdenMain
, sodass Sie drei weitere Zeichen abschneiden können.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.
EcmaScript 6-Snippet (nur Firefox)
EcmaScript 5-Snippet (in Chrome getestet)
quelle
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:
quelle
Javascript:
307216Du 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:
Nicht golfen:
Edit 1: Lies die Regeln genauer durch und schreibe meinen Code entsprechend um
quelle
SpecBAS -
428402 (ohne Druck,466425 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.
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.
quelle
2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)
und auch verwendenIF instead of ELSE IF
.Ein weiteres C #,
221171170Hier 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.
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):
Die Druckerklasse ist fast gleich, nur eine neue Überladung von Druckern ...
quelle
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.
quelle
QBasic, 103 Bytes
Gemäß den Regeln der Challenge ist das
Show
Unterprogramm nicht in der Byte-Zählung enthalten, ebenso wenig wie derShow p, q, a, b
Aufruf (mit der folgenden neuen Zeile).Um sich zu bewegen, geben Sie eine Zahl ein und drücken Sie die Eingabetaste:
1
um nach links zu gehen,2
um nach oben3
zu gehen , um nach rechts4
zu 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, b
nach derIF
Anweisung eine weitere hinzu .Erläuterung
Lassen Sie
a
,b
die Koordinaten des Amuletts undp
,q
die 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
0
für falsch,-1
für wahr zurückgegeben werden. Sehen wir uns die Update-Anweisung für die Player-Zeile an:Wenn
m=2
, wollen wir nach oben gehen, indem wir 1 von abziehenp
, solangep>0
. In ähnlicher Weisem=4
möchten wir nach unten gehen, indem wir 1 zu hinzufügenp
, solangep<4
. Wir können das gewünschte Verhalten durch Multiplikation erhalten. Wenn beide Faktoren zutreffen-1
, ist ihr Produkt das1
, von dem wir subtrahieren oder das wir addieren könnenp
. Wenn eine der beiden Bedingungen erfüllt ist0
, hat das Produkt0
keine Auswirkung.Ebenso lautet die Bedingung, um festzustellen, ob der Spieler das Amulett gefunden hat:
Wenn eine der Bedingungen wahr ist, ist ihre Summe ungleich Null (entweder
-1
oder-2
) und somit wahr, und das Programm kehrt zu Zeile 1 zurück. Sobald siep
gleicha
undq
gleich sindb
, sind beide Bedingungen erfüllt0
, so dass ihre Summe ist0
und der Kontrollfluss den erreichen kann Ende des Programms.quelle