NetHack Minimal

64

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:

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

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

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

sumber
10
Saya merasa ini akan menarik bagi @Doorknob.
Alex A.
10
Rogue adalah gim seperti roguelike asli di mana seorang pemain harus mengambil Amulet Yendor dari tingkat bawah tanah dungeon. Mengapa tidak menyebutnya Rogue minimal?
Gilles 'SANGAT berhenti menjadi jahat'
5
@Gilles Mengapa tidak menyebut ini ular minimal?
Casey Kuball
26
Psshh, tidak ada gerakan diagonal? Tidak ada yubnhjkl? Bahkan tidak naik tangga untuk naik setelah mendapatkan jimat? : P ( lagipula
naik turun
2
@tolos: Saya masih tidak jelas apa yang dianggap sebagai acak di sini. Sangat tidak mungkin untuk memenuhi perbedaan setiap kali program dijalankan persyaratan jika program dijalankan 80 kali ... Secara khusus, dalam jawaban ini , jimat hanya dapat menempati 9 dari semua 79 lokasi yang mungkin. Apakah itu masuk hitungan?
Dennis

Jawaban:

37

TI-BASIC, 42 41 38 36 35 byte

Untuk kalkulator grafik TI-83 atau 84+ seri Anda.

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

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:

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

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+0ike 15+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 offset 0.5dan posisi kita -1+3i(dari layar ke kiri), maka posisi akan diperbaiki ke iPart(-0.5+3.5i)=0+3i, di mana seharusnya. Memeriksa batas bawah dan kanan sedikit lebih rumit; kita perlu mengurangi bilangan dari konstanta C, yaitu sekitar 15.635 + 4.093i(ini yang terpendek yang dapat saya temukan di antara 15+4idan 16+5i), bulat, kurangi dari Clagi 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). Cadalah palang merah di tengah lingkaran.

masukkan deskripsi gambar di sini

Kode lama (42 byte):

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

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.

lirtosiast
sumber
2
Hanya untuk bersenang-senang, saya membuat cuplikan ini yang menempatkan diaeresis dan simbol @ di Str1 (sebagai lawan dari 'alat luar'). Pilih garis di atas yang cocok dengan kalkulator Anda, masukkan ke dalam program baru, dan jalankan program itu dengan Asm (.
MI Wright
Oh, saya lupa tentang pengkodean dalam kode mesin pada kalkulator. Jangan 'ingin membuat crash milik saya dengan kesalahan ketik, tapi saya percaya itu berhasil.
lirtosiast
44

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:

Tangkapan layar

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

Sebuah hex dump dari program lengkap itu adalah sebagai berikut:

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

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:

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

Bentuk lengkap, tidak lengkap dari program ini ditulis dalam bahasa majelis tingkat tinggi sebagai berikut:

: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

Perhatikan bahwa byte yang dikompilasi sendiri adalah bahasa pemrograman CHIP-8; assembler hanyalah cara yang lebih mudah untuk membuat program seperti itu.

JohnE
sumber
19
Alat yang tepat untuk pekerjaan itu.
Dennis
6
+1 karena membuat saya membuang banyak waktu untuk memainkan game Anda berulang kali.
Alex A.
4
@AlexA. jika Anda ingin membuang lebih banyak waktu Anda harus mencoba Cave Explorer . Pindah ASWD di dunia luar dan QE digunakan untuk mengatur ulang / memindahkan blok di level platformer.
JohnE
4
Hebat, ya sudah akhir pekan saya.
Alex A.
1
Awalnya saya skeptis, tetapi Cave Explorer menyenangkan dan CHIP-8 sudah ada jauh lebih lama dari yang saya duga. Jadi saya rasa saya harus belajar ini.
10

Python 3, 86 byte

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]

Hanya menghitung dua baris terbawah, dan jatuh d();.

Lynn
sumber
Saya menyimpan byte lain dengan memulai pemain di sudut kanan bawah (kotak "terakhir"), lalu secara acak mengambil sampel dari 79 kotak pertama .
Lynn
Ups, maaf, sudah diperbaiki! Saya kira saya tidak luar biasa dalam menghitung byte secara manual. : <
Lynn
1
Saya pikir Anda dapat menyimpan karakter lain dengan menggantinya a=id(9)%79dengan a=id(9)%p.
kirbyfan64sos
@ kirbyfan64sos Cemerlang! Terima kasih.
Lynn
1
Juga, jika Anda membuat ini untuk Python 3, Anda dapat mengubah raw_inputpanggilan menjadi adil input.
kirbyfan64sos
10

