У моєму терміналі йде дощ!


24

Опис виклику

Ви повинні показати моделювання дощу в терміналі.

У наведеному нижче прикладі додається 100 дощових крапель навмання (використовуйте випадкову функцію за умовчанням, яку пропонує ваша мова), координуючись, чекаючи 0,2 секунди, а потім перемальовуючи знову, поки не закінчиться заданий час. Будь-який символ може бути використаний для представлення краплі дощу.

Параметри

  • Зачекайте час між перемальовуванням в секундах.
  • Час, за який буде видно дощ. Це просто ціле число, що представляє кількість ітерацій. [Отже, чистий час, протягом якого буде видно дощ, це ціле число, помножене на час очікування]
  • Повідомлення, яке відображатиметься після закінчення дощу. (Це має бути по центру)
  • Кількість крапель дощу, які потрібно відобразити на екрані.

Правила

  • Один байт повинен використовуватися для представлення краплі дощу, і це може бути будь-що, навіть кішки та собаки.
  • Він не повинен відповідати розміру терміналу, а це означає, що вам не доведеться обробляти помилку для різних розмірів терміналу. Ви можете самостійно вказати ширину та висоту клеми.
  • Діють стандартні правила проведення гольфу.

Зразок та вихідний код

Це незворушена версія, написана в python 2.7 за допомогою ncurses.

import curses
import random
import time

myscreen = curses.initscr()
curses.curs_set(0) # no cursor please 
HEIGHT, WIDTH = myscreen.getmaxyx() 
RAIN = '/' # this is what my rain drop looks like 
TIME = 10 

def make_it_rain(window, tot_time, msg, wait_time, num_drops):
    """
    window    :: curses window 
    time      :: Total time for which it rains
    msg       :: Message displayed when it stops raining
    wait_time :: Time between redrawing scene 
    num_drops :: Number of rain drops in the scene 
    """
    for _ in range(tot_time):
        for i in range(num_drops):
            x,y=random.randint(1, HEIGHT-2),random.randint(1,WIDTH-2)       
            window.addstr(x,y,RAIN)
        window.refresh()
        time.sleep(wait_time)
        window.erase()

    window.refresh()
    window.addstr(HEIGHT/2, int(WIDTH/2.7), msg)


if __name__ == '__main__':
    make_it_rain(myscreen, TIME, 'IT HAS STOPPED RAINING!', 0.2, 100)
    myscreen.getch()
    curses.endwin()

Вихід -

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


3
Надалі замість публікації знову відредагуйте оригінал. Якщо люди вважають, що специфікації зрозумілі, вони висунуть його на повторне відкриття.
Пшеничний майстер

6
Чи має бути текст по центру? Довільно йде дощ, чи має значення початкове положення крапель? Як ви вимірюєте час? У мілісекундах, секундах, хвилинах? Що таке "додаткові бали"?
Чарівний восьминіг Урна

1
Якщо ви, А. Вкажіть одиниці. B. Вкажіть розмір терміналу або візьміть його як вхід. і C. Приберіть частину про додаткові точки; цю проблему краще визначити.
Чарівний восьминіг Урна

Коли ви говорите "випадковий", чи можна вважати, що це означає "рівномірно випадковий" ?
Цифрова травма

3
1 день у пісочниці часто недостатньо. Пам'ятайте, що люди тут є рекреаційно та з різних часових поясів - негайного зворотного зв’язку не слід очікувати.
Цифрова травма

Відповіді:


12

MATL , 52 байти

xxx:"1GY.Xx2e3Z@25eHG>~47*cD]Xx12:~c!3G80yn-H/kZ"why

Введення в такому порядку: пауза між оновленнями, кількістю крапель, повідомленням, кількістю повторень. Монітор має розмір 80 × 25 символів (жорстко закодований).

GIF або цього не сталося! (Приклад з входами 0.2, 100, 'THE END', 30)

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

Або спробуйте в MATL Online .

Пояснення

xxx      % Take first three inputs implicitly and delete them (but they get
         % copied into clipboard G)
