Minimal NetHack


64

NetHack , bir oyuncunun zindanın en alt seviyesinden Yendor Amuletini alması gereken bir oyun. Yaygın olarak telnet üzerinden oynanan tüm oyun ASCII grafikleriyle temsil edilir. Oyun son derece zorlu ve başarılı olmak için birçok oyun mekaniği bilgisi gerektirir.

Bu zorluğun amaçları doğrultusunda, tüm zindanın tek bir seviye ve sadece 5 x 16 karakter olduğunu varsayalım. Dahası, bunun "güvenli" bir zindan olduğunu veya yalnızca bir prototip uyguladığınızı varsayalım - canavarlar, açlık endişeleri olmayacak, vs.. oyuncu muska ile aynı yere geldiğinde etkili bir şekilde sona erecek.

Zorluk şartları

  • 5 × 16 zindan olacak (tek seviye).
  • Oyuncuya bir başlangıç ​​konumu verin (isteğe bağlı olarak rastgele) ve muska, zindanın içinde başlayan kareye ayrı bir rasgele (programın her çalıştırılışında farklı) verin. Yani, muska, oyuncuyla aynı meydanda başlamaz.
  • Müzikçaları bir defada bir kare hareket ettiren dört giriş tuşunu kabul edin (dört kardinal yön). Diğer girdilerin okunmasına / işlenmesine izin verilir ('enter', vb. Gerektiren bir readline () işlevi).
  • Zindanın sınırlarının dışına seyahat etmek yasaktır. Örneğin, oyuncu zindanın sağ kenarındaysa sağa basmak hiçbir şey yapmamalıdır.
  • İlk nesilden sonra ve her hareketten sonra, oyunun durumunu yazdırın. Bu kod golf olduğundan ve yazdırma oldukça ilgi çekici olmadığından, durum değişikliği olmadığını varsayarak yazdırma işlevi ve işlev çağrısı için karakter sayısını göz ardı edin . Boş hücreler; dönem ( .), muska, çift alıntı ( ") ve karakter ( @) ile gösterilmelidir.
  • Oyuncu muska "keşfettiğinde" biter (aynı kareye vardığında).

Kazanan

Bu bir kod golf mücadelesidir, bugünden bir hafta sonra gereksinimlerini karşılayacak en kısa kod kazanan ilan edilecektir.

Örnek

Temel gereklilikleri ve örnek çıktılarını gösteren örnek bir C # (ungolfed) çözümü.

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

Toplam karakter sayısı 1474'tür, ancak baskı işlevine yapılan çağrıları ve tanımını son karakter sayımı olarak görmezden gelmek 896.

Program çalıştırıldığında çıktı:

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

'A' tuşuna iki kez basıldıktan sonra çıkan çıktı (yukarıdakiler dahil):

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

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

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

10
Bunun @Doorknob'un ilgisini çekeceğini hissediyorum.
Alex A.

10
Rogue , oyuncunun Yendor Amuletini zindanın en alt seviyesinden alması gereken orijinal oyun oyunudur. Neden buna minimal Rogue demiyorsun?
Gilles,

5
@Gilles Neden buna minimal bir yılan demiyorsun?
Casey Kuball

26
Psshh, köşegen hareketi yok mu? Yubnhjkl yok mu? Muska aldıktan sonra tırmanacak bir merdiven bile yok mu? : P ( yine de öfkeyle yükseltir )
Doorknob

2
@ tolos: Hala burada rastgele sayılan şeyin ne olduğu konusunda net değilim . Programın 80 defa çalıştırılması durumunda programın her çalıştırılması gerektiğinde farklı olanı gerçekleştirmek gerçekten mümkün değildir ... Spesifik olarak, bu cevapta , muska, tüm olası 79 konumdan sadece 9'unu kaplayabilir. Bu sayılır mı?
Dennis,

Yanıtlar:


37

TI-BASIC, 42 41 38 36 35 bayt

TI-83 veya 84+ serisi grafik hesap makineniz için.

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

Müzikçaların hangi yöne gideceği, basılan tuşun tuş kodunun bir işlevidir , ancak kesinlikle çalışan dört tuş en üst sıradadır:

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

Muska ilk sütundaki beş kareden birinde başlar ve oyuncu sağ alt köşeden başlar. Örneğin, olası bir düzenleme:

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

açıklama

Oyuncunun pozisyonu gelen karmaşık bir sayı olarak depolanır 0+0iiçin 15+4igerçek bir parçası sağa gider ve sanal kısmı battığı yere. Bu, üstte ve solda kolay sınır kontrolünü kolaylaştırır: sayıyı hafifçe kaydırır ve sıfıra doğru döndürürüz. Örneğin, ofset 0.5ve konumumuz -1+3i(ekrandan sola doğru) ise, konum iPart(-0.5+3.5i)=0+3iolması gereken yere göre düzeltilecektir . Alt ve sağ sınırları kontrol etmek biraz daha karmaşıktır; sayıyı sabit bir sayıdan çıkarmamız gerekir C, ki bu 15.635 + 4.093i( yaklaşık 15+4ive arasında bulabildiğim en kısa sayıdır 16+5i), yuvarlak, Csayıyı geri çevirmek için tekrar çıkarmak ve tekrar döndürmek.

Bir tuşa basıldığında, ayarlanmamış oynatıcı konumu bir birimde 1 birim hareket eder, ancak tamsayı kısmı yalnızca belirli tuşlara basıldığında değişir. Neyse ki, çalışan anahtarların hepsi en üst sırada. Aşağıda, 11, 12, 13 ve 15 tuşlarına basıldığı ve hiçbir tuşa basılmadığı durumlarda ofsetlerin bir grafiği gösterilmektedir (Orta karenin içindeki hiçbir basma yok, tamsayı parçalarının değişmemesine neden olan, dört tuşa basılması; 'ofsetlerin farklı tamsayı parçaları var). Cdairenin ortasındaki kırmızı çarpıdır.

görüntü tanımını buraya girin

Eski kod (42 bayt):

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

Sınırlamalar

Bir "karakterden kaçmanın bir yolu yoktur , bu nedenle "bir programın içinde bir karakter dizisi bulunamaz. Bu nedenle, bu ¨alıntı yerine umlaut işaretini kullanır (eğer zaten alıntı işaretli bir dize olsaydı, bunu gösterebilirdim). Almak için ¨ve @bir programda, bir dış alet gereklidir; Ancak, geçerli bir TI-BASIC.


2
Sadece eğlence için, diaerezi ve @ sembolünü Str1'e yerleştiren bu parçacığı yaptım ('dış araç' yerine). Hesap makinenize uygun çizgiyi seçin, yeni bir programa girin ve bu programı Asm ile çalıştırın (.
MI Wright

Hesap makinesinde makine kodunu kodlamayı unuttum. Benimkine bir yanlış yazımla çarpmak istemem, ama işe yaradığına inanıyorum.
lirtosiast

44

CHIP-8 , 48 bayt

Bu yasal olarak kabul edilemez, ama neden olmasın. Programımı sanal bir oyun konsolu için bytecode tabanlı bir programlama dili olan CHIP-8'de yazdım. Octo adlı yazdığım bir emülatör / hata ayıklayıcıyı kullanarak tarayıcınızdaki tüm programı (99 bayt) deneyebilirsiniz:

Ekran görüntüsü

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

Bu tam programın onaltılık bir dökümü aşağıdaki gibidir:

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

Oynatıcıyı ASWD tuşlarıyla veya orijinal CHIP-8 tuş takımındaki 7589 tuşlarıyla hareket ettirebilirsiniz. Arka planı ve oynatıcıyı çizmeye yönelik tüm kodu ve verileri kaldırırsam, bunun yerine bu 48 bayt boşluğu alıyorum:

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

Ungolfed, programın tam formu aşağıdaki şekilde yüksek düzeyde bir meclis dilinde yazılmıştır:

: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

Derlenmiş baytların kendilerinin CHIP-8 programlama dili olduğunu unutmayın; birleştirici bu tür programları oluşturmanın daha uygun bir yoludur.


19
İş için doğru alet.
Dennis,

6
+1 oyununu tekrar tekrar oynayarak bir sürü zamanımı boşa harcıyorum.
Alex A.

4
@AlexA. daha fazla zaman harcamak istiyorsanız Cave Explorer'ı denemelisiniz . Yeryüzündeki ASWD hareketi ve QE, platformer seviyesindeki blokları sıfırlamak / taşımak için kullanılır.
JohnE,

4
Harika, işte hafta sonu gidiyor.
Alex A.

1
İlk başta şüpheliydim, ancak Cave Explorer eğlenceliydi ve CHIP-8 tahmin ettiğimden çok daha uzun süredir var. Sanırım bunu öğrenmek zorunda kalacağım.

10

Python 3, 86 bayt

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]

Sadece alttaki iki satırı sayıyor ve düşüyor d();.


Oynatıcıyı sağ alt köşede ("son" kare) başlatarak, ardından ilk 79 kareden rastgele örnekleyerek başka bir bayt kurtardım .
Lynn,

Maalesef, düzeltildi! El ile bayt sayma konusunda şaşırtıcı değilim sanırım. : <
Lynn

1
Sana değiştirerek başka bir karakter kaydedebilirsiniz düşünüyorum a=id(9)%79ile a=id(9)%p.
kirbyfan64sos

@ kirbyfan64sos Mükemmel! Teşekkürler.
Lynn,

1
Ayrıca, bunu Python 3 için yaparsanız, raw_inputaramayı sadece olarak değiştirebilirsiniz input.
kirbyfan64sos

10

C, 122 121 115 104 102 101 bayt

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

Burada ilk kez gönderme! Umarım beğenmişsindir :)