C, 122 121 115 104 102 101 byte

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

Pertama kali memposting di sini! Saya harap Anda menyukainya :)

oadalah 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 adan imenjadi mainparameter.

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.

Quentin
sumber
Bisa !!(p%16)jadi p%16>0? Saya tidak ingat urutan operasi saya.
lirtosiast
@ThomasKwa, tapi unary -tidak bisa menahan diri p, jadi tanda kurung diperlukan. The double-bang hanya kebingungan :)
Quentin
@Quentin 3 & getchar () / 2 <getchar () / 2-25
Mikkel Alan Stokkebye Christia
@MikkelAlanStokkebyeChristia terima kasih :)
Quentin
9

CJam, 46 45 44 40 39 37 byte

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

Baris 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

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

Dengan biaya empat byte lagi, format input ditingkatkan secara signifikan:

  • Versi ini menerima 8, 2, 4dan 6untuk Up , Bawah , Kiri dan Kanan , yang cocok dengan tombol panah yang sesuai pada papan angka tersebut.
  • Hal ini juga menerima 7, 9, 1dan 3untuk bergerak diagonal yang sesuai.

Pengujian

Karena I / O bersifat interaktif, Anda harus mencoba kode ini dengan Java interpreter .

Unduh versi terbaru dan jalankan program seperti ini:

java -jar cjam-0.6.5.jar nethack.cjam

Untuk menghindari menekan Entersetelah setiap tombol, dan untuk pembaruan output di tempat, Anda dapat menggunakan pembungkus ini:

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

Panggil seperti ini:

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

Versi utama

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.

Versi alternatif

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.

Fungsi 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
sumber
2
Saya tepat di belakang Anda dengan TI-BASIC! Saya akan memposting setelah saya memverifikasi solusi saya.
lirtosiast
8

Java, 231 byte (196 jika berfungsi)

Berikut kode program lengkapnya di 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":""));}}}

Tanpa fungsi cetak, 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);}}

Jika suatu fungsi tidak apa-apa (saya tidak jelas dari spec), maka saya dapat memotongnya sedikit lebih jauh ke 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);}

Dan dengan beberapa jeda baris untuk sedikit kejelasan ...

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

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.

Geobit
sumber
Saya lebih suka memformat nested operator ternary pada tingkat indentasi yang sama, seperti yang Anda lakukan pada rantai if / else if. Ini lebih mudah dibaca.
lirtosiast
@ThomasKwa Ya, saya pernah melakukannya dua kali. Ini lebih seperti pernyataan bersarang jika daripada dirantai. Rasanya lebih baik bagi saya karena kedua bagian dari masing-masing ternary berada pada tingkat yang sama, tetapi berbeda dari yang lain.
Geobits
Jika fungsi anonim dapat diterima, Anda dapat memangkas jawaban Anda menjadi 192 byte: void m()menjadi()->
ankh-morpork
@ dohaqatar7 Ya, tapi saya tidak menggunakan fungsi anon Java untuk kode golf. Saya merasa teduh pada prinsipnya, apakah orang lain merasakan hal yang sama atau tidak.
Geobits
Bisakah kamu melakukannya p+=?
lirtosiast
5

Java, 574 byte

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

Pada dasarnya sama dengan versi C #, kecuali dikaburkan & diminimalkan.

tahap
sumber
begitu banyak ruang yang tidak perlu ...;)
Will
@Apakah saya baru saja memperbaikinya: P
fase
1
Juga, gunakan nama dan terner satu huruf.
lirtosiast
@ThomasKwa diperbaiki: D
fase
6
Masih ada banyak ruang yang tidak perlu dan kurangnya terner;)
Will
5

Julia, 161 byte

Penggunaan w, a, s, dan duntuk bergerak ke atas, kiri, bawah, dan kanan, masing-masing.