:"       % Take fourth input implicitly. Repeat that many times
  1G     %   Push first input (pause time)
  Y.     %   Pause that many seconds
  Xx     %   Clear screen
  2e3    %   Push 2000 (number of chars in the monitor, 80*25)
  Z@     %   Push random permutation of the integers from 1 to 2000
  25e    %   Reshape as a 25×80 matrix, which contains the numbers from 1 to 2000
         %   in random positions
  HG     %   Push second input (number of drops)
  >~     %   Set numbers that are <= second input to 1, and the rest to 0
  47*c   %   Multiply by 47 (ASCII for '/') and convert to char. Char 0 will
         %   be displayed as a space
  D      %   Display
]        % End
Xx       % Clear screen
12:~     % Push row vector of twelve zeros
c!       % Convert to char and transpose. This will produce 12 lines containing
         % a space, to vertically center the message in the 25-row monitor
3G       % Push third input (message string)
80       % Push 80
yn       % Duplicate message string and push its length
-        % Subtract
H/k      % Divide by 2 and round down
Z"       % Push string of that many spaces, to horizontally center the message 
         % in the 80-column monitor
w        % Swap
h        % Concatenate horizontally
y        % Duplicate the column vector of 12 spaces to fill the monitor
         % Implicitly display

1
Мені подобається, як це закінчується why:)
tkellehe

1
@tkellehe Мені подобається опис у вашому профілі :-)
Луїс Мендо

1
Дякую тобі. Вашу мову так цікаво читати. (Так, я переслідую ваші відповіді MATL хаха )
tkellehe

10

JavaScript (ES6), 268 261 байт

t=
(o,f,d,r,m,g=(r,_,x=Math.random()*78|0,y=Math.random()*9|0)=>r?g(r-(d[y][x]<`/`),d[y][x]=`/`):d.map(a=>a.join``).join`
`)=>i=setInterval(_=>o.data=f--?g(r,d=[...Array(9)].map(_=>[...` `.repeat(78)])):`



`+` `.repeat(40-m.length/2,clearInterval(i))+m,d*1e3)
<input id=f size=10 placeholder="# of frames"><input id=d placeholder="Interval between frames"><input id=r size=10 placeholder="# of raindrops"><input id=m placeholder="End message"><input type=button value=Go onclick=t(o.firstChild,+f.value,+d.value,+r.value,m.value)><pre id=o>&nbsp;

Принаймні, у моєму браузері вихід призначений для розміщення в області фрагмента стека без необхідності переходити на «Повну сторінку», тому якщо ви попросите більше 702 крапель дощу, він вийде з ладу.

Редагувати: Збережено 7 байтів, використовуючи текстовий вузол як зону виводу.


Ви можете зберегти кілька байт, передавши функцію у вигляді рядка setInterval. Крім того, чому ви використовуєте textContentзамість цього innerHTML?
Лука

@ L.Serné Використання внутрішньої функції дозволяє мені звертатися до змінних у зовнішній функції.
Ніл

На жаль, я не помітив цього.
Лука

8

R, 196 192 185 байт

Просто макетна версія, яку я написав на основі опису. Сподіваємось, це дещо те, що шукав ОП.

Збережено кілька байтів завдяки @plannapus.

