В моем терминале идет дождь!


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
Если вы, А. Укажите единицы. Б. Укажите размер терминала или примите его в качестве ввода. и 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 байт

Просто фиктивная версия, которую я написал на основе описания. Надеюсь, это то, что искала OP.

Сохранено несколько байтов благодаря @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-studio 23x100 символов. Размеры жестко закодированы в функцию, но в принципе ее можно использовать, 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 и я не думаю, что это идет вверх, это просто ваше восприятие lol
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 байт

редактировать

По запросу, дополнительные функции удалены и Golf'd.

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)

Смотрите webm это работает здесь


2

Noodel , неконкурентный 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 байт

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

Core Utils были необходимы для 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, хотя. Все найденные мной проблемы были исправлены здесь .
Эрик Outgolfer

Код, который я разместил, работает на меня. И да, я действительно посчитал это неправильно, я не сосчитал пространство с белым отступом, я не знал об этом. Спасибо за ссылку! Я отредактирую это.
hashcode55

@EriktheOutgolfer Да и в отношении этого символа ESC, последовательность перехода не требуется. Он просто печатает 'ESC [2J' 'эффективно, что является escape-последовательностью для очистки экрана. Это не сбрасывает позицию курсора, хотя.
hashcode55

Вы можете играть в гольф еще больше :) Но вам нужно добавить примечание под вашим кодом, указывающее, что <esc>обозначает буквальный байт ESC 0x1B. Число байт 242 , а не 246.
Эрик Outgolfer

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