Kode lengkap, termasuk pencetakan (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

Kode yang dicetak, tidak termasuk pencetakan (161 byte):

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

Perbedaannya di sini adalah bahwa kita tidak menyimpan status permainan sebagai matriks; semua informasi yang relevan terkandung dalam array cdan a. Dan, tentu saja, tidak ada yang dicetak. Pengguna tidak akan lagi diminta untuk input setelah pemain mencapai jimat.


Penjelasan + ungolfed (kode lengkap):

# 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.
sumber
Saya pikir itu baik
3
+1 untuk versi terkompresi / dikaburkan tampak sangat mirip dengan apa yang saya ingat dari kode sumber nethack yang sebenarnya.
Ben Jackson
Anda dapat menyimpan beberapa byte dengan menggunakan pengacakan yang lebih buruk:a=[rand(1:5),1] c=a+1
lirtosiast
@ThomasKwa: Apa yang menyenangkan jika selalu ada di baris pertama? :)
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
sumber
Ini sangat mengesankan. Saya terkejut mungkin melakukan ini.
eis
Ini tidak menampilkan penjara bawah tanah untuk saya, hanya serangkaian garis yang meminta [W, A, S, D] ?. Tampaknya "bekerja" - berjalan di ruang bawah tanah yang tidak terlihat akhirnya keluar. win7 cmd.exe
Dan Pritts
Ini bekerja untuk saya dengan Win7 cmd.exe - ketika saya mengetik ver saya dapatkanMicrosoft Windows [Version 6.1.7601]
Jerry Jeremiah
@DanPritts Aneh. Ini berfungsi dengan baik untuk saya di Windows 8 ( Microsoft Windows [Version 6.2.9200])
ankh-morpork
doh, saya belum menyalin & menempel semuanya, saya tidak gulir ke bawah di jendela. Sudah selesai dilakukan dengan baik.
Dan Pritts
3

Perl, 228 222 karakter (tidak termasuk baris baru yang tidak terpisahkan dengan cara kerja kode) - 207 jika tidak menghitung printdan print ifpernyataan 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.

($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}}

Perhatikan bahwa untuk kode ini, tidak mungkin memisahkan perhitungan dan pencetakan, karena operasi dilakukan langsung pada representasi yang dicetak menggunakan ekspresi reguler.

Penjelasan:

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

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 ( randmemberikan 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 $auntuk 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.

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

Ini menghasilkan bidang awal, dan kemudian mencetak adalah. ("."x80)hanya menghasilkan string 80 titik. =~s/(.{$=})./\1@/rkemudian menggantikan $=karakter th dengan @, dan =~s/(.{$=})./\1@/ryang $akarakter th dengan ". Karena rpengubah 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/grmasukkan baris baru setiap 16 karakter. Perhatikan bahwa bidang disimpan dalam variabel khusus $_yang dapat digunakan secara implisit dalam pernyataan selanjutnya.

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

Ini menciptakan hash yang berisi aturan penggantian untuk gerakan yang berbeda. Versi yang lebih mudah dibaca dari ini adalah

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

Kunci adalah karakter untuk bergerak, dan nilainya adalah string yang berisi aturan penggantian yang sesuai.

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

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 %rdan 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 hal printini dieksekusi. Karena disebut tanpa argumen, ia mencetak $_, yaitu bidang yang dimodifikasi.

celtschk
sumber
1
Hanya karena Anda memasukkan umpan baris agar dapat dibaca bukan berarti Anda harus menghitungnya. Saya melihat 228 byte. Selain itu, sesuai aturan khusus pertanyaan ini, bagian pencetakan kode Anda tidak berkontribusi pada jumlah byte.
Dennis
@Dennis: Untuk bagian pencetakan, lihat penjelasan yang sekarang saya tambahkan: Anda tidak dapat memisahkan pencetakan dan evaluasi secara bermakna dalam kode saya. Saya sekarang mengubah penghitungan seperti yang Anda sarankan.
celtschk
Apakah ada perubahan status pada kode pencetakan Anda? Tidak? Nah, menurut saya, menggunakan kembali output kode pencetakan Anda untuk logika Anda seharusnya tidak menghukum Anda. Kode gerakan (yang berbeda!) Harus dihitung, tetapi kode yang menghasilkan "string tampilan" tidak boleh dihitung.
Yakk
@ Yakk: Bagian mana dari kode saya yang Anda anggap sebagai kode pencetakan? (Sebenarnya pendapat saya adalah mengecualikan kode pencetakan dari penghitungan adalah ide yang buruk, tepatnya karena itu tidak selalu didefinisikan dengan baik apa "kode pencetakan" itu.)
celtschk
@celtschk ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grcukup dekat pada pandangan pertama, tetapi perl-fu saya beberapa tahun berkarat. Saya bisa melewatkan perubahan negara di sana.
Yakk
2

C #, 256 248 234 227 226 225 byte

Menggunakan panah NumPad dengan NumLock dihidupkan untuk bergerak.

Diindentasi dan dikomentari untuk kejelasan:

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();
        }
    }
}
Makanan Tangan
sumber
1
Saya pikir C # ints secara implisit init ke nol. Juga (tidak dapat memeriksa saat ini) jika casting bukan masalah Anda dapat mengkonversi literal karakter ke int, atau setidaknya 'a' ke 97 (saya pikir) meskipun yang lain adalah tiga digit.
Hanya bidang kelas yang diinisialisasi secara default, dan yang mengharuskan mereka dinyatakan statis dalam kasus ini. Variabel metode harus diinisialisasi sebelum digunakan pertama kali. Itu membutuhkan lebih sedikit karakter: 4 vs 7.
Hand-E-Food
Terima kasih @tolos untuk tip tentang casting char ke int secara implisit! Lebih baik lagi, jika saya menggunakan enum cast ConsoleKey sebagai int, saya bisa menggunakan nilai 2 digit.
Hand-E-Food
Secara teknis, Mainmetode ini tidak harus dipanggil Main, sehingga Anda dapat mencukur tiga karakter lainnya.
Luaan
@Luaan, saya pikir Anda salah. Dokumentasi C #: msdn.microsoft.com/en-us/library/acy3edy3.aspx
Hand-E-Food
2

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.

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