f=function(w,t,m,n){for(i in 1:t){x=matrix(" ",100,23);x[sample(2300,n)]="/";cat("\f",rbind(x,"\n"),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",11),rep(" ",(100-nchar(m))/2),m,g,sep="")}

Аргументи:

  • w: Зачекайте час між кадрами
  • t: Загальна кількість кадрів
  • m: Користувацьке повідомлення
  • n: Кількість крапель дощу

Приклад

Чому це схоже на те, що йде дощ?

Редагувати: Я мушу зазначити, що це моя індивідуальна консоль R-студії 23х100 символів. Розміри жорстко вводяться у функцію, але можна, в принципі, використовувати getOption("width")її для гнучкості до розміру консолі.

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

Безумовно і пояснив

f=function(w,t,m,n){
    for(i in 1:t){
        x=matrix(" ",100,23);             # Initialize matrix of console size
        x[sample(2300,n)]="/";            # Insert t randomly sampled "/"
        cat("\f",rbind(x,"\n"),sep="");   # Add newlines and print one frame
        Sys.sleep(w)                      # Sleep 
    };
    cat("\f",g<-rep("\n",11),rep(" ",(100-nchar(m))/2),m,g,sep="")  # Print centered msg
}

Це виглядає ідеально добре! +1, і я не думаю, що це відбувається вгору, це лише ваше сприйняття хаха
hashcode55

@plannapus. Реалізований rep()автоматично заповнює timesаргумент, тому в цьому немає потреби. Збережено ще 7 байт!
Billywob

Дуже приємне рішення. Ви можете зберегти один байт, натиснувши розмір консолі для функціонування аргументів (якщо це дозволено); ви можете зберегти інший байт, використовуючи, runifа не sampleвипадкове заповнення матриці. f=function(w,t,m,n,x,y){for(i in 1:t){r=matrix(" ",x,y);r[runif(n)*x*y]="/";cat("\f",rbind(r,"\n"),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",y/2),rep(" ",(x-nchar(m))/2),m,g,sep="")}
Ось

5

C 160 байт

f(v,d,w,char *s){i,j;char c='/';for(i=0;i<v;i++){for(j=0;j<d;j++)printf("%*c",(rand()%100),c);fflush(stdout);sleep(w);}system("clear");printf("%*s\n",1000,s);}

v-Time the raindrops are visible in seconds.
d-Number of drops per iteration
w-Wait time in seconds, before the next iteration
s-String to be passed on once its done

Негольована версія:

void f(int v, int d, int w,char *s)
{ 

   char c='/';
   for(int i=0;i<v;i++)
   { 
      for(int j=0;j<d;j++)
         printf("%*c",(rand()%100),c);

      fflush(stdout);
      sleep(w); 
   }   
   system("clear");
   printf("%*s\n", 1000,s);
}

Тестова шафа на моєму терміналі

v - 5 seconds
d - 100 drops
w - 1 second wait time
s - "Raining Blood" :)

4

R, 163 символів

f=function(w,t,n,m){for(i in 1:t){cat("\f",sample(rep(c("/"," "),c(n,1920-n))),sep="");Sys.sleep(w)};cat("\f",g<-rep("\n",12),rep(" ",(80-nchar(m))/2),m,g,sep="")}

З відступами та новими рядками:

f=function(w,t,n,m){
    for(i in 1:t){
        cat("\f",sample(rep(c("/"," "),c(n,1920-n))),sep="")
        Sys.sleep(w)
    }
    cat("\f",g<-rep("\n",12),rep(" ",(80-nchar(m))/2),m,g,sep="")
}

Він адаптований до терміналу розміром 24 рядки на 80 стовпців. w- час очікування, tкількість кадрів, nкількість крапель дощу та mостаточне повідомлення.

Він відрізняється від @ відповідь billywob в в інше використання sample: якщо вихідний розмір не вказаний, sampleдає перестановку вхідного вектора (тут вектор , що містить необхідну кількість дощових крапель і відповідну кількість прогалин, завдяки тому , що аргумент timesпро функція repвекторизована). Оскільки розмір вектора точно відповідає розміру екрана, немає необхідності додавати нові рядки або форсувати його в матрицю.

Gif виходу


3

NodeJS: 691 158 148 байт

Редагувати

За потребою видалено додаткові функції та гольф.

s=[];setInterval(()=>{s=s.slice(L='',9);for(;!L[30];)L+=' |'[Math.random()*10&1];s.unshift(L);console.log("\u001b[2J\u001b[0;0H"+s.join('\n'))},99)

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

s='';setInterval(()=>{for(s='\n'+s.slice(0,290);!s[300];)s=' |'[Math.random()*10&1]+s;console.log("\u001b[2J\u001b[0;0H"+s)},99)

Попередня відповідь

Можливо, не найкращий гольф, але я трохи захопився. Він має необов'язковий напрямок вітру та коефіцієнт дощу.

node rain.js 0 0.3

var H=process.stdout.rows-2, W=process.stdout.columns,wnd=(arg=process.argv)[2]||0, rf=arg[3]||0.3, s=[];
let clr=()=>{ console.log("\u001b[2J\u001b[0;0H") }
let nc=()=>{ return ~~(Math.random()*1+rf) }
let nl=()=>{ L=[];for(i=0;i<W;i++)L.push(nc()); return L}
let itrl=(l)=>{ for(w=0;w<wnd;w++){l.pop();l.unshift(nc())}for(w=0;w>wnd;w--){l.shift();l.push(nc())};return l }
let itrs=()=>{ if(s.length>H)s.pop();s.unshift(nl());s.map(v=>itrl(v)) }
let d=(c,i)=>{if(!c)return ' ';if(i==H)return '*';if(wnd<0)return '/';if(wnd>0)return '\\';return '|'}
let drw=(s)=>{ console.log(s.map((v,i)=>{ return v.map(  c=>d(c,i)  ).join('') }).join('\r\n')) }
setInterval(()=>{itrs();clr();drw(s)},100)

Дивіться веб-сайт, який працює тут


2

Локшина , не конкуруючий 44 байти

У центрі мого списку речей, які я робив, я мав текст центрування ... Але я був ледачий і не додав до цього завдання. Отже, тут я не змагаюся, але розважався з викликом :)

ØGQÆ×Øæ3/×Æ3I_ȥ⁻¤×⁺Æ1Ḷḋŀ÷25¶İÇæḍ€Æ1uụC¶×12⁺ß

Розмір консолі важко закодований до 25x50, що не дуже добре виглядає в онлайн-редакторі, але для фрагменту.

Спробуй це:)


Як це працює

Ø                                            # Pushes all of the inputs from the stack directly back into the stdin since it is the first token.

 GQÆ×Ø                                       # Turns the seconds into milliseconds since can only delay by milliseconds.
 GQ                                          # Pushes on the string "GQ" onto the top of the stack.
   Æ                                         # Consumes from stdin the value in the front and pushes it onto the stack which is the number of seconds to delay.
    ×                                        # Multiplies the two items on top of the stack.
                                             # Since the top of the stack is a number, the second parameter will be converted into a number. But, this will fail for the string "GQ" therein treated as a base 98 number producing 1000.
     Ø                                       # Pops off the new value, and pushes it into the front of stdin.

      æ3/×Æ3I_ȥ⁻¤×⁺                          # Creates the correct amount of rain drops and spaces to be displayed in a 50x25 console.
      æ3                                     # Copies the forth parameter (the number of rain drops).
        /                                    # Pushes the character "/" as the rain drop character.
         ×                                   # Repeats the rain drop character the specified number of times provided.
          Æ3                                 # Consumes the number of rain drops from stdin.
            I_                               # Pushes the string "I_" onto the stack.
              ȥ                              # Converts the string into a number as if it were a base 98 number producing 25 * 50 = 1250.
               ⁻                             # Subtract 1250 - [number rain drops] to get the number of spaces.
                ¤                            # Pushes on the string "¤" which for Noodel is a space.
                 ×                           # Replicate the "¤" that number of times.
                  ⁺                          # Concatenate the spaces with the rain drops.

                   Æ1Ḷḋŀ÷25¬İÇæḍ€            # Handles the animation of the rain drops.
                   Æ1                        # Consumes and pushes on the number of times to loop the animation.
                     Ḷ                       # Pops off the number of times to loop and loops the following code that many times.
                      ḋ                      # Duplicate the string with the rain drops and spaces.
                       ŀ                     # Shuffle the string using Fisher-Yates algorithm.
                        ÷25                  # Divide it into 25 equal parts and push on an array containing those parts.
                           ¶                 # Pushes on the string "¶" which is a new line.
                            İ                # Join the array by the given character.
                             Ç               # Clear the screen and display the rain.
                              æ              # Copy what is on the front of stdin onto the stack which is the number of milliseconds to delay.
                               ḍ             # Delay for the specified number of milliseconds.
                                €            # End of the loop.

                                 Æ1uụC¶×12⁺ß # Creates the centered text that is displayed at the end.
                                 Æ1          # Pushes on the final output string.
                                   u         # Pushes on the string "u" onto the top.
                                    ụC       # Convert the string on the top of the stack to an integer (which will fail and default to base 98 which is 50) then center the input string based off of that width.
                                      ¶      # Push on a the string "¶" which is a new line.
                                       ×12   # Repeat it 12 times.
                                          ⁺  # Append the input string that has been centered to the new lines.
                                           ß # Clear the screen.
                                             # Implicitly push on what is on the top of the stack which is the final output.

<div id="noodel" code="ØGQÆ×Øæ3/×Æ3I_ȥ⁻¤×⁺Æ1Ḷḋŀ÷25¶İÇæḍ€Æ1uụC¶×12⁺ß" input='0.2, 50, "Game Over", 30' cols="50" rows="25"></div>

<script src="https://tkellehe.github.io/noodel/noodel-latest.js"></script>
<script src="https://tkellehe.github.io/noodel/ppcg.min.js"></script>


1
Ах це класна мова мати в моїй панелі інструментів ха-ха! У будь-якому разі, радий, що вам сподобався виклик :) +1
hashcode55

2

Ruby + GNU Core Utils, 169 байт

Параметри функції - це час очікування, кількість повторень, повідомлення та кількість крапель дощу в такому порядку. Нові рядки для читабельності.

Основні утиліти були потрібні для tput та clear.

->w,t,m,n{x=`tput cols`.to_i;z=x*h=`tput lines`.to_i
t.times{s=' '*z;[*0...z].sample(n).map{|i|s[i]=?/};puts`clear`+s;sleep w}
puts`clear`+$/*(h/2),' '*(x/2-m.size/2)+m}

1

Python 2.7, 254 251 байт

Це моя власна спроба без використання ncurses.

from time import*;from random import*;u=range;y=randint
def m(t,m,w,n):
    for _ in u(t):
        r=[[' 'for _ in u(40)]for _ in u(40)]
        for i in u(n):r[y(0,39)][y(0,39)]='/'
        print'\n'.join(map(lambda k:' '.join(k),r));sleep(w);print '<esc>[2J'
    print' '*33+m

Дякую @ErikTheOutgolfer за виправлення та збереження байтів.


Ви не можете поставити forцикл в одному рядку (як у вас 40)];for i in u(). Вам також потрібен знак ESC, '[2J'я думаю. Крім того, був додатковий простір у u(n): r[y. Я не знаю, як ти нарахував 249. Усі проблеми, які я знайшов, були виправлені тут .
Ерік Атголфер

Код, який я опублікував, працює для мене. І так, я насправді неправильно порахував це, я не порахував пробіл з білим відступом, про нього не знав. Дякуємо за посилання! Я відредагую.
хеш-код55

@EriktheOutgolfer О так, так, щодо цієї схеми ESC, послідовність виходу не потрібна. Він просто друкує "ESC [2J" ефективно, що є послідовністю аси для очищення екрана. Однак він не скидає положення курсору.
хеш-код55

Ви можете грати в гольф ще більше :) Але вам потрібно додати примітку під кодом із зазначенням того, що <esc>позначає буквальний байт 0x1B ESC. Кількість байтів - 242 , а не 246.
Ерік Аутгольфер

@EriktheOutgolfer О, дякую!
hashcode55

1

SmileBASIC, 114 байт

INPUT W,T,M$,N
FOR I=1TO T
VSYNC W*60CLS
FOR J=1TO N
LOCATE RND(50),RND(30)?7;
NEXT
NEXT
LOCATE 25-LEN(M$)/2,15?M$

Розмір консолі завжди 50 * 30.


1

Perl 5, 156 байт

154 байт код + 2 для -pl.

$M=$_;$W=<>;$I=<>;$R=<>;$_=$"x8e3;{eval'$-=rand 8e3;s!.{$-}\K !/!;'x$R;print;select$a,$a,$a,$W;y!/! !;--$I&&redo}$-=3920-($l=length$M)/2;s;.{$-}\K.{$l};$M

Використовує фіксований розмір 160x50.

Дивіться його в Інтернеті!


Perl 5, 203 байти

201 байт код + 2 для -pl.

$M=$_;$W=<>;$I=<>;$R=<>;$_=$"x($z=($x=`tput cols`)*($y=`tput lines`));{eval'$-=rand$z;s!.{$-}\K !/!;'x$R;print;select$a,$a,$a,$W;y!/! !;--$I&&redo}$-=$x*($y+!($y%2))/2-($l=length$M)/2;s;.{$-}\K.{$l};$M

Використовується tputдля визначення розміру терміналу.

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