obaskı, erm, fonksiyondur. Cesur kahramanımız 2, 4, 6 ve 8 ile hareket ettirilebilir, ancak başka bir giriş göndermemeye dikkat edin (yeni hat yok!).

Güncelleme 1: getirdi ave iiçine main'ın parametreleri.

Güncelleme 2: OP, tek bir giriş dizesinin tamam olduğunu doğruladıktan sonra scanf(yeni çizgiyi atlamak için kullandım) kurtuldum .

Güncelleme 3: Bileşik bir dizi hazır bilgi kullandı ve giriş düzenini değiştirdi. Geçersiz bir yön girerseniz program şimdi haywire gider;)

Güncelleme 4: Yazdırma işlevine yapılan çağrı sayılmaz. Kuralları daha dikkatli okumak için not aldım.

Güncelleme 5: Mikkel Alan Stokkebye Christia sayesinde bir bayt kurtarıldı.


Could !!(p%16)olmak p%16>0? İşlem emirimi hatırlamıyorum.
lirtosiast

@ThomasKwa öyle, ama bu tek başına -yardımcı olamaz ama yapışmaz p, bu yüzden parantezlere iki şekilde de ihtiyaç duyulur. Çifte patlama sadece şaşkınlık yaratıyor :)
Quentin

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

@MikkelAlanStokkebyeChristia thank you :)
Quentin

