Мінімальний NetHack


64

NetHack - це шахрайська гра, в якій гравець повинен отримати Амулет Єндора з найнижчого рівня підземелля. Зазвичай грається через telnet, вся гра представлена ​​графікою ASCII. Гра надзвичайно складна і вимагає знань багатьох ігрових механіків, щоб досягти успіху.

Для цілей цього виклику припустіть, що вся підземелля - це однорівневий і лише 5 × 16 символів. Крім того, припустимо, що це "безпечне" підземелля або що ви лише впроваджуєте прототип - не буде жодних монстрів, побоювань з приводу голоду тощо. Насправді потрібно лише відстежувати місцезнаходження персонажа та амулет та гру фактично закінчиться, коли гравець прибуде в те саме місце, що і амулет.

Виклики вимог

  • Буде підземелля 5 × 16 (однорівневий).
  • Дайте гравцеві початкове місце (необов'язково випадковий) та амулет окремим випадковим випадком (різним щоразу, коли програма запускається), починаючи квадрат у підземеллі. Тобто амулет не дозволяється запускати на тому ж квадраті, що і гравцеві.
  • Прийміть чотири клавіші введення, які переміщують гравця по одному квадрату (чотири кардинальні напрямки). Читання / обробка іншого вводу дозволено (функція readline (), яка потребує натискання клавіші "enter" тощо).
  • Подорож за межі підземелля заборонена. Наприклад, якщо гравець знаходиться на правій грані підземелля, натискаючи праворуч, нічого не повинно робити.
  • Після початкового покоління та після кожного руху надрукуйте стан гри. Оскільки це гольф коду, а друк є досить нецікавим, ігноруйте кількість символів для функції друку та виклику функції, не допускаючи змін стану . Порожні клітинки повинні бути показані у вигляді періоду ( .), амулета як подвійна цитата ( ") та символу як у символу ( @).
  • Гра закінчена, коли гравець «виявить» амулет (потрапляє на ту саму площу)

Перемога

Це кодовий гольф-виклик, найкоротший код для задоволення вимог через тиждень з сьогоднішнього дня буде оголошено переможцем.

Приклад

Ось приклад рішення в C # (необгрунтований), щоб показати основні вимоги та вибірки.

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

Загальна кількість символів - 1474, але остання кількість символів - ігнорування дзвінків до функції друку та її визначення 896.

Вихід при запуску програми:

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

Вихід (у тому числі вище) після натискання клавіші "a" двічі:

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

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

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

10
У мене є відчуття, що це буде цікаво @Doorknob.
Олексій А.

10
Rogue - це оригінальна грабієцька гра, де гравець повинен витягти Амулет Єндора з найнижчого рівня підземелля. Чому б не назвати це мінімальним негідником?
Жиль

5
@Gilles Чому б не назвати це мінімальною змією?
Кейсі Кубалл

26
Psshh, немає діагонального руху? Ні yubnhjkl? Навіть сходами на підйом, щоб піднятися після отримання оберега? : P ( люто upvotes так чи інакше )
дверна ручка

2
@tolos: Мені все ще незрозуміло, що тут вважається випадковим . Насправді неможливо виконати різні вимоги кожного разу, коли програма запускається, якщо програма запускається 80 разів ... Зокрема, у цій відповіді амулет може займати лише 9 з усіх 79 можливих місць. Це враховує?
Денніс

Відповіді:


37

TI-BASIC, 42 41 38 36 35 байт

Для вашого калькулятора графіків серії TI-83 або 84+.

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

У якому напрямку гравець піде - це функція коду клавіші натиснутої клавіші, але чотири клавіші, які точно працюють, - це у верхньому рядку:

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

Амулет починається на одному з п’яти квадратів у першій колонці, а гравець починається з правого нижнього квадрата. Наприклад, можлива домовленість:

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

Пояснення

Позиція гравця зберігається як складне число від 0+0iдо 15+4i, де реальна частина йде вправо, а уявна частина йде вниз. Це полегшує перевірку меж у верхній і лівій частині: ми просто зміщуємо число злегка і округлюємо до нуля. Наприклад, якщо зсув є, 0.5а наше положення - -1+3i(поза екраном зліва), то позиція буде виправлена ​​в те місце iPart(-0.5+3.5i)=0+3i, де воно має бути. Перевірка нижньої та правої меж трохи складніше; нам потрібно відняти число від константи C, яка є приблизно 15.635 + 4.093i(це найкоротший, який я міг знайти між 15+4iі 16+5i), округнути, відняти Cзнову, щоб повернути число назад, і знову обвести.

Якщо натиснути клавішу, невідрегульована позиція гравця переміститься на 1 одиницю в деякому напрямку, але ціла частина змінюється лише при натисканні певних клавіш. На щастя, клавіші, які працюють, знаходяться у верхньому ряду. Нижче наведено графік відступів у випадках, коли натискаються клавіші 11, 12, 13 і 15, і коли не натискається жодна клавіша (Жодне натискання не є точкою всередині центральної площі, внаслідок чого цілі частини не змінюються; чотири натискання клавіш 'зсуви мають різні цілі частини). C- червоний хрест у центрі кола.

введіть тут опис зображення

Старий код (42 байти):

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

Обмеження

Немає можливості уникнути "символу, тому рядки з символом "не можна генерувати всередині програми. Тому для цього використовується позначка umlaut ¨замість цитати (якби вже існував рядок із лапкою, я міг би це відобразити). Щоб отримати ¨і @в програмі, потрібно зовнішній інструмент; однак це дійсно TI-BASIC.


2
Для розваги я зробив цей фрагмент, який поміщає діарез і символ @ у Str1 (на відміну від «зовнішнього інструмента»). Виберіть рядок у верхній частині, що відповідає вашому калькулятору, введіть його в нову програму та запустіть програму з Asm (.
MI Wright

О, я забув про кодування машинного коду на калькуляторі. Не хочу зламати шахту, але я впевнений, що це працює.
lirtosiast

44

CHIP-8 , 48 байт

Це, можливо, не вважається законним, але чому, пекло, ні. Я написав свою програму в CHIP-8, мові програмування на основі байт-коду для віртуальної ігрової консолі. Ви можете спробувати повну програму (99 байт) у вашому браузері за допомогою емулятора / налагоджувача, який я написав під назвою Octo:

Знімок екрана

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

Шестнадцятковий дамп цієї повної програми такий:

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

Ви можете переміщати програвач за допомогою клавіш ASWD або клавіш 7589 на оригінальній клавіатурі CHIP-8. Якщо я видаляю весь код і дані для малювання фону та програвача, я замість цього отримую цей дамб на 48 байтів:

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

Невиконана, повна форма програми була написана асемблерною мовою високого рівня наступним чином:

: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

Зверніть увагу , що скомпільований байт самі є мова програмування ЧІП-8; асемблер - просто більш зручний засіб складання таких програм.


19
Правильний інструмент для роботи.
Денніс

6
+1 за те, щоб змусити мене витрачати купу часу, граючи у вашу гру знову і знову.
Алекс А.

4
@AlexA. якщо ви хочете витрачати ще більше часу, спробуйте Cave Explorer . ASWD переміщення у overorld та QE використовуються для скидання / переміщення блоків на платформерних рівнях.
JohnE

4
Чудово, ну там проходять мої вихідні.
Олексій А.

1
Я спочатку скептично ставився, але Cave Explorer був веселим, і CHIP-8 був набагато довше, ніж я б здогадався. Тож я думаю, що мені доведеться це навчитися.

10

Python 3, 86 байт

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]

Тільки підрахунок двох нижніх рядків і скидання d();.


Я врятував ще один байт, запустивши програвач у правому нижньому куті ("останній" квадрат), а потім випадковим чином відібрав вибір з перших 79 квадратів.
Лінн

На жаль, вибачте, виправлено! Напевно, я не дивуюсь вручну підраховувати байти. : <
Лінн

1
Я думаю, ви можете зберегти інший символ, замінивши a=id(9)%79на a=id(9)%p.
kirbyfan64sos

@ kirbyfan64sos Блискучий! Дякую.
Лінн

1
Крім того, якщо ви зробите це для Python 3, ви можете змінити raw_inputвиклик на просто input.
kirbyfan64sos

10

C, 122 121 115 104 102 101 байт

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

Перший раз розміщую тут! Я сподіваюся, вам сподобається :)

oє функція друку, erm, функції. Нашого хороброго героя можна пересунути за допомогою 2, 4, 6 і 8, але остерігайтеся не надсилати будь-який інший вклад (жодних нових рядків!).

Оновлення 1: введено aі iв main's параметри.

Оновлення 2: ОП підтвердив, що один рядок вводу в порядку, я позбувся scanf(що я пропускав новий рядок).

Оновлення 3: Використовували складений літерал масиву та змінювали макет введення. Програма тепер переходить у сірий, якщо ви введете неправильний напрямок;)

Оновлення 4: Помічено, що виклик функції друку не враховується. Зауважив, щоб уважніше читати правила.

Оновлення 5: один байт збережений, завдяки Мікелю Алану Стоккебі Крістіа.


Може !!(p%16)бути p%16>0? Я не пам'ятаю свого порядку операцій.
lirtosiast

@ThomasKwa це так, але цей унар -не може не дотримуватися p, тому дужки потрібні в будь-якому випадку. Подвійний удар - просто заплутаний :)
Квентін

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