Cuplikan EcmaScript 6 (khusus 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>

Cuplikan EcmaScript 5 (diuji di 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>

edc65
sumber
2

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:

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

Javascript: 307 216

Anda dapat bermain di cuplikan di bawah ini! Angka-angka di sebelah kiri hanya agar konsol (setidaknya satu chrome) tidak menggabungkan baris.

Untuk menjalankan kode:

  1. tekan "jalankan potongan kode"
  2. tekan ctrl-shift-j untuk membuka konsol
  3. klik di bagian hasil
  4. gunakan tombol panah dan mainkan

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

Tidak golf:

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

Sunting 1: Baca aturan lebih hati-hati dan tulis ulang kode saya sesuai

  • nilai jimat y sekarang diacak
  • pemain tidak bisa lagi keluar kamar
  • Saya tidak lagi menghitung karakter dalam fungsi menggambar atau memanggilnya
Eric Vincent
sumber
1

SpecBAS - 428 402 (tidak termasuk pencetakan, 466 425 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.

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

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.

Brian
sumber
Anda mungkin dapat menyimpan beberapa karakter dengan mengacak dengan kurang baik: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)dan juga menggunakan IF instead of ELSE IF.
lirtosiast
1

C # lain, 221 171 170

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

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


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

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

Kelas Printer hampir sama, hanya kelebihan cetak baru ...

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

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.

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

QBasic, 103 byte

Sesuai aturan tantangan, Showsubprogram tidak termasuk dalam byte-count, juga Show p, q, a, bpanggilan (dengan baris baru berikut).

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

Untuk bergerak, masukkan nomor dan tekan Enter: 1untuk ke kiri, 2untuk naik, 3untuk 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, bsetelah IFpernyataan.

Penjelasan

Biarkan a, bmewakili koordinat jimat dan p, qkoordinat 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 0untuk false, -1untuk true. Mari kita lihat pernyataan pembaruan baris pemain:

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

Jika m=2, kami ingin naik dengan mengurangi 1 dari p, selama p>0. Demikian pula, jika m=4, kami ingin pindah ke bawah dengan menambahkan 1 p, asalkan p<4. Kita dapat memperoleh perilaku yang diinginkan dengan mengalikan. Jika kedua faktor tersebut -1, produk mereka akan 1, yang dapat kita kurangi atau tambahkan p. Jika salah satu kondisional adalah 0, produk akan 0, tanpa efek.

Demikian pula, syarat untuk menentukan apakah pemain telah menemukan jimat adalah:

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

Jika salah satu dari kondisi tersebut benar, jumlah mereka akan menjadi nol (baik -1atau -2) dan dengan demikian benar, dan program kembali ke baris 1. Sekali psama adan qsama b, kedua kondisi akan 0, sehingga jumlah mereka akan 0dan aliran kontrol dapat mencapai akhir program.

DLosc
sumber