9

CJam, 46 45 44 40 39 37 bayt

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

İlk hat (a geçerli oyun durumu yazdırır işlev tanımlar) p 'nin ikinci hat (Bu işlev çağrısı) bayt sayısı katkıda bulunmazlar.

Hem başlangıç ​​pozisyonu hem de muska pozisyonu sözde rasgele seçilmiştir. Dağılım aynıdır ve alttaki PRNG izin verir.

Girdi olduğunu E, 6, 9ve Biçin Yukarı , Aşağı , Sol ve Sağ ile, Caps Lockaktive edilmiş, ardından Enter.

Alternatif sürüm

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

Dört bayt pahasına, giriş formatı önemli ölçüde geliştirildi:

  • Bu sürüm kabul 8, 2, 4ve 6için Yukarı , Aşağı , Sol ve Sağ numpad üzerinde ilgili ok tuşlarını maçları.
  • Ayrıca kabul 7, 9, 1ve 3karşılık gelen diyagonal hareketler için.

Test yapmak

G / Ç etkileşimli olduğundan, bu kodu Java tercümanı ile denemelisiniz .

En son sürümü indirin ve programı şu şekilde çalıştırın:

java -jar cjam-0.6.5.jar nethack.cjam

EnterHer tuştan sonra ve çıktının yerinde güncellemeleri için basılmasını önlemek için bu sargıcıyı kullanabilirsiniz:

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

Bu şekilde çağır:

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

Ana sürüm

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.

Alternatif sürüm

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.

İşlev P

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

2
TI-BASIC ile kuyruğundayım! Çözümümü doğruladığımda bir kez gönderirim.
lirtosiast

8

Java, 231 bayt (işlev varsa 196)

