NetHack adalah gim seperti roguelike di mana seorang pemain harus mengambil Amulet Yendor dari tingkat bawah tanah dungeon. Biasa dimainkan melalui telnet, seluruh permainan diwakili dengan grafik ASCII. Gim ini sangat menantang dan membutuhkan pengetahuan banyak mekanik gim agar berhasil.
Untuk keperluan tantangan ini, asumsikan bahwa seluruh ruang bawah tanah adalah satu tingkat dan hanya 5 × 16 karakter. Lebih jauh, anggaplah ini adalah penjara bawah tanah "aman" atau bahwa Anda hanya menerapkan prototipe — tidak akan ada monster, kekhawatiran tentang kelaparan, dll. Faktanya, Anda hanya harus melacak lokasi karakter dan jimat dan permainan akan secara efektif berakhir ketika pemain tiba di lokasi yang sama dengan jimat.
Persyaratan tantangan
- Akan ada penjara 5x16 (level tunggal).
- Berikan pemain lokasi awal (opsional acak) dan jimat acak terpisah (berbeda setiap kali program dijalankan) mulai kuadrat di dalam ruang bawah tanah. Yaitu, jimat tidak diperbolehkan untuk memulai di lapangan yang sama dengan pemain.
- Terima empat tombol input yang menggerakkan pemain satu kotak pada satu waktu (empat arah mata angin). Membaca / memproses input lain diperbolehkan (fungsi readline () yang membutuhkan penekanan 'enter', dll).
- Bepergian ke luar batas dungeon tidak diperbolehkan. Misalnya, jika pemain berada di tepi kanan bawah tanah, menekan kanan seharusnya tidak melakukan apa-apa.
- Setelah generasi awal dan setelah setiap gerakan, cetak status permainan. Karena ini adalah kode golf dan pencetakan agak tidak menarik, abaikan penghitungan karakter untuk fungsi cetak dan panggilan fungsi dengan asumsi tidak ada perubahan status . Sel kosong harus ditampilkan sebagai titik (
.
), jimat sebagai tanda kutip ganda ("
) dan karakter sebagai pada simbol (@
). - Permainan berakhir ketika pemain "menemukan" jimat (tiba di alun-alun yang sama)
Kemenangan
Ini adalah kode golf challenege, kode terpendek untuk memenuhi persyaratan satu minggu dari hari ini akan dinyatakan sebagai pemenang.
Contoh
Berikut adalah contoh solusi dalam C # (ungolfed) untuk menunjukkan persyaratan dasar dan output sampel.
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');
}
}
}
}
Jumlah karakter total adalah 1474, tetapi mengabaikan panggilan ke fungsi cetak dan definisinya adalah jumlah karakter akhir 896
.
Output ketika program dijalankan:
................
...."...........
..........@.....
................
................
Keluaran (termasuk di atas) setelah tombol 'a' ditekan dua kali:
................
...."...........
..........@.....
................
................
................
...."...........
.........@......
................
................
................
...."...........
........@.......
................
................
Jawaban:
TI-BASIC,
4241383635 byteUntuk kalkulator grafik TI-83 atau 84+ seri Anda.
Ke arah mana pemain akan pergi adalah fungsi dari kode kunci dari tombol yang ditekan, tetapi empat tombol yang pasti bekerja adalah ini pada baris atas:
Jimat dimulai pada salah satu dari lima kotak di kolom pertama, dan pemain mulai di kotak kanan bawah. Misalnya, pengaturan yang mungkin adalah:
Penjelasan
Posisi pemain disimpan sebagai bilangan kompleks dari
0+0i
ke15+4i
, di mana bagian nyata pergi ke kanan dan bagian imajiner turun. Ini memfasilitasi pemeriksaan batas yang mudah di bagian atas dan kiri: kita cukup mengimbangi jumlahnya sedikit dan berputar ke nol. Misalnya, jika offset0.5
dan posisi kita-1+3i
(dari layar ke kiri), maka posisi akan diperbaiki keiPart(-0.5+3.5i)=0+3i
, di mana seharusnya. Memeriksa batas bawah dan kanan sedikit lebih rumit; kita perlu mengurangi bilangan dari konstantaC
, yaitu sekitar15.635 + 4.093i
(ini yang terpendek yang dapat saya temukan di antara15+4i
dan16+5i
), bulat, kurangi dariC
lagi untuk membalikkan angka kembali, dan bulat lagi.Ketika suatu tombol ditekan, posisi pemain yang tidak disesuaikan akan bergerak sebanyak 1 unit dalam beberapa arah, tetapi bagian bilangan bulat hanya berubah ketika tombol-tombol tertentu ditekan. Untungnya, kunci yang berfungsi semuanya ada di baris paling atas. Di bawah ini adalah grafik dari offset dalam kasus-kasus di mana tombol 11, 12, 13, dan 15 ditekan, dan ketika tidak ada tombol yang ditekan (Tidak ada tekan adalah titik di dalam pusat persegi, menyebabkan bagian bilangan bulat tidak berubah; empat penekanan tombol 'offset memiliki bagian integer yang berbeda).
C
adalah palang merah di tengah lingkaran.Kode lama (42 byte):
Keterbatasan
Tidak ada cara untuk melarikan diri
"
karakter, jadi string dengan a"
tidak dapat dihasilkan di dalam suatu program. Oleh karena itu, ini menggunakan tanda umlaut¨
alih-alih kutipan (jika ada string yang sudah ada dengan tanda kutip, saya bisa menampilkannya). Untuk mendapatkan¨
dan@
dalam suatu program, diperlukan alat luar; Namun, itu valid TI-BASIC.sumber
CHIP-8 , 48 byte
Ini mungkin tidak dianggap legal, tapi kenapa tidak. Saya menulis program saya di CHIP-8, bahasa pemrograman berbasis bytecode untuk konsol game virtual. Anda dapat mencoba program lengkap (99 byte) di browser Anda menggunakan emulator / debugger yang saya tulis bernama Octo:
http://johnearnest.github.io/Octo/index.html?gist=1318903acdc1dd266469
Sebuah hex dump dari program lengkap itu adalah sebagai berikut:
Anda dapat memindahkan pemain dengan tombol ASWD, atau tombol 7589 pada keypad CHIP-8 asli. Jika saya menghapus semua kode dan data untuk menggambar latar belakang dan pemain, saya malah mendapatkan dump 48 byte ini:
Bentuk lengkap, tidak lengkap dari program ini ditulis dalam bahasa majelis tingkat tinggi sebagai berikut:
Perhatikan bahwa byte yang dikompilasi sendiri adalah bahasa pemrograman CHIP-8; assembler hanyalah cara yang lebih mudah untuk membuat program seperti itu.
sumber
Python 3, 86 byte
Hanya menghitung dua baris terbawah, dan jatuh
d();
.sumber
a=id(9)%79
dengana=id(9)%p
.raw_input
panggilan menjadi adilinput
.C,
122121115104102101 bytePertama kali memposting di sini! Saya harap Anda menyukainya :)
o
adalah fungsi pencetakan, erm,. Pahlawan pemberani kami dapat dipindah-pindahkan dengan 2, 4, 6 dan 8, tetapi jangan sampai tidak mengirim input lain (tidak ada baris baru!).Pembaruan 1: dibawa
a
dani
menjadimain
parameter.Pembaruan 2: OP telah mengkonfirmasi bahwa satu string input OK, saya singkirkan
scanf
(yang saya gunakan untuk melewati baris baru).Pembaruan 3: Menggunakan literal majemuk majemuk dan mengubah tata letak input. Program sekarang menjadi rusak jika Anda memasukkan arah yang tidak valid;)
Pembaruan 4: Melihat bahwa panggilan ke fungsi pencetakan tidak masuk hitungan. Mencatat untuk membaca aturan lebih hati-hati.
Pembaruan 5: satu byte disimpan, terima kasih kepada Mikkel Alan Stokkebye Christia.
sumber
!!(p%16)
jadip%16>0
? Saya tidak ingat urutan operasi saya.-
tidak bisa menahan dirip
, jadi tanda kurung diperlukan. The double-bang hanya kebingungan :)CJam,
464544403937 byteBaris pertama (menentukan fungsi yang mencetak status permainan saat ini) dan P di baris kedua (memanggil fungsi itu) tidak berkontribusi pada jumlah byte.
Posisi awal dan posisi jimat dipilih secara acak semu. Distribusi seragam dan PRNG yang mendasarinya memungkinkan.
Input adalah E, 6, 9dan Buntuk Up , Bawah , Kiri dan Kanan , dengan Caps Lockdiaktifkan, diikuti oleh Enter.
Versi alternatif
Dengan biaya empat byte lagi, format input ditingkatkan secara signifikan:
Pengujian
Karena I / O bersifat interaktif, Anda harus mencoba kode ini dengan Java interpreter .
Unduh versi terbaru dan jalankan program seperti ini:
Untuk menghindari menekan Entersetelah setiap tombol, dan untuk pembaruan output di tempat, Anda dapat menggunakan pembungkus ini:
Panggil seperti ini:
Versi utama
Versi alternatif
Fungsi P
sumber
Java, 231 byte (196 jika berfungsi)
Berikut kode program lengkapnya di 342:
Tanpa fungsi cetak, 231:
Jika suatu fungsi tidak apa-apa (saya tidak jelas dari spec), maka saya dapat memotongnya sedikit lebih jauh ke 196:
Dan dengan beberapa jeda baris untuk sedikit kejelasan ...
Perhatikan bahwa saya tidak menghitung fungsi cetak
p(p,y)
itu sendiri, tapi aku sedang menghitung panggilan untuk itu, karena saya memiliki hal-hal yang berubah dalam pernyataan panggilan.Ini bekerja dengan huruf kapital
ASDW
. Karena cara memeriksa untuk itu, beberapa surat lain mungkin juga berfungsi, tetapi spec tidak benar-benar mengatakan apa-apa tentang apa yang harus terjadi jika saya menekan tombol yang berbeda.sumber
void m()
menjadi()->
p+=
?Java, 574 byte
Pada dasarnya sama dengan versi C #, kecuali dikaburkan & diminimalkan.
sumber
Julia, 161 byte
Penggunaan w, a, s, dan duntuk bergerak ke atas, kiri, bawah, dan kanan, masing-masing.
Kode lengkap, termasuk pencetakan (330 byte):
Kode yang dicetak, tidak termasuk pencetakan (161 byte):
Perbedaannya di sini adalah bahwa kita tidak menyimpan status permainan sebagai matriks; semua informasi yang relevan terkandung dalam array
c
dana
. Dan, tentu saja, tidak ada yang dicetak. Pengguna tidak akan lagi diminta untuk input setelah pemain mencapai jimat.Penjelasan + ungolfed (kode lengkap):
sumber
a=[rand(1:5),1] c=a+1
Batch, 329 Bytes
sumber
Microsoft Windows [Version 6.1.7601]
Microsoft Windows [Version 6.2.9200]
)Perl,
228222 karakter (tidak termasuk baris baru yang tidak terpisahkan dengan cara kerja kode) - 207 jika tidak menghitungprint
danprint if
pernyataan bagian yang digunakan untuk mencetak, tetapi jangan menambah logika permainan; 144 jika juga mempertimbangkan kode generasi representasi lapangan sebagai bagian dari pencetakan, seperti yang disarankan oleh Yakk dalam komentar)Kode ini menggunakan wasd huruf kecil untuk kontrol; input harus dikonfirmasi dengan Enter. Diuji dengan Perl 5.14.2.
Perhatikan bahwa untuk kode ini, tidak mungkin memisahkan perhitungan dan pencetakan, karena operasi dilakukan langsung pada representasi yang dicetak menggunakan ekspresi reguler.
Penjelasan:
Baris ini menentukan posisi pemain dan jimat. Posisi pemain ditentukan oleh
$==rand(80)
dan sebenarnya mudah dipahami: Pada papan 5 × 16, ada 80 posisi berbeda di mana pemain bisa berada. Posisi disimpan dalam$=
variabel yang memaksa nilai yang disimpan ke dalam integer; ini menghemat beberapa byte karena tidak perlu secara eksplisit melemparkan hasilnya ke integer (rand
memberikan nilai floating point).Karena salah satu posisi sudah ditempati oleh pemain, hanya ada 79 posisi yang tersisa untuk jimat, oleh karena itu untuk posisi jimat,
$a=$==rand(79)
digunakan. Sekali lagi, penugasan untuk$=
memaksa konversi ke integer, namun saya selanjutnya menugaskannya$a
untuk menggunakan kembali$=
posisi pemain.Sekarang untuk menghindari jimat untuk menempati posisi yang sama dengan pemain, ia maju dengan satu posisi jika posisinya setidaknya sama besar dengan pemain, memberikan distribusi seragam pada tempat-tempat yang tidak ditempati oleh pemain. Ini dicapai dengan di
$a = ($a >= $=)
mana$=
posisi pemain di sini. Sekarang baris pertama dihasilkan dengan memasukkan dua penugasan awal alih-alih$a$ and the only
$ pertama `dalam ekspresi ini.Ini menghasilkan bidang awal, dan kemudian mencetak adalah.
("."x80)
hanya menghasilkan string 80 titik.=~s/(.{$=})./\1@/r
kemudian menggantikan$=
karakter th dengan@
, dan=~s/(.{$=})./\1@/r
yang$a
karakter th dengan"
. Karenar
pengubah mereka tidak mencoba untuk memodifikasi di tempat, tetapi mengembalikan string yang dimodifikasi, itu sebabnya mereka dapat diterapkan ke ekspresi sebelumnya. Akhirnya,=~s/(.{16})/\1\n/gr
masukkan baris baru setiap 16 karakter. Perhatikan bahwa bidang disimpan dalam variabel khusus$_
yang dapat digunakan secara implisit dalam pernyataan selanjutnya.Ini menciptakan hash yang berisi aturan penggantian untuk gerakan yang berbeda. Versi yang lebih mudah dibaca dari ini adalah
Kunci adalah karakter untuk bergerak, dan nilainya adalah string yang berisi aturan penggantian yang sesuai.
Ini adalah loop utama.
while(/"/)
memeriksa apakah masih ada"
karakter di$_
(yaitu, di lapangan). Jika kita pindah ke jimat, karakternya akan diganti dengan karakter pemain sehingga menghilang dari lapangan.eval $r{getc STDIN}
membaca karakter dari input standar, mencari aturan penggantian yang sesuai dari has%r
dan berlaku untuk$_
, yaitu, bidang. Ini mengevaluasi ke true jika pengganti benar-benar dibuat (yaitu, kuncinya ditemukan di hash dan langkah itu mungkin; langkah yang mustahil tidak akan cocok dengan aturan penggantian). Dalam halprint
ini dieksekusi. Karena disebut tanpa argumen, ia mencetak$_
, yaitu bidang yang dimodifikasi.sumber
("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/gr
cukup dekat pada pandangan pertama, tetapi perl-fu saya beberapa tahun berkarat. Saya bisa melewatkan perubahan negara di sana.C #,
256 248 234 227 226225 byteMenggunakan panah NumPad dengan NumLock dihidupkan untuk bergerak.
Diindentasi dan dikomentari untuk kejelasan:
sumber
Main
metode ini tidak harus dipanggilMain
, sehingga Anda dapat mencukur tiga karakter lainnya.Html + JavaScript (ES6), skor mungkin 217
Terlalu panjang, tetapi dapat dimainkan online di cuplikan di bawah ini.
Baris 6 (Nilai T. ...) adalah untuk keluaran dan tidak dihitung (tetapi untuk kesederhanaan saya menghitung teks adalah tag buka dan tutup, bahkan jika itu keluaran juga)
Adapun keacakan: jimat selalu di bagian kanan kotak dan pemain selalu mulai di bagian kiri.
Klik pada textArea (setelah memperbesar) untuk memulai dan memulai ulang gim.
Cuplikan EcmaScript 6 (khusus Firefox)
Cuplikan EcmaScript 5 (diuji di Chrome)
sumber
Actionscript 3: 267 bytes
Contoh yang berfungsi adalah 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()}
Berikut adalah program lengkap (ruang putih termasuk untuk keterbacaan) menggunakan fungsi game:
sumber
Javascript:
307216Anda dapat bermain di cuplikan di bawah ini! Angka-angka di sebelah kiri hanya agar konsol (setidaknya satu chrome) tidak menggabungkan baris.
Untuk menjalankan kode:
Tidak golf:
Sunting 1: Baca aturan lebih hati-hati dan tulis ulang kode saya sesuai
sumber
SpecBAS -
428402 (tidak termasuk pencetakan,466425 saat dihitung)Gunakan Q / A / O / P untuk bergerak masing-masing ke atas / bawah / kiri / kanan.
Garis untuk mencetak ruang bawah tanah pada baris 1 adalah satu-satunya garis yang dapat diabaikan, tetapi juga menurunkannya.
Referensi ke # 34 hanyalah cara singkat memasukkan CHR $ (34) dalam kode.
Terima kasih @Thomas Kwa, saya tidak melihat posisi awal pemain secara acak adalah opsional. Juga menggunakan pernyataan IF terpisah untuk memangkas beberapa karakter.
sumber
2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)
dan juga menggunakanIF instead of ELSE IF
.C # lain,
221171170Berikut ini cara lain dalam C # dengan kedua posisi acak. Ingin menunjukkan ini walaupun bagian ini lebih panjang 7 byte dari solusi Hand-E-Food.
Jawaban Hand-E-Food akan lebih pendek tentu saja begitu dia akan menggunakan Console.Read ().
Kelemahan dari Consol.Read adalah, bahwa menekan Enter yang diperlukan menyebabkan bidang dicetak 2 kali lagi.
Tapi saya tidak berpikir ada persyaratan untuk mencetak hanya pada input (nyata).
Navigasi dilakukan oleh 8426 seperti pada solusi Hand-E-Foods.
Sunting: (menambahkan solusi baru dan memindahkan PrinterClass ke ujung)
Sunting2: (mengubah 14 menjadi 15 dan menyimpan byte dengan mulai dari kanan bawah)
Menyesuaikan teknik Mauris adalah mungkin untuk mencairkannya ke 171 byte dalam C # (tentu saja sekarang tanpa kedua posisi acak):
Kelas Printer hampir sama, hanya kelebihan cetak baru ...
sumber
Ruby, 185
Ini adalah contoh Ruby juga.
Saya sangat baru di Ruby, mungkin ada yang tahu bagaimana melakukannya dengan lebih baik :)
Saya telah menghitung lineFeeds sebagai 1 karena Program akan macet jika tidak ...
Navigasi dilakukan oleh 8462. Anda harus mengirim input setiap kali dengan memasukkan.
sumber
QBasic, 103 byte
Sesuai aturan tantangan,
Show
subprogram tidak termasuk dalam byte-count, jugaShow p, q, a, b
panggilan (dengan baris baru berikut).Untuk bergerak, masukkan nomor dan tekan Enter:
1
untuk ke kiri,2
untuk naik,3
untuk ke kanan, dan4
untuk turun.Kode ini tidak menampilkan status permainan di akhir, ketika pemain telah menemukan jimat. Untuk membuatnya, tambahkan yang lain
Show p, q, a, b
setelahIF
pernyataan.Penjelasan
Biarkan
a
,b
mewakili koordinat jimat danp
,q
koordinat pemain. Pemain mulai dari (0, 0), dan jimat dimulai pada baris 0, dengan kolom antara 1 dan 9, inklusif, berdasarkan pada angka 1 dari waktu saat ini.Sisanya hanya sekelompok matematika dengan persyaratan. Yang penting untuk diingat adalah bahwa persyaratan dalam QBasic mengembalikan
0
untuk false,-1
untuk true. Mari kita lihat pernyataan pembaruan baris pemain:Jika
m=2
, kami ingin naik dengan mengurangi 1 darip
, selamap>0
. Demikian pula, jikam=4
, kami ingin pindah ke bawah dengan menambahkan 1p
, asalkanp<4
. Kita dapat memperoleh perilaku yang diinginkan dengan mengalikan. Jika kedua faktor tersebut-1
, produk mereka akan1
, yang dapat kita kurangi atau tambahkanp
. Jika salah satu kondisional adalah0
, produk akan0
, tanpa efek.Demikian pula, syarat untuk menentukan apakah pemain telah menemukan jimat adalah:
Jika salah satu dari kondisi tersebut benar, jumlah mereka akan menjadi nol (baik
-1
atau-2
) dan dengan demikian benar, dan program kembali ke baris 1. Sekalip
samaa
danq
samab
, kedua kondisi akan0
, sehingga jumlah mereka akan0
dan aliran kontrol dapat mencapai akhir program.sumber