NetHack tối thiểu


64

NetHack là một trò chơi roguelike, trong đó người chơi phải lấy Amulet of Yendor từ cấp thấp nhất của ngục tối. Thường được chơi qua telnet, toàn bộ trò chơi được thể hiện bằng đồ họa ASCII. Trò chơi là vô cùng thách thức và đòi hỏi kiến ​​thức của nhiều cơ chế trò chơi để thành công.

Đối với mục đích của thử thách này, giả sử rằng toàn bộ ngục tối là một cấp độ duy nhất và chỉ có 5 × 16 ký tự. Hơn nữa, giả sử rằng đây là một hầm ngục "an toàn" hoặc bạn chỉ đang thực hiện một nguyên mẫu, sẽ không có quái vật, mối quan tâm về đói, v.v. Trên thực tế, bạn chỉ phải theo dõi vị trí của nhân vật và bùa hộ mệnh và trò chơi sẽ kết thúc hiệu quả khi người chơi đến cùng địa điểm với bùa hộ mệnh.

Yêu cầu thử thách

  • Sẽ có một hầm ngục 5 × 16 (cấp đơn).
  • Cung cấp cho người chơi một vị trí bắt đầu (tùy chọn ngẫu nhiên) và bùa hộ mệnh ngẫu nhiên riêng biệt (khác nhau mỗi khi chương trình được chạy) bắt đầu hình vuông bên trong ngục tối. Đó là, bùa hộ mệnh không được phép bắt đầu trên cùng một hình vuông với người chơi.
  • Chấp nhận bốn phím nhập di chuyển người chơi một ô vuông cùng một lúc (bốn hướng chính). Đọc / xử lý đầu vào khác được cho phép (một hàm readline () yêu cầu nhấn 'enter', v.v.).
  • Đi du lịch ngoài giới hạn của ngục tối không được phép. Ví dụ, nếu người chơi ở rìa bên phải của ngục tối, nhấn phải không làm gì cả.
  • Sau thế hệ ban đầu và sau mỗi chuyển động, in trạng thái của trò chơi. Vì đây là mã golf và in ấn không thú vị, bỏ qua số ký tự cho chức năng in và chức năng gọi giả sử không có thay đổi trạng thái . Các ô trống phải được hiển thị dưới dạng period ( .), bùa hộ mệnh dưới dạng trích dẫn kép ( ") và ký tự như tại ký hiệu ( @).
  • Trò chơi kết thúc khi người chơi "phát hiện" bùa hộ mệnh (đến cùng một hình vuông)

Chiến thắng

Đây là một mã golf, mã ngắn nhất để đáp ứng các yêu cầu một tuần kể từ hôm nay sẽ được tuyên bố là người chiến thắng.

Thí dụ

Dưới đây là một giải pháp ví dụ trong C # (chưa được chỉnh sửa) để hiển thị các yêu cầu cơ bản và đầu ra mẫu.

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

Tổng số ký tự là 1474, nhưng bỏ qua các lệnh gọi đến chức năng in và định nghĩa của nó là số ký tự cuối cùng là 896.

Đầu ra khi chương trình được chạy:

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

Đầu ra (bao gồm cả ở trên) sau khi nhấn phím 'a' hai lần:

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

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

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

10
Tôi có cảm giác điều này sẽ được @Doorknob quan tâm.
Alex A.

10
Rogue là trò chơi roguelike ban đầu, nơi người chơi phải lấy Amulet of Yendor từ cấp thấp nhất của ngục tối. Tại sao không gọi đây là Rogue tối thiểu?
Gilles 'SO- đừng trở nên xấu xa'

5
@Gilles Tại sao không gọi đây là một con rắn tối thiểu?
Casey Kuball

26
Psshh, không có chuyển động chéo? Không có yubnhjkl? Thậm chí không có một cầu thang lên để leo lên sau khi lấy bùa hộ mệnh? : P ( dù sao cũng rất nhiệt tình )
Doorknob

2
@tolos: Tôi vẫn chưa rõ những gì được coi là ngẫu nhiên ở đây. Thật sự không thể đáp ứng khác nhau mỗi khi chương trình được chạy yêu cầu nếu chương trình được chạy 80 lần ... Cụ thể, trong câu trả lời này , bùa hộ mệnh chỉ có thể chiếm 9 trong số 79 địa điểm có thể. Có tính không?
Dennis

Câu trả lời:


37

TI-BASIC, 42 41 38 36 35 byte

Đối với máy tính vẽ đồ thị sê-ri TI-83 hoặc 84+ của bạn.

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

Người chơi sẽ đi theo hướng nào là một chức năng của mã phím của phím được nhấn, nhưng bốn phím chắc chắn hoạt động là những phím này ở hàng trên cùng:

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

Bùa hộ mệnh bắt đầu ở một trong năm ô vuông trong cột đầu tiên và người chơi bắt đầu ở ô vuông dưới cùng bên phải. Ví dụ: một sự sắp xếp có thể là:

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

Giải trình

Vị trí của người chơi được lưu trữ dưới dạng một số phức từ 0+0iđến 15+4i, trong đó phần thực ở bên phải và phần ảo đi xuống. Điều này tạo điều kiện cho việc kiểm tra ranh giới dễ dàng ở phía trên và bên trái: chúng ta chỉ cần bù số một chút và làm tròn về 0. Ví dụ: nếu độ lệch là 0.5và vị trí của chúng ta là -1+3i(tắt màn hình sang trái), thì vị trí sẽ được sửa thành vị trí iPart(-0.5+3.5i)=0+3icần đặt. Kiểm tra ranh giới dưới và bên phải phức tạp hơn một chút; chúng ta cần trừ số từ một hằng số C, đó là khoảng 15.635 + 4.093i(đó là số ngắn nhất tôi có thể tìm thấy giữa 15+4i16+5i), làm tròn, trừ đi Cmột lần nữa để lật lại số và làm tròn lại.

Khi nhấn một phím, vị trí người chơi không được điều chỉnh sẽ di chuyển 1 đơn vị theo một số hướng, nhưng phần nguyên chỉ thay đổi khi nhấn một số phím nhất định. May mắn thay, các phím làm việc là tất cả trên hàng đầu. Dưới đây là biểu đồ của các độ lệch trong trường hợp các phím 11, 12, 13 và 15 được nhấn và khi không nhấn phím nào (Không nhấn là điểm bên trong hình vuông trung tâm, làm cho các phần nguyên không thay đổi; bốn phím nhấn 'offset có các phần nguyên khác nhau). Clà chữ thập đỏ ở trung tâm của vòng tròn.

nhập mô tả hình ảnh ở đây

Mã cũ (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

Hạn chế

Không có cách nào để thoát khỏi một "ký tự, vì vậy các chuỗi "không thể được tạo trong chương trình. Do đó, điều này sử dụng dấu umlaut ¨thay vì dấu ngoặc kép (nếu đã có một chuỗi đã tồn tại với dấu ngoặc kép, tôi có thể hiển thị dấu đó). Để có được ¨@trong một chương trình, cần có một công cụ bên ngoài; tuy nhiên, nó là TI-BASIC hợp lệ.


2
Để giải trí, tôi đã tạo đoạn trích này đặt biểu tượng diaeresis và @ trong Str1 (trái ngược với 'một công cụ bên ngoài'). Chọn dòng ở trên cùng phù hợp với máy tính của bạn, nhập nó vào một chương trình mới và chạy chương trình đó với Asm (.
MI Wright

Ồ, tôi quên mất việc mã hóa mã máy trên máy tính. Đừng muốn đánh sập tôi với một loại nhầm, nhưng tôi tin rằng nó hoạt động.
lirtosiast 04/07/2015

44

CHIP-8 , 48 byte

Điều này có thể không được coi là hợp pháp, nhưng tại sao địa ngục không. Tôi đã viết chương trình của mình bằng CHIP-8, ngôn ngữ lập trình dựa trên mã byte cho bảng điều khiển trò chơi ảo. Bạn có thể thử chương trình hoàn chỉnh (99 byte) trong trình duyệt của mình bằng trình giả lập / trình gỡ lỗi mà tôi đã viết có tên là Octo:

Ảnh chụp màn hình

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

Một kết xuất hex của chương trình hoàn chỉnh đó như sau:

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

Bạn có thể di chuyển trình phát bằng các phím ASWD hoặc 7589 phím trên bàn phím CHIP-8 ban đầu. Nếu tôi xóa tất cả mã và dữ liệu để vẽ nền và trình phát, thay vào đó tôi nhận được kết xuất 48 byte này:

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

Hình thức hoàn chỉnh, không hoàn chỉnh của chương trình được viết bằng ngôn ngữ lắp ráp cấp cao như sau:

: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

Lưu ý rằng biên soạn byte mình là ngôn ngữ lập trình CHIP-8; trình biên dịch đơn giản là một phương tiện thuận tiện hơn để soạn các chương trình như vậy.


19
Công cụ phù hợp cho công việc.
Dennis

6
+1 để khiến tôi lãng phí rất nhiều thời gian để chơi trò chơi của bạn nhiều lần.
Alex A.

4
@AlexA. Nếu bạn muốn lãng phí nhiều thời gian hơn nữa, bạn nên thử Cave Explorer . Di chuyển ASWD trong thế giới bên kia và QE được sử dụng để đặt lại / di chuyển các khối ở cấp độ platformer.
JohnE

4
Tuyệt, cuối tuần tôi cũng đi.
Alex A.

1
Lúc đầu tôi đã hoài nghi, nhưng Cave Explorer rất vui và CHIP-8 đã tồn tại lâu hơn nhiều so với tôi đoán. Vì vậy, tôi đoán tôi sẽ phải học điều này.

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]

Chỉ đếm hai dòng dưới cùng, và thả d();.


Tôi đã lưu một byte khác bằng cách bắt đầu trình phát ở góc dưới bên phải (ô vuông "cuối cùng"), sau đó lấy mẫu ngẫu nhiên từ 79 ô vuông đầu tiên .
Lynn

Rất tiếc, xin lỗi, đã sửa! Tôi đoán tôi không tuyệt vời khi đếm byte thủ công. : <
Lynn

1
Tôi nghĩ bạn có thể lưu một nhân vật khác bằng cách thay thế a=id(9)%79bằng a=id(9)%p.
kirbyfan64sos

@ kirbyfan64sos Rực rỡ! Cảm ơn.
Lynn

1
Ngoài ra, nếu bạn thực hiện điều này cho Python 3, bạn có thể thay đổi raw_inputcuộc gọi thành chỉ 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]);}