@MikkelAlanStokkebyeChristia дякую :)
Квентін

9

CJam, 46 45 44 40 39 37 байт

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

Перший рядок (визначає функцію, яка друкує поточний стан гри) та P у другому рядку (викликайте цю функцію) не вносять внесок у кількість байтів.

Як вихідне, так і положення амулета вибираються псевдовипадково. Розподіл є настільки ж рівномірним, що дозволяє базовий PRNG.

Введення є E, 6, 9і Bдля Up , вниз , вліво і вправо , з Caps Lockактивовано, а потім Enter.

Альтернативна версія

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

Ціною ще чотирьох байтів формат введення значно покращується:

  • Ця версія приймає 8, 2, 4і 6для Up , вниз , вліво і вправо , що відповідає відповідні клавіші зі стрілками на цифровій клавіатурі.
  • Він також приймає 7, 9, 1і 3для відповідних діагональних ходів.

Тестування

Оскільки введення / виведення є інтерактивним, слід спробувати цей код з інтерпретатором Java .

Завантажте останню версію та запустіть програму так:

java -jar cjam-0.6.5.jar nethack.cjam

Щоб уникнути натискання Enterпісля кожної клавіші та для оновлення результатів на місці, ви можете використовувати цю обгортку:

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

Викликайте так:

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