İşte 342'deki tam program kodu:

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

Yazdırma işlevi olmadan, 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);}}

Eğer sadece bir işlev tamamsa (teknik özelliklerden belirsizim), o zaman bunu 196'ya biraz daha kısaltabilirim:

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

Ve bazı netliklerle biraz netlik için ...

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

Ben baskı fonksiyonu saymıyorum unutmayın p(p,y)kendisini ama am Bir şeylere çağrı deyimi içinde değişen beri, kendisine çağrı sayma.

Büyük harflerle çalışır ASDW. Bunları kontrol etme biçiminden dolayı, diğer bazı harfler de işe yarayabilir, ancak teknik özellik, farklı tuşlara basarsam ne olması gerektiği hakkında hiçbir şey söylemiyor.


İç içe üçlü operatörlerin aynı girintiye göre biçimlendirilmesini tercih ederim, eğer if / else if zincirleri gibi. Daha okunaklı.
lirtosiast

@ThomasKwa Yea, iki kere de yaptım. Zincirleme ifadelerinden daha fazlası iç içe geçmiş gibidir. Benim için daha iyi hissettiriyor çünkü her üçlünün her iki yarısı da aynı seviyede, ancak diğerlerinden farklı.
Geobits

Anonim bir fonksiyon olarak kabul edilebilir ise, 192 bayt cevabınızı Döşeme olabilir: void m()olur()->
ankh-morpork

@ dohaqatar7 Evet, fakat Java'nın anon fonksiyonlarını kod golf için kullanmıyorum. Başkalarının aynı hissetip hissetmediği prensipte bana biraz gölgeli geliyor.
Geobits

Bunu yapabilir misin p+=?
lirtosiast

5

Java, 574 bayt

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

Temelde, karışık ve küçültülmüş durumlar dışında, C # sürümüyle aynıdır.


Pek çok gereksiz boşluklar ...;)
Will

@Will Ben sadece tamir ediyordu: P
faz

1
Ayrıca, tek harfli adlar ve üçlü harfler kullanın.
lirtosiast

@ThomasKwa düzeltildi: D
faz

6
Hala çok fazla gereksiz alan ve üçlü eksikliği var;)
Will

5

Julia, 161 bayt

Kullanımları w, a, sve dsırasıyla aşağı ve sağa, sola, yukarı taşımak için.

Yazdırma dahil tam kod (330 bayt):

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

Puanlanmış kod, yazdırma hariç (161 bayt):

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

Buradaki fark, oyun durumunu bir matris olarak kaydetmememizdir; ilgili tüm bilgiler dizilerde cve a. Ve elbette, hiçbir şey yazdırılmaz. Oyuncu muskaya ulaştığında, kullanıcıdan artık giriş yapması istenmeyecek.


Ungolfed + açıklama (tam kod):

# 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

Bence bu iyi

3
Gerçek nethack kaynak kodunu hatırladığım şeye çok benzeyen sıkıştırılmış / şaşkın sürüm için +1.
Ben Jackson,

Daha kötü randomizasyon kullanarak birkaç bayttan tasarruf edebilirsiniz:a=[rand(1:5),1] c=a+1
lirtosiast

@ThomasKwa: Her zaman ilk satırda olsaydı ne eğlenceli? :)
Alex A.

3

Toplu İş, 329 Bayt

@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

Bu oldukça etkileyici. Bunu yapmanın mümkün olduğuna şaşırdım.
eis

Bu benim için zindanı göstermiyor, sadece [W, A, S, D]? "Çalışıyor" gibi görünüyor - görünmeyen zindanda yürürken sonunda çıkıyor. win7 cmd.exe
Dan Pritts,

Benim için çalışır Win7 cmd.exe witn içinMicrosoft Windows [Version 6.1.7601]
Jerry Jeremiah

@DanPritts Bu garip. Windows 8 ( Microsoft Windows [Version 6.2.9200]) benim için mükemmel çalışıyor
ankh-morpork

ah, her şeyi kopyalayıp yapıştırmadım, pencerede aşağı kaydırmadım. Aferin.
Dan Pritts

3

Perl, 228 (kod çalışma ayrılmaz olmayan yeni satır hariç) 222 karakter - 207 ise saymıyor printve print ifbaskı için kullanılır, ancak oyun mantığına katmayan ifadesi parçalar; (144) ayrıca alan gösterimi oluşturma kodunu, Yakk tarafından yorumlarda önerildiği gibi, baskının bir parçası olarak düşünürse)