Lần đầu tiên đăng bài ở đây! Tôi hy vọng bạn thích nó :)

olà in ấn, erm, chức năng. Anh hùng dũng cảm của chúng ta có thể được di chuyển xung quanh với 2, 4, 6 và 8, nhưng hãy cẩn thận vì không gửi bất kỳ đầu vào nào khác (không có dòng mới!).

Cập nhật 1: đưa aivào maincác tham số.

Cập nhật 2: OP đã xác nhận rằng một chuỗi đầu vào là OK, tôi đã loại bỏ scanf(mà tôi đã sử dụng để bỏ qua dòng mới).

Cập nhật 3: Được sử dụng một mảng ghép theo nghĩa đen và sửa đổi bố cục đầu vào. Chương trình bây giờ đi haywire nếu bạn nhập một hướng không hợp lệ;)

Cập nhật 4: Lưu ý rằng cuộc gọi đến chức năng in không được tính. Đã lưu ý để đọc các quy tắc cẩn thận hơn.

Cập nhật 5: một byte được lưu, nhờ Mikkel Alan Stokkebye Christia.


Có thể !!(p%16)p%16>0gì? Tôi không nhớ thứ tự hoạt động của tôi.
lirtosiast

@ThomasKwa là vậy, nhưng unary đó -không thể giúp gì được p, vì vậy, cần có dấu ngoặc đơn. Double-bang chỉ là obfuscation :)
Quentin

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