Основна версія

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.

Альтернативна версія

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.

Функція 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! Я опублікую повідомлення, як тільки я підтверджу своє рішення.
ліртосіаст

8

Java, 231 байт (якщо функція 196)

Ось повний код програми на 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":""));}}}

Без функції друку 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);}}

Якщо з функцією все добре (мені незрозуміло), я можу скоротити цю функцію до 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);}

І з деякими розривами рядків для трохи ясності ...

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

Зверніть увагу , що я не брати до уваги функцію друку p(p,y)себе, але я я розраховую на виклик до нього, так як у мене є речі , що змінюються в операторі виклику.

Це працює з великої літери ASDW. Завдяки тому, як він перевіряє їх, деякі інші листи можуть також працювати, але специфікація насправді нічого не говорить про те, що має відбутися, якщо я натискаю різні клавіші.


Я вважаю за краще форматувати вкладені потрійні оператори на тому ж рівні відступу, як і ланцюг if / else if. Це читабельніше.
lirtosiast

@ThomasKwa Так, я робив це обома способами часом. Це більше схоже на вкладені, якщо заяви, ніж приковані. Мені це краще, тому що обидві половини кожного трійця знаходяться на одному рівні, але відрізняються від інших.
Геобіт

Якщо анонімна функція є прийнятною, ви можете void m()()->
підкреслити

@ dohaqatar7 Так, але я не використовую анонні функції Java для гольфу з кодом. Мені в принципі здається тіньовим, незалежно від того, відчувають те чи інші.
Геобіт

Можна зробити p+=?
lirtosiast

5

Java, 574 байти

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

В основному те саме, що і версія C #, за винятком прихованого та мінімізованого.


так багато непотрібних просторів ...;)
Will

@ Буду, я щойно це зафіксував: P
фаза

1
Також використовуйте однолітерні назви та тернарі.
lirtosiast