Bu kod kontrol için küçük harf wasd kullanır; giriş Enter ile onaylanmalıdır. Perl ile Test Edildi 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}}

İşlemlerin düzenli ifadeler kullanılarak doğrudan basılı gösterime yapıldığı için bu kod için, hesaplamayı ve yazdırmayı ayırmanın imkansız olduğunu unutmayın.

Açıklama:

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

Bu çizgi, oyuncunun ve muska pozisyonunu belirler. Oyuncunun pozisyonu belirlenir $==rand(80)ve anlaşılması kolaydır: 5 × 16'lik bir tahtada oyuncunun olabileceği 80 ayrı pozisyon vardır. Konum, $=kaydedilen değeri tam sayıya zorlayan değişkende saklanır; bu, sonucu tamsayıya açıkça aktarmaya gerek duymadığınız için birkaç bayt kazandırır ( randkayan nokta değeri sağlar).

Pozisyonlardan biri zaten oyuncu tarafından işgal edilmiş olduğundan, muska için sadece 79 pozisyon kalmıştır, bu nedenle muska pozisyonu $a=$==rand(79)için kullanılmaktadır. Yine, $=tamsayılı bir dönüşüm zorlamak için atama , ancak ben oyuncunun pozisyonu $aiçin yeniden kullanmak $=için daha da atayın .