@MikkelAlanStokkebyeChristia cảm ơn bạn :)
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];

Dòng đầu tiên (xác định chức năng in trạng thái trò chơi hiện tại) và P trên dòng thứ hai (gọi chức năng đó) không đóng góp vào số byte.

Cả vị trí bắt đầu và vị trí của bùa hộ mệnh đều được chọn giả ngẫu nhiên. Việc phân phối là thống nhất và PRNG cơ bản cho phép.

Đầu vào là E, 6, 9Bcho lên , xuống , tráiphải , với Caps Lockkích hoạt, tiếp theo Enter.

Phiên bản thay thế

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

Với chi phí thêm bốn byte, định dạng đầu vào được cải thiện đáng kể:

  • Phiên bản này chấp nhận 8, 2, 46cho lên , xuống , tráiphải , mà phù hợp với các phím mũi tên tương ứng trên numpad.
  • Nó cũng chấp nhận 7, 9, 13cho di chuyển chéo tương ứng.

Kiểm tra

Vì I / O tương tác, bạn nên thử mã này với trình thông dịch Java .

Tải xuống phiên bản mới nhất và chạy chương trình như thế này:

java -jar cjam-0.6.5.jar nethack.cjam

Để tránh nhấn Entersau mỗi phím và để cập nhật tại chỗ của đầu ra, bạn có thể sử dụng trình bao bọc này:

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