@ThomasKwa зафіксовано: D
фаза

6
Є ще багато непотрібних просторів та нестача територій;)
Буде

5

Юлія, 161 байт

Користі w, a, sі dрухатися вгору, вліво, вниз і вправо по горизонталі.

Повний код, включаючи друк (330 байт):

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

Набраний код, за винятком друку (161 байт):

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

Різниця тут полягає в тому, що ми не зберігаємо ігровий стан як матрицю; вся відповідна інформація міститься в масивах cта a. І, звичайно, нічого не друкується. Користувачеві більше не буде запропоновано вводити дані, коли гравець досягне амулета.


Ungolfed + пояснення (повний код):

# 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

Я думаю, що це нормально

3
+1 для стислої / затуманеної версії, схожа на те, що я пам’ятаю про фактичний вихідний код Nethack.
Бен Джексон

Ви можете зберегти кілька байт, скориставшись гіршою рандомізацією:a=[rand(1:5),1] c=a+1
lirtosiast

@ThomasKwa: Що цікавого, якщо це завжди на першому рядку? :)
Алекс А.

3

Пакетна, 329 байт

@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

Це дуже вражає. Я здивований, що це можна зробити.
eis

Це не відображає підземелля для мене, лише серія рядків, що спонукають [W, A, S, D] ?. Це, здається, "працює" - ходіння по невідомій підземеллі зрештою виходить. win7 cmd.exe
Dan Pritts

Для мене це працює з Win7 cmd.exe - коли я набираю версію, я отримуюMicrosoft Windows [Version 6.1.7601]
Джеррі Джеремія

@DanPritts Це дивно. Мені ідеально підходить для Windows 8 ( Microsoft Windows [Version 6.2.9200])
ankh-morpork

До, я не копіював і не вставляв всю річ, я не прокручувався вниз у вікно. Молодці.
Dan Pritts

3

Perl, 228 222 символів (не рахуючи нових рядків, які не є невід'ємними частинами роботи коду) - 207, якщо не рахувати частин printта print ifоператорів, які використовуються для друку, але не додають до логіки гри; 144, якщо також розглядати код генерації представлення на місцях як частину друку, як це запропонував Yakk у коментарях)

Цей код використовує малу величину wasd для управління; вхід повинен бути підтверджений клавішею Enter. Перевірено за допомогою 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}}

Зауважте, що для цього коду неможливо відокремити обчислення та друк, оскільки операції виконуються безпосередньо над друкованим представленням, використовуючи регулярні вирази.

Пояснення:

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

Ця лінія визначає положення гравця та амулета. Положення гравця визначається $==rand(80)і насправді легко зрозуміти: На дошці 5 × 16 є 80 різних позицій, де може бути гравець. Позиція зберігається в $=змінній, яка змушує збережене значення в ціле число; це економить кілька байтів, щоб не потрібно явно переводити результат на ціле число ( randнадає значення з плаваючою точкою).

Оскільки гравець на одній із позицій вже зайнятий, для амулета залишилось лише 79 позицій, тому для позиції амулета $a=$==rand(79)використовується. Знову ж таки, призначення $=примушує перетворення на ціле число, однак я надалі призначаю його $aдля повторного використання $=на позиції гравця.