Şimdi, muskanın oyuncu ile aynı pozisyonda kalmasını engellemek için, pozisyonu en az oyuncu kadar büyükse, bir oyuncu tarafından işgal edilmeyen yerler üzerinde eşit bir dağılım sağlayarak, bir pozisyon ile ilerler. Bu, oyuncunun pozisyonunu burada tuttuğu $a = ($a >= $=)yerden başarılır $=. Şimdi ilk satır, $a$ and the onlybu ifadede ilk $ = ` yerine iki ilk atama eklenerek oluşturulur .

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

Bu, başlangıç ​​alanını oluşturur ve daha sonra yazdırır. ("."x80)sadece 80 noktalık bir dizi oluşturur. =~s/(.{$=})./\1@/rsonra $=inci karakteri ile değiştirir @ve=~s/(.{$=})./\1@/r$a birlikte inci karakter ". Nedeniyle rdeğiştirici onlar yerinde değiştirmeye çalışıyorum, ama modifiye dize döndürmez önceki ifadelerde uygulanabilir neden bu. Son olarak, =~s/(.{16})/\1\n/grher 16 karakterde bir yeni satır ekler. Alanın $_daha sonraki ifadelerde dolaylı olarak kullanılabilecek özel değişkende saklandığını unutmayın .

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

Bu, farklı hamleler için değiştirme kurallarını içeren bir karma oluşturur. Bunun daha okunaklı bir versiyonu

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

Anahtarlar hamlelerin karakterleridir ve değerler karşılık gelen değiştirme kuralını içeren dizelerdir.

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

Bu ana döngü. while(/"/)İçinde hala bir "karakter olup olmadığını kontrol eder $_(yani alanda). Muskaya geçersek, karakteri oyuncu karakteri ile değiştirilir, böylece alandan kaybolur.

eval $r{getc STDIN}Standart girişten bir karakter okur, karşılık gelen değiştirme kuralına sahip olandan bakar %rve onu $_alana uygular . Bu, gerçekten bir değişiklik yapıldıysa (yani, anahtarın anahtarında bulundu ve taşıma mümkün olduğunda; değiştirme kuralında imkansız bir hareket eşleşmiyorsa) doğru olarak değerlendirilir. Bu durumda printyürütülür. Argüman olmadan çağrıldığından $_, değiştirilmiş alanı yazdırır .


1
Sırf okunabilirlik için satır beslemelerini dahil etmeniz, onları saymanız gerektiği anlamına gelmez. 228 bayt görüyorum. Ayrıca, bu sorunun özel kuralları uyarınca, kodunuzun basılan kısmı bayt sayısına katkıda bulunmaz.
Dennis,

@Dennis: Yazdırma bölümü için şimdi eklediğim açıklamaya bakın: Kodumdaki yazdırma ve değerlendirmeyi anlamlı şekilde ayıramazsınız. Şimdi saymayı istediğin gibi değiştirdim.
celtschk

Baskı kodunuzda herhangi bir durum değişikliği var mı? Hayır? Bence, baskı kodunuzun çıktısını mantığınız için tekrar kullanmak sizi cezalandırmamalıdır. Hareket kodu (farklı!) Sayılmalıdır, ancak "görüntüleme dizesini" oluşturan kod sayılmamalıdır.
Yakk

@Yakk: Kodumun hangi bölümünü yazdırma kodunu düşünüyorsunuz? (Aslında benim görüşüme göre baskı kodunun sayılmasının dışında tutulması kötü bir fikirdi, çünkü tam olarak "baskı kodunun" ne olduğu her zaman iyi tanımlanmadı.)
celtschk

@celtschk ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grilk bakışta oldukça yakın, ancak perl- fu'm birkaç yıl paslandı. Orada bir devlet değişikliğini kaçırabilirdim.
Yakk

2

C #, 256 248 234 227 226 225 bayt

Hareket etmek için NumLock açıkken NumPad oklarını kullanır.

Girintili ve netlik için yorum yaptı:

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

1
C #, dolaylı olarak sıfıra init bence. Ayrıca (şu anda kontrol edemezsiniz) eğer oyuncu seçimi bir sorun değilse, karakter değişmezlerini ints e, en azından 'a' dan 97 ye (sanırım) diğerleri üç haneli olsa da dönüştürebilirsiniz.

Yalnızca sınıf alanları varsayılan olarak başlatılır ve bu durumda bunların statik olarak bildirilmesini gerektirir. İlk kullanımdan önce yöntem değişkenleri başlatılmalıdır. Bu daha az karakter alır: 4 vs 7.
Hand-E-Food

Örtülü bir şekilde char karakterine int için ipucu için @tolos! Daha da iyisi, ConsoleKey enum cast int olarak kullanırsam 2 basamaklı değerler kullanabilirim.
El-E-Yemek

Teknik olarak, Mainyöntemin çağrılması gerekmez Main, bu nedenle başka üç karakteri daha tıraş edebilirsiniz.
Luaan

@Luaan, sanırım yanılıyorsun. C # dokümantasyonu: msdn.microsoft.com/en-us/library/acy3edy3.aspx
El-E-Yiyecek

2

HTML + JavaScript (ES6), belki 217 puan

Çok looong, ancak aşağıdaki snippet'lerde çevrimiçi olarak oynanabilir.

Satır 6 (T.value ...) çıktı içindir ve sayılmaz (ama basitlik için ben de çıktı olsa bile textarea aç ve kapat etiketlerini saydım)

Rasgelelik gelince: muska her zaman şebekenin sağ yarısında ve oyuncu her zaman sol yarısında başlar.

Oyunu başlatmak ve yeniden başlatmak içinArea (genişlettikten sonra) metinine tıklayın.

<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 (yalnızca 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'i (Chrome'da test edilmiştir)

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

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

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


2

Actionscript 3: 267 bayt

Çalışan bir örnek çevrimiçi

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

Oyun işlevini kullanan tam (boşluklar dahil) bir program:

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

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

        public function MiniRogue()
        {
            g();
        }

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

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

2

Javascript: 307 216

Aşağıdaki pasajda oynayabilirsiniz! Soldaki sayılar sadece konsolun (en azından bir krom olan) satırları birleştirmemesi içindir.

Kodu çalıştırmak için:

  1. "kod snippet'ini çalıştır" tuşuna basın
  2. konsolu açmak için ctrl-shift-j tuşlarına basın
  3. sonuç bölümüne tıklayın
  4. ok tuşlarını kullanın ve

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

Un-golfed:

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

Düzenleme 1: Kuralları daha dikkatli okuyun ve kodumu buna göre yeniden yazın.

  • muska y değeri şimdi rastgele
  • oyuncu artık odadan kaçamaz
  • Artık draw işlevindeki karakterleri saymıyorum veya onu çağırmıyorum

1

SpecBAS - 428 402 (yazdırma hariç, sayıldığında 466 425)

Sırasıyla yukarı / aşağı / sola / sağa hareket etmek için Q / A / O / P kullanır.

Zindanı 1. satırda basma çizgisi, yok sayılabilecek tek satırdır, ancak bunu biraz da düşürdüler.

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

# 34 referansı CHR $ (34) koduna koymanın sadece kısa bir yoludur.

Teşekkürler @Thomas Kwa, oyuncunun başlangıç ​​pozisyonunun rastgele olmasının isteğe bağlı olduğunu fark etmemiştim. Ayrıca birkaç karakteri tıraş etmek için ayrı IF ifadeleri kullanılır.


Bazı karakterleri daha az iyi rastgele seçerek kaydedebilirsiniz: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)ve ayrıca IF instead of ELSE IF.
lirtosiast

1

Başka bir C #, 221 171 170

Burada C # 'da her iki pozisyonun da rastgele olduğu bir başka yol var. Bu kısım, Hand-E-Food'un çözümünden 7 byte daha uzun olsa bile bunu göstermek istedi.
El-E-Gıda'nın cevabı, Console'u kullandığı anda elbette daha kısa olacaktır.
Konsolun dezavantajı, okumaya ihtiyaç duyulan Enter tuşuna basıldığında alanın 2 kez daha yazdırılmasını sağlar.
Ancak sadece (gerçek) girdiyi yazdırmak için bir gereklilik olduğunu sanmıyorum.

Navigasyon, Hand-E-Foods çözümünde olduğu gibi 8426 tarafından yapılır.

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


Düzenleme: (yeni bir çözüm eklendi ve PrinterClass'ı sonuna kadar taşıdı)
Düzen2: (14'ten 15'e değiştirildi ve sağ alttan başlayarak baytı kurtardı)

Mauris tekniğini uyarlayarak C # 'da 171 bayta kadar eritmek mümkün (tabii ki şimdi her iki pozisyonda rastgele olmadan):

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

Yazıcı Sınıfı neredeyse aynı, sadece yeni bir baskı aşırı yükü ...

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

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

1

Ruby, 185

İşte bir Ruby örneği.
Ruby'de çok yeniyim, belki birileri bunu nasıl daha iyi yapabileceğini bilir :)

Program aksi halde çökeceği için lineFeeds'i 1 olarak saydım.

Navigasyon 8462 tarafından yapılır. Her seferinde enter ile giriş yapmanız gerekir.

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


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

0

QBasic, 103 bayt

Mücadelenin kuralları uyarınca, Showalt program bayt-sayıma dahil edilmez ve Show p, q, a, bçağrı da (aşağıdaki yeni satırla birlikte).

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

Taşımak için bir sayı girin ve Enter tuşuna basın: 1sola 2gitmek, yukarı 3gitmek, sağa gitmek ve4 aşağı gitmek için.

Bu kod, oyuncunun muskayı bulduğunda, sonunda oyun durumunu göstermez. Bunu yapmak için Show p, q, a, b, IFifadeden sonra bir tane daha ekleyin .

açıklama

Let a, bmuska koordinatlarını ve temsil p, qoyuncunun koordinatlar. Müzikçalar (0, 0) başlar ve muska, o anki saatin 1 basamağını temel alarak 1 ile 9 arasında bir sütunla 0 satırında başlar.

Gerisi koşullu sadece bir demet matematik. Hatırlanması gereken en önemli şey, QBasic'deki şartlı koşulların 0false -1için doğru olduğu gerçeğidir . Oyuncu sıra güncelleme bildirimine bakalım:

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

Eğer m=2öyleyse, 1'den p, kadar çıkarılarak yukarı doğru hareket etmek istiyoruz p>0. Benzer şekilde, eğer m=4, psürece 1'e ekleyerek aşağı gitmek istiyoruz p<4. İstenilen davranışı çarparak elde edebiliriz. Her iki faktör de varsa -1, onların 1çıkardığı veya ekleyebileceğimiz bir ürün olacaktır p. Koşullardan herhangi biri geçerliyse, hiçbir etkisi 0olmayacak şekilde ürün olacaktır 0.

Benzer şekilde, oyuncunun muska bulduğunu belirleme koşulu şöyledir:

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

Koşullamalar biri doğru ise, bunların toplamı sıfırdan farklı olacaktır (ya da -1ya da -2) ve bu nedenle truthy ve program 1. Bir kez hizaya döner peşittir ave qeşit biki şart olur, 0bunların toplamı olur, böylece, 0ve akış ulaşabilir programın sonu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.