Gọi như thế này:

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

Phiên bản chính

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.

Phiên bản thay thế

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.

Chức năng 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
Tôi đang theo sát bạn với TI-BASIC! Tôi sẽ đăng một khi tôi xác minh giải pháp của mình.
lirtosiast

8

Java, 231 byte (hàm 196)

Đây là mã chương trình đầy đủ tại 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":""));}}}

Không có chức năng in, 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);}}

Nếu chỉ một chức năng là ổn (tôi không rõ từ thông số kỹ thuật), thì tôi có thể cắt giảm thêm một chút xuống còn 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);}

Và với một số ngắt dòng cho một chút rõ ràng ...

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

Lưu ý rằng tôi không đếm p(p,y)chính chức năng in , nhưng tôi đang đếm cuộc gọi đến nó, vì tôi có những thứ thay đổi bên trong câu lệnh.

Nó hoạt động với chữ in hoa ASDW. Do cách nó kiểm tra những cái đó, một số chữ cái khác cũng có thể hoạt động, nhưng thông số kỹ thuật không thực sự nói bất cứ điều gì sẽ xảy ra nếu tôi nhấn các phím khác nhau.


Tôi thích định dạng các toán tử ternary lồng nhau ở cùng mức độ thụt lề, vì bạn sẽ có một chuỗi if / other if. Nó dễ đọc hơn.
lirtosiast

@ThomasKwa Yea, đôi khi tôi đã làm cả hai cách. Điều này giống như lồng nhau nếu câu lệnh hơn chuỗi. Tôi cảm thấy tốt hơn vì cả hai nửa của mỗi con chim nhạn đều ở cùng cấp độ, nhưng khác biệt với những con khác.
Geobits

Nếu một hàm ẩn danh có thể chấp nhận được, bạn có thể cắt câu trả lời của mình thành 192 byte: void m()trở thành()->
ankh-morpork 04/07/2015

@ dohaqatar7 Yea, nhưng tôi không sử dụng các hàm anon của Java cho mã golf. Nó cảm thấy mờ ám với tôi về nguyên tắc, cho dù người khác có cảm thấy như vậy hay không.
Geobits 04/07/2015

Bạn có thể làm được p+=không
lirtosiast 04/07/2015

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

Về cơ bản giống như phiên bản C #, ngoại trừ bị xáo trộn & thu nhỏ.


quá nhiều khoảng trống không cần thiết ...;)
Will

@ Tôi sẽ sửa nó: P
giai đoạn

1
Ngoài ra, sử dụng tên một chữ cái và chim nhạn.
lirtosiast