Тепер, щоб уникнути того, щоб амулет займав ту саму позицію, що і гравець, його висувають на одну позицію, якщо його позиція принаймні така велика, як і гравця, що дає рівномірний розподіл на місця, які не займають гравець. Це досягається тим, $a = ($a >= $=)де $=тут утримується позиція гравця. Тепер перший рядок генерується, вставляючи два початкових призначення замість першого $a$ and the only$ = `у цьому виразі.

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

Це генерує початкове поле, а потім друкує. ("."x80)просто створює рядок з 80 крапок. =~s/(.{$=})./\1@/rпотім замінює $=й символ з @, а =~s/(.{$=})./\1@/rв $aй символ з ". Завдяки rмодифікатору вони не намагаються змінити їх на місці, але повертають модифіковану рядок, тому вони можуть бути застосовані до попередніх виразів. Нарешті, =~s/(.{16})/\1\n/grвставляє новий рядок кожні 16 символів. Зауважте, що поле зберігається в спеціальній змінній, $_яка може неявно використовуватись у наступних операторах.

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

Це створює хеш, що містить правила заміни для різних ходів. Більш читаною є версія цього

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

Клавішами є символи для ходів, а значення - це рядки, що містять відповідне правило заміни.

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

Це головна петля. while(/"/)перевіряє, чи є ще "символ $_(тобто в полі). Якщо ми переходимо на амулет, його персонаж заміняється символом гравця, щоб він зник з поля.

eval $r{getc STDIN}зчитує символ із стандартного вводу, шукає відповідне правило заміни з значень has %rта застосовує його до $_поля, тобто до поля. Це оцінюється як вірно, якщо заміна була фактично здійснена (тобто ключ знайдено в хеші і переміщення було можливе; неможливий хід не збігатиметься в правилі заміни). У цьому випадку printвиконується. Оскільки він викликається без аргументу, він друкує $_, тобто модифіковане поле.


1
Тільки тому, що ви включаєте рядки ліній для читабельності, не означає, що ви повинні їх рахувати. Я бачу 228 байт. Крім того, відповідно до конкретних правил цього питання, частина друку коду не сприяє кількості байтів.
Денніс

@Dennis: Щодо друкарської частини, дивіться пояснення, яке я зараз додав: Ви не можете змістовно розділити друк та оцінку в моєму коді. Тепер я змінив підрахунок, як ви запропонували.
celtschk

Чи є якісь зміни стану вашого коду друку? Немає? Ну, на мою думку, повторне використання виводу коду друку для вашої логіки не повинно вас штрафувати. Код руху (який виразний!) Повинен рахуватися, але код, який генерує "рядок відображення", не повинен рахуватися.
Якк

@Yakk: Яку частину мого коду ви вважаєте кодом друку? (Насправді, на мою думку, виключення друкарського коду з підрахунку було поганою ідеєю саме тому, що не завжди точно визначено, що таке "код друку".)
celtschk

@celtschk ("."x80)=~s/(.{$=})./\1@/r=~s/(.{$a})./\1"/r=~s/(.{16})/\1\n/grна перший погляд досить близький, але мій перл-фу на кілька років іржавий. Я міг пропустити там зміну штату.
Якк

2

C #, 256 248 234 227 226 225 байт

Для переміщення використовує стрілки NumPad із увімкненою NumLock.

Відступ та коментар для наочності:

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 # ints неявно init до нуля. Крім того (зараз не можу перевірити), якщо кастинг не є проблемою, ви можете перетворити символи прямолінійних знаків в ints або, принаймні, "a" до 97 (я думаю), хоча інші - тризначні.

За замовчуванням ініціалізуються лише поля класів, і це вимагає, щоб вони були оголошені статичними в цьому випадку. Змінні методу повинні бути ініціалізовані перед першим використанням. Це займе менше символів: 4 проти 7.
Hand-E-Food

Дякуємо @tolos за пораду про неявне лиття char to int! А ще краще, якщо я використовую перелік перерахунку ConsoleKey як int, я можу використовувати двозначні значення.
Hand-E-Food

Технічно Mainметод не потрібно викликати Main, тому ви можете поголити ще трьох символів.
Луань

@Luaan, я думаю, ти помилився. C # документація: msdn.microsoft.com/en-us/library/acy3edy3.aspx
Hand-E-Food

2

Html + JavaScript (ES6), оцінка може бути 217

Занадто довгий, але відтворюваний в Інтернеті у фрагментах нижче.

Рядок 6 (T.value ...) призначений для виведення та не враховується (але для простоти я підрахував тегиreatarea відкритих і закритих тегів, навіть якщо це також вихід)

Що стосується випадковості: амулет завжди знаходиться у правій половині сітки, а гравець завжди починається в лівій половині.

Клацніть на текстArea (після його збільшення), щоб почати та перезапустити гру.

<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 (лише 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 (тестується в 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

Сценарій дій 3: 267 байт

Робочим прикладом є Інтернет

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

Ось повна (білі простори, включені для читання) з використанням ігрової функції:

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

Ви можете грати у фрагмент нижче! Цифри ліворуч - це лише те, що консоль (принаймні хромована) не зливає рядки.

Для запуску коду:

  1. натисніть "фрагмент запуску коду"
  2. натисніть ctrl-shift-j, щоб відкрити консоль
  3. натисніть у розділі результатів
  4. використовувати клавіші зі стрілками і грати

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

Без гольфу:

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

Редагувати 1: уважніше читати правила і відповідно переписати мій код

  • значення amulet y тепер рандомізоване
  • Гравець більше не може вийти з кімнати
  • Я більше не рахую символів у функції малювання або дзвінків до неї

1

SpecBAS - 428 402 (без урахування друку, 466 425 при підрахунку)

Використовує Q / A / O / P для переміщення відповідно вгору / вниз / вліво / вправо.

Рядок для друку підземелля в рядку 1 - це єдиний рядок, який можна ігнорувати, але також пропустив цей гольф.

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 - це лише короткий спосіб введення CHR $ (34) у код.

Дякую @Thomas Kwa, я не помітив, що стартова позиція гравця була випадковою. Також використовували окремі оператори IF для гоління кількох символів.


Можливо, ви зможете зберегти деякі символи шляхом рандомізації менш добре: 2 LET px=1: LET py=1: LET ax=2: LET ay=INT(RND*5)а також за допомогою IF instead of ELSE IF.
lirtosiast

1

Ще один C #, 221 171 170

Ось ще один спосіб у C # з обома позиціями випадковим чином. Хотіла показати це, навіть якщо ця частина на 7 байт довша за рішення Hand-E-Food.
Відповідь Hand-E-Food буде, звичайно, коротшою, як тільки він скористається Console.Read ().
Мінус Consol.Read полягає в тому, що натискання потрібного клавіші Enter надрукує поле ще 2 рази.
Але я не думаю, що існує потреба друкувати лише на (реальний) ввід.

Навігація виконується 8426, як у розчині 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;
}
}
}


Редагувати: (додано нове рішення та перемістили PrinterClass до кінця)
Edit2: (змінив 14 на 15 і

зберег байт, починаючи справа внизу). (звичайно, зараз без обох позицій випадковим чином):

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

Клас принтерів майже такий же, лише нове перевантаження друку ...

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

Рубі, 185

Ось і приклад Ruby.
Я дуже новачок у Рубі, можливо, хтось знає, як це зробити краще :)

Я порахував lineFeeds як 1, оскільки програма вийде з ладу в іншому випадку ...

Навігація виконується 8462. Потрібно надсилати введення кожен раз, коли клавіша Enter.

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 байти

Згідно з правилами виклику, Showпідпрограма не включається до підрахунку байтів, а також Show p, q, a, bвиклику (із наступним новим рядком).

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

Щоб переміститись, введіть число і натисніть Enter: 1щоб піти вліво, 2вгору, 3вправо і 4вниз.

Цей код не виводить ігровий стан наприкінці, коли гравець знайшов амулет. Щоб це зробити так, додайте ще один Show p, q, a, bпісля IFзаяви.

Пояснення

Нехай a, bпредставляють координати амулета і p, qкоординати гравця. Гравець починається з (0, 0), а амулет починається з рядка 0 зі стовпцем між 1 і 9 включно, виходячи з цифри 1 поточного часу.

Решта - лише купа математики з умовними умовами. Важливо пам’ятати, що умовні умови в QBasic повертаються 0за хибними, -1за істинними. Давайте подивимось на заяву оновлення рядка плеєра:

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

Якщо m=2ми хочемо рухатися вгору, віднімаючи 1 з p, до тих пір, як p>0. Аналогічно, якщо m=4ми хочемо рухатися вниз, додаючи 1 до p, до тих пір, як p<4. Ми можемо отримати бажану поведінку шляхом множення. Якщо обидва фактори є -1, то їх продуктом буде такий 1, який ми можемо відняти або додати p. Якщо це будь-яке умовне 0, продукт буде 0без ефекту.

Аналогічно, умовою для визначення того, чи виявив гравець амулет, є:

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

Якщо будь-який із умов є правдивим, їх сума буде ненульовою (або -1або -2), і, таким чином, правдоподібною, і програма повертається до рядка 1. Коли pдорівнює aі qдорівнює b, обидва умовні будуть 0, тому їх сума буде 0і контрольний потік може досягти кінець програми.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.