@ThomasKwa đã sửa: D
giai đoạn

6
Vẫn còn rất nhiều không gian không cần thiết và thiếu chim nhạn;)
Will

5

Julia, 161 byte

Sử dụng w, a, s, và dđể di chuyển lên, trái, xuống, và phải, tương ứng.

Mã đầy đủ, bao gồm in (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

Mã được ghi, không bao gồm in (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

Sự khác biệt ở đây là chúng ta không lưu trạng thái trò chơi dưới dạng ma trận; tất cả các thông tin liên quan được chứa trong các mảng ca. Và, tất nhiên, không có gì được in. Người dùng sẽ không còn được nhắc nhập liệu sau khi người chơi đến bùa hộ mệnh.


Ungolfed + giải thích (mã đầy đủ):

# 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

Tôi nghĩ điều đó tốt

3
+1 cho phiên bản nén / bị xáo trộn trông rất giống với những gì tôi nhớ về mã nguồn nethack thực tế.
Ben Jackson

Bạn có thể lưu một vài byte bằng cách sử dụng ngẫu nhiên tồi tệ hơn:a=[rand(1:5),1] c=a+1
lirtosiast

@ThomasKwa: Có gì vui nếu nó luôn ở dòng đầu tiên? :)
Alex A.

3

Mẻ, 329 byte

@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

Điều này rất ấn tượng. Tôi ngạc nhiên khi có thể làm điều này.
eis

Điều này không hiển thị dungeon cho tôi, chỉ một loạt các dòng nhắc [W, A, S, D]?. Nó dường như "làm việc" - đi bộ trong ngục tối không bị phá hủy cuối cùng thoát ra. win7 cmd.exe
Dan Pritts 6/07/2015

Nó hoạt động với tôi với Win7 cmd.exe - khi tôi gõ ver tôi nhận đượcMicrosoft Windows [Version 6.1.7601]
Jerry Jeremiah

@DanPritts Thật kỳ lạ. Nó hoạt động hoàn hảo với tôi trên Windows 8 ( Microsoft Windows [Version 6.2.9200])
ankh-morpork 7/07/2015

doh, tôi đã không sao chép và dán toàn bộ, tôi đã không cuộn xuống trong cửa sổ. Làm tốt.
Dan Pritts 7/07/2015

3

Perl, 228 222 ký tự (không tính các dòng mới không tách rời với hoạt động của mã) - 207 nếu không tính các phần printprint ifcâu lệnh được sử dụng để in, nhưng không thêm vào logic trò chơi; 144 nếu cũng coi mã tạo đại diện trường là một phần của in ấn, như đề xuất của Yakk trong các bình luận)

Mã này sử dụng wasd chữ thường để kiểm soát; đầu vào phải được xác nhận bằng Enter. Đã thử nghiệm với 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}}

Lưu ý rằng đối với mã này, không thể tách rời phép tính và in, vì các thao tác được thực hiện trực tiếp trên biểu diễn được in bằng các biểu thức thông thường.

Giải trình:

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

Dòng này xác định vị trí của người chơi và bùa hộ mệnh. Vị trí người chơi được xác định bởi $==rand(80)và thực sự dễ hiểu: Trên bảng 5 × 16, có 80 vị trí riêng biệt mà người chơi có thể ở. Vị trí được lưu trữ trong $=biến buộc giá trị được lưu thành số nguyên; điều này tiết kiệm một vài byte vì không cần truyền rõ ràng kết quả thành số nguyên ( randcung cấp giá trị dấu phẩy động).

Vì một trong những vị trí đã bị người chơi chiếm giữ, chỉ còn 79 vị trí cho bùa hộ mệnh, do đó, đối với vị trí của bùa hộ mệnh, $a=$==rand(79)được sử dụng. Một lần nữa, nhiệm vụ $=buộc chuyển đổi thành số nguyên, tuy nhiên tôi tiếp tục gán nó $ađể sử dụng lại $=cho vị trí của người chơi.

Bây giờ để tránh bùa hộ mệnh chiếm vị trí tương tự như người chơi, nó được nâng lên một vị trí nếu vị trí của nó ít nhất bằng người chơi, phân phối đồng đều ở những nơi không bị người chơi chiếm giữ. Điều này đạt được bởi $a = ($a >= $=)nơi $=đây giữ vị trí của người chơi. Bây giờ, dòng đầu tiên được tạo bằng cách chèn hai phép gán ban đầu thay vì $a$ and the only$ = ` đầu tiên trong biểu thức này.

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

Điều này tạo ra trường ban đầu, và sau đó in. ("."x80)chỉ cần tạo ra một chuỗi 80 chấm. =~s/(.{$=})./\1@/rsau đó thay thế các $=nhân vật thứ với @, và =~s/(.{$=})./\1@/rcác $anhân vật thứ với ". Do công cụ rsửa đổi, họ không cố gắng sửa đổi tại chỗ, nhưng trả về chuỗi đã sửa đổi, đó là lý do tại sao chúng có thể được áp dụng cho các biểu thức trước đó. Cuối cùng, =~s/(.{16})/\1\n/grchèn một dòng mới cứ sau 16 ký tự. Lưu ý rằng trường được lưu trữ trong biến đặc biệt $_có thể được sử dụng ngầm trong các câu lệnh sau.

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

Điều này tạo ra một hàm băm chứa các quy tắc thay thế cho các di chuyển khác nhau. Một phiên bản dễ đọc hơn của điều này là

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

Các khóa là các ký tự cho các bước di chuyển và các giá trị là các chuỗi chứa quy tắc thay thế tương ứng.

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

Đây là vòng lặp chính. while(/"/)kiểm tra nếu vẫn còn một "ký tự $_(nghĩa là trong trường). Nếu chúng ta di chuyển lên bùa hộ mệnh, nhân vật của nó sẽ được thay thế bằng nhân vật người chơi để nó biến mất khỏi sân.

eval $r{getc STDIN}đọc một ký tự từ đầu vào tiêu chuẩn, tra cứu quy tắc thay thế tương ứng từ có %rvà áp dụng nó cho $_, đó là trường. Điều này đánh giá là đúng nếu một sự thay thế thực sự được thực hiện (nghĩa là, khóa được tìm thấy trong hàm băm di chuyển là có thể; một động thái không thể sẽ không khớp với quy tắc thay thế). Trong trường hợp đó printđược thực thi. Vì nó được gọi mà không có đối số, nó in ra $_, đó là trường được sửa đổi.


1
Chỉ vì bạn bao gồm các nguồn cấp dữ liệu cho khả năng đọc không có nghĩa là bạn phải đếm chúng. Tôi thấy 228 byte. Ngoài ra, theo các quy tắc cụ thể của câu hỏi này, phần in mã của bạn không đóng góp vào số byte.
Dennis

@Dennis: Đối với phần in, hãy xem phần giải thích tôi đã thêm: Bạn không thể tách riêng việc in và đánh giá trong mã của tôi. Bây giờ tôi đã thay đổi cách tính như bạn đề xuất.
celtschk 04/07/2015

Có bất kỳ thay đổi trạng thái trong mã in ấn của bạn? Không? Vâng, theo tôi, việc sử dụng lại đầu ra của mã in cho logic của bạn không nên phạt bạn. Mã chuyển động (khác biệt!) Nên tính, nhưng mã tạo ra "chuỗi hiển thị" không nên tính.
Yakk

@Yakk: Phần nào trong mã của tôi mà bạn xem là mã in? (Trên thực tế ý kiến ​​của tôi là loại trừ mã in ra khỏi việc đếm là một ý tưởng tồi, chính xác bởi vì nó không phải lúc nào cũng được xác định rõ "mã in" là gì.)
celtschk

@celtschk thoạt nhìn ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grkhá gần, nhưng perl-fu của tôi thì bị rỉ sét vài năm. Tôi có thể đã bỏ lỡ một sự thay đổi nhà nước ở đó.
Yakk

2

C #, 256 248 234 227 226 225 byte

Sử dụng các mũi tên NumPad với NumLock được bật để di chuyển.

Ấn định và bình luận cho rõ ràng:

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
Tôi nghĩ rằng C # ints ngầm bắt đầu bằng không. Ngoài ra (không thể kiểm tra tại thời điểm này) nếu việc truyền không phải là vấn đề, bạn có thể chuyển đổi ký tự chữ thành ints hoặc ít nhất là 'a' thành 97 (tôi nghĩ) mặc dù các chữ số khác có ba chữ số.

Chỉ các trường lớp được khởi tạo theo mặc định và điều đó yêu cầu chúng được khai báo tĩnh trong trường hợp này. Các biến phương thức phải được khởi tạo trước khi sử dụng lần đầu tiên. Điều đó cần ít ký tự hơn: 4 so với 7.
Thực phẩm cầm tay

Cảm ơn @tolos về mẹo về việc ngầm định char cho int! Tốt hơn nữa, nếu tôi sử dụng enum ConsoleKey dưới dạng int, tôi có thể sử dụng các giá trị 2 chữ số.
Thực phẩm cầm tay

Về mặt kỹ thuật, Mainphương thức này không phải được gọi Main, vì vậy bạn có thể loại bỏ ba ký tự khác.
Luaan

@Luaan, tôi nghĩ bạn đã nhầm. Tài liệu C #: msdn.microsoft.com/en-us/l Library /acy3edy3.aspx
Hand-E-Food

2

Html + JavaScript (ES6), điểm có thể là 217

Quá looong, nhưng có thể chơi trực tuyến trong đoạn trích dưới đây.

Dòng 6 (T.value ...) là cho đầu ra và không được tính (nhưng để đơn giản, tôi đã đếm các thẻ mở và đóng của textarea, ngay cả khi nó cũng xuất ra)

Về tính ngẫu nhiên: bùa hộ mệnh luôn ở nửa bên phải của lưới và người chơi luôn bắt đầu ở nửa bên trái.

Nhấp vào textArea (sau khi mở rộng nó) để bắt đầu và khởi động lại trò chơi.

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

Đoạn mã EcmaScript 6 (chỉ dành cho 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>

Đoạn mã EcmaScript 5 (đã thử nghiệm trong 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>


2

Bản thảo 3: 267 byte

Một ví dụ làm việc là trực tuyến

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

Đây là một chương trình hoàn chỉnh (bao gồm các khoảng trắng để dễ đọc) sử dụng chức năng trò chơi:

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

Bạn có thể chơi trong đoạn trích dưới đây! Các số ở bên trái chỉ để bảng điều khiển (ít nhất là chrome) không hợp nhất các hàng.

Để chạy mã:

  1. nhấn "chạy đoạn mã"
  2. nhấn ctrl-shift-j để mở giao diện điều khiển
  3. bấm vào phần kết quả
  4. sử dụng các phím mũi tên và chơi

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

Chưa chơi gôn:

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

Chỉnh sửa 1: Đọc quy tắc cẩn thận hơn và viết lại mã của tôi cho phù hợp

  • giá trị bùa hộ mệnh hiện được chọn ngẫu nhiên
  • người chơi không thể thoát khỏi phòng
  • Tôi không còn đếm các ký tự trong hàm vẽ hoặc gọi nó

1

SpecBAS - 428 402 (không bao gồm in, 466 425 khi được tính)

Sử dụng Q / A / O / P để di chuyển lên / xuống / trái / phải tương ứng.

Dòng để in dungeon ở dòng 1 là dòng duy nhất có thể bị bỏ qua, nhưng cũng đã đánh golf xuống một chút.

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

Tham chiếu đến # 34 chỉ là một cách ngắn gọn để đưa CHR $ (34) vào mã.

Cảm ơn @Thomas Kwa, tôi đã không nhận thấy vị trí bắt đầu của người chơi là ngẫu nhiên là tùy chọn. Cũng sử dụng các câu lệnh IF riêng để cạo một vài ký tự.


Bạn có thể lưu một số ký tự bằng cách ngẫu nhiên ít tốt hơn: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)và cũng sử dụng IF instead of ELSE IF.
lirtosiast

1

Một C # khác, 221 171 170

Đây là một cách khác trong C # với cả hai vị trí ngẫu nhiên. Muốn thể hiện điều này ngay cả khi phần này dài hơn 7 byte so với giải pháp của Hand-E-Food.
Tất nhiên, câu trả lời của Hand-E-Food sẽ ngắn hơn ngay khi anh ta sử dụng Console.Read ().
Nhược điểm của Consol.Read là, việc nhấn Enter cần thiết sẽ khiến trường được in thêm 2 lần nữa.
Nhưng tôi không nghĩ có một yêu cầu chỉ in trên đầu vào (thực).

Điều hướng được thực hiện bởi 8426 như trong giải pháp Thực phẩm tay.

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


Chỉnh sửa: (đã thêm giải pháp mới và di chuyển Máy in đến cuối)
Edit2: (đã thay đổi 14 thành 15 và lưu byte bằng cách bắt đầu ở dưới cùng bên phải) Điều

chỉnh kỹ thuật của Mauris có thể làm tan chảy nó xuống còn 171 byte trong C # (tất nhiên bây giờ không có cả hai vị trí ngẫu nhiên):

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

Lớp Máy in gần giống nhau, chỉ là một bản in quá tải mới ...

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

Đây là một ví dụ về Ruby.
Tôi rất mới với Ruby, có lẽ ai đó biết cách làm điều đó tốt hơn :)

Tôi đã tính các nguồn cấp dữ liệu là 1 vì Chương trình sẽ bị sập ...

Điều hướng được thực hiện bởi 8462. Bạn cần gửi đầu vào mỗi lần nhập.

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 byte

Theo các quy tắc của thử thách, Showchương trình con không được bao gồm trong số đếm byte, cũng không phải là Show p, q, a, bcuộc gọi (với dòng mới sau đây).

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

Để di chuyển, nhập số và nhấn Enter: 1để sang trái, 2đi lên, 3sang phải và 4đi xuống.

Mã này không xuất ra trạng thái trò chơi ở cuối, khi người chơi đã tìm thấy bùa hộ mệnh. Để làm cho nó làm như vậy, thêm một cái khác Show p, q, a, bsau IFtuyên bố.

Giải trình

Hãy a, bđại diện cho tọa độ của bùa hộ mệnh và p, qtọa độ của người chơi. Người chơi bắt đầu ở (0, 0) và bùa hộ mệnh bắt đầu ở hàng 0, với một cột trong khoảng từ 1 đến 9, bao gồm, dựa trên chữ số 1 của thời điểm hiện tại.

Phần còn lại chỉ là một loạt các toán học với điều kiện. Điều quan trọng cần nhớ là các điều kiện trong QBasic trả về 0sai, -1là đúng. Hãy xem tuyên bố cập nhật hàng người chơi:

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

Nếu m=2, chúng tôi muốn di chuyển lên bằng cách trừ 1 từ p, miễn là p>0. Tương tự, nếu m=4, chúng tôi muốn chuyển xuống bằng cách thêm 1 vào p, miễn là p<4. Chúng ta có thể có được hành vi mong muốn bằng cách nhân. Nếu cả hai yếu tố -1, sản phẩm của họ sẽ 1, mà chúng ta có thể trừ hoặc thêm vào p. Nếu một trong hai điều kiện là 0, sản phẩm sẽ 0không có hiệu lực.

Tương tự, điều kiện để xác định xem người chơi có tìm thấy bùa hộ mệnh hay không là:

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

Nếu một trong hai điều kiện là đúng, tổng của chúng sẽ khác 0 (hoặc -1hoặc -2) và do đó, và chương trình trở về dòng 1. Một khi pbằng aqbằng b, cả hai điều kiện sẽ là 0, vì vậy tổng của chúng sẽ 0và dòng điều khiển có thể đạt đến kết thúc chương trình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.