Відтворіть заставку Windows ME як ASCII


19

Ця проблема випливає з цієї відповіді на Ask Ubuntu Stack Exchange.

Вступ

Пам'ятаєте заставку Windows ME з трубами ? Час повернути ностальгію назад!

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

Виклик

Ви повинні написати програму або функцію, яка виводить ASCII представлення заставки. У заставці повинна бути одна труба, яка буде рости в напів випадкових напрямках.
Початок труби буде розміщений випадковим чином на будь-якій з меж екрана, і шматок труби повинен бути перпендикулярний до бордюру (кутові першопровідні труби можуть бути горизонтальними або вертикальними). Кожна галочка труби зростатиме у напрямку, до якого вона спрямована (горизонтальна / вертикальна), 80%або випадково забирає кут 20%.

Представлення труб

Для створення труби буде використано 6 символів unicode

─    \u2500    horizontal pipe
│    \u2502    vertical pipe
┌    \u250C    upper left corner pipe
┐    \u2510    upper right corner pipe
└    \u2514    lower left corner pipe
┘    \u2518    lower right corner pipe

Вхідні дані

Програма / функція прийме 3 значення введення, які можна зібрати через параметри функції або запропонувати користувачеві.

  • Кількість кліщів
  • Ширина екрана
  • Висота екрана

Кількість кліщів

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

Наприклад, візьміть екран розміром 3х3

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

Кожного разу, коли труба виходить з екрану, як в останньому прикладі на 5 кліщів, то нова труба нерестується на випадковій межі. Наприклад:

ticks == 6
│┐ 
└┘ 
  ─

Нова труба повинна мати 50% шансів бути горизонтальною або вертикальною.

Ширина / висота екрана

Ширина та висота екрана можуть бути об'єднані в одне значення, якщо це бажано для вашої мови, що вибираєте. Ширина та висота екрана завжди матимуть мінімальне значення 1 та максимальне значення 255. Якщо ваша обрана мова підтримує консоль чи вихідний екран, розмір яких менший за сітку символів 255x255, то ви можете припустити, що ширина та висота будуть ніколи не перевищуйте межі вашої консолі. (Приклад: Windows 80x25 cmd вікно)

Вихідні дані

Вихід вашої програми / функції повинен бути надрукований на екран або повернутись з функції. Для кожного запуску вашої програми повинен бути створений різний набір труб.

Тестові справи

Наступні тестові випадки - це випадкові приклади дійсних результатів

f(4, 3, 3)
 │
─┘
  │

f(5, 3, 3)
 │
─┘┌
  │

f(6, 3, 3)
─│
─┘┌
  │

f(7, 3, 3)
──
─┘┌
  │

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

Правила

  • Це , найменший виграш байтів
  • Застосовуються стандартні лазівки
  • Якщо ви використовуєте символи труби Unicode у вихідному коді, ви можете вважати їх одним байтом

Це досить важкий виклик, який, можливо, можна вирішити багатьма творчими способами, вам рекомендується написати відповідь більш докладною мовою, навіть якщо відповіді вже є у коротких езолангах. Це створить каталог найкоротших відповідей на кожну мову. Бонусні надбавки для фантазійних кольорових gifs;)

Щасливого гольфу!

Відмова: Я знаю, що символи Unicode - це не ASCII, але за відсутності кращого імені я просто називаю це мистецтвом ASCII. Пропозиції вітаються :)


9
Символи Unicode, які ви хочете у висновку, не є ASCII.
Пшеничний майстер

2
Я думаю, що це слід ascii-artgraphical-output
помітити

13
Ностальгія та Windows ME не вписуються в одну лінію
Луїс Мендо

1
Заставка 3D Pipes передувала Windows ME.
Ніл

1
@ Джордан Я думав, що він мав на увазі кортежі.
КарлКастор

Відповіді:


9

JavaScript (ES6), 264 266 274 281

(t,w,h,r=n=>Math.random()*n|0,g=[...Array(h)].map(x=>Array(w).fill` `))=>((y=>{for(x=y;t--;d&1?y+=d-2:x+=d-1)x<w&y<h&&~x*~y?0:(d=r(4))&1?x=r(w,y=d&2?0:h-1):y=r(h,x=d?0:w-1),e=d,d=r(5)?d:2*r(2)-~d&3,g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d]})(w),g.map(x=>x.join``).join`
`)

Підрахунок символів малювання unicode як 1 байт кожен. (Як зазначено в ОП)

Менше гольфу

(t,w,h)=>{
  r=n=>Math.random()*n|0; // integer range random function
  g=[...Array(h)].map(x=>Array(w).fill(' ')); // display grid
  for (x=y=w;t--;)
    x<w & y<h && ~x*~y||( // if passed boundary
      d = r(4), // select random direction
      d & 1? (x=r(w), y=d&2?0:h-1) : (y=r(h), x=d?0:w-1) // choose start position 
    ),
    e=d, d=r(5)?d:2*r(2)-~d&3, // change direction 20% of times
    g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d], // use char based on current+prev direction
    d&1 ? y+=d-2 : x+=d-1 // change x,y position based on direction
  return g.map(x=>x.join``).join`\n`
}

Тест на анімацію

Примітка: намагаючись утримати час анімації менше 30 секунд, більше толків робить швидший темп анімації

f=(t,w,h,r=n=>Math.random()*n|0,g=[...Array(h)].map(x=>Array(w).fill` `))=>
{
  z=[]
  for(x=y=w;t--;d&1?y+=d-2:x+=d-1)
    x<w&y<h&&~x*~y?0:(d=r(4))&1?x=r(w,y=d&2?0:h-1):y=r(h,x=d?0:w-1),
    e=d,d=r(5)?d:2*r(2)-~d&3,g[y][x]="─└ ┌┐│┌  ┘─┐┘ └│"[e*4|d],
    z.push(g.map(x=>x.join``).join`\n`)
  return z
}

function go() {
  B.disabled=true
  var [t,w,h]=I.value.match(/\d+/g)
  var r=f(+t,+w,+h)
  O.style.width = w+'ch';
  var step=0
  var animate =_=>{
    S.textContent = step
    var frame= r[step++]
    if (frame) O.textContent = frame,setTimeout(animate, 30000/t);
    else   B.disabled=false
  }
  
  animate()
}

go()
#O { border: 1px solid #000 }
Input - ticks,width,height
<input value='600,70,10' id=I><button id=B onclick='go()'>GO</button>
<span id=S></span>
<pre id=O></pre>


Просто коли я думав, що QBasic може насправді виграти виклик у гольфі. ;) Майте нагороду.
DLosc

12

Ніщо не говорить про ностальгію так, як ...

QBasic, 332 байти

INPUT t,w,h
RANDOMIZE
CLS
1b=INT(RND*4)
d=b
IF b MOD 2THEN c=(b-1)/2*(w-1)+1:r=1+INT(RND*h)ELSE c=1+INT(RND*w):r=b/2*(h-1)+1
WHILE t
LOCATE r,c
m=(b+d)MOD 4
IF b=d THEN x=8.5*m ELSE x=13*m+(1<((b MOD m*3)+m)MOD 5)
?CHR$(179+x);
r=r-(d-1)MOD 2
c=c-(d-2)MOD 2
b=d
d=(4+d+INT(RND*1.25-.125))MOD 4
t=t-1
IF(r<=h)*(c<=w)*r*c=0GOTO 1
WEND

QBasic - це правильна мова для завдання, оскільки:

  • Його кодування включає символи малювання коробки - немає потреби в Unicode
  • LOCATE дозволяє друкувати в будь-якому місці на екрані, перезаписуючи те, що там було раніше
  • Microsoft ®

Особливості

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

Програма вводить три значення, розділені комами: галочки, ширина та висота. Потім він запитує насіння з випадковим числом. (Якщо така поведінка неприйнятна, змініть другий рядок на RANDOMIZE TIMER+6 байт.) Нарешті, він перетягує труби на екран.

Максимальні розміри, які можна ввести, - 80 (ширина) на 25 (висота). Якщо досягти висоти 25, це призведе до відсікання нижнього ряду, коли QBasic каже: "Натисніть будь-яку клавішу для продовження".

Як?

TL; DR: Багато математики.

Поточний рядок і стовпець є rі c; поточний напрямок є dі попередній напрямок b. Значення напрямків 0-3 вниз, вправо, вгору, вліво. Арифметика переводить їх у правильні значення кроку для rта c, а також у правильні координати ребер для початку.

Символи малювання поля - │┐└─┘┌це кодові точки 179, 191, 192, 196, 217 та 218 у QBasic. Вони здаються досить випадковими, але він все ж використовує менше символів для генерування чисел з деякою (доволі перекрученою, я не впевнений - навіть я розумію - це) математикою, ніж робити купу умовних висловлювань.

Код для зміни напрямку генерує випадкове число між -0,125 та 1,125 і займає його слово. Це дає -110% часу, 080% часу та 110% часу. Потім додаємо це до поточного значення d, мод 4. Додавання 0 зберігає поточний напрямок; додавання +/- 1 робить поворот.

Що стосується контрольного потоку, WHILE t ... WENDто основний контур; розділ перед ним, починаючи з номера рядка 1( 1b=INT(RND*4)), перезапускає трубу на випадковому краю. Всякий раз , коли rі cзнаходяться за межами вікна, ми GOTO 1.

Покажіть мені GIF!

Ось вам:

Труби!

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

INPUT t, w, h
RANDOMIZE TIMER
CLS

restart:
' Calculate an edge to start from

b = INT(RND * 4)
'0: top edge (moving down)
'1: left edge (moving right)
'2: bottom edge (moving up)
'3: right edge (moving left)
d = b

' Calculate column and row for a random point on that edge
IF b MOD 2 THEN
    c = (b - 1) / 2 * (w - 1) + 1
    r = 1 + INT(RND * h)
ELSE
    c = 1 + INT(RND * w)
    r = b / 2 * (h - 1) + 1
END IF
COLOR INT(RND * 15) + 1

WHILE t
    ' Mathemagic to generate the correct box-drawing character
    m = (b + d) MOD 4
    IF b = d THEN
        x = 17 * m / 2
    ELSE
        x = 13 * m + (1 < ((b MOD m * 3) + m) MOD 5)
    END IF
    LOCATE r, c
    PRINT CHR$(179 + x);

    ' Update row and column
    r = r - (d - 1) MOD 2
    c = c - (d - 2) MOD 2
    ' Generate new direction (10% turn one way, 10% turn the other way,
    ' 80% go straight)
    b = d
    d = (4 + d + INT(RND * 1.25 - .125)) MOD 4

    ' Pause
    z = TIMER
    WHILE TIMER < z + 0.01
        IF z > TIMER THEN z = z - 86400
    WEND

    t = t - 1
    IF r > h OR c > w OR r = 0 OR c = 0 THEN GOTO restart
WEND

Я набрав це у свій MS-DOS v6.22 VM :-)
Neil

9

Python 2.7, 624 616 569 548 552 байт

from random import*
from time import*
i=randint
z=lambda a,b:dict(zip(a,b))
c={'u':z('lur',u'┐│┌'),'d':z('ldr',u'┘│└'),'l':z('uld',u'└─┌'),'r':z('urd',u'┘─┐')}
m=z('udlr',[[0,-1],[0,1],[-1,0],[1,0]])
def f(e,t,w,h):
 seed(e);s=[w*[' ',]for _ in' '*h]
 while t>0:
  _=i(0,1);x,y=((i(0,w-1),i(0,1)*(h-1)),(i(0,1)*(w-1),i(0,h-1)))[_];o=('du'[y>0],'rl'[x>0])[_]
  while t>0:
   d=c[o].keys()[i(7,16)//8];s[y][x]=c[o][d];x+=m[d][0];y+=m[d][1];t-=1;sleep(.5);print'\n'.join([''.join(k)for k in s]);o=d
   if(x*y<0)+(x>=w)+(y>=h):break

Перший параметр - це насіння, ті ж насіння генеруватимуть однаковий вихід, друкуючи кожен крок із затримкою 500 мс.

  • -10 байт завдяки @TuukkaX

відбийте його

Приклад виконання

f(5,6,3,3)

виведе

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

багатослівна версія

import random as r
from time import *
char={
'u':{'u':'│','l':'┐','r':'┌'},
'd':{'d':'│','l':'┘','r':'└'},
'l':{'u':'└','d':'┌','l':'─'},
'r':{'u':'┘','d':'┐','r':'─'}
}
move={'u':[0,-1],'d':[0,1],'l':[-1,0],'r':[1,0]}
def f(seed,steps,w,h):
 r.seed(seed)
 screen=[[' ',]*w for _ in ' '*h]
 while steps > 0:
  if r.randint(0,1):
   x,y=r.randint(0,w-1),r.randint(0,1)*(h-1)
   origin='du'[y>0]  
  else:
   x,y=r.randint(0,1)*(w-1),r.randint(0,h-1)
   origin = 'rl'[x>0]
  while steps > 0:
   direction = char[origin].keys()[r.randint(0,2)]
   screen[y][x]=char[origin][direction]
   x+=move[direction][0]
   y+=move[direction][1]
   steps-=1
   sleep(0.5)
   print '\n'.join([''.join(k) for k in screen]),''
   if x<0 or y<0 or x>=w or y>=h:
    break
   origin=direction

1
Тут є марний пробіл if x*y<0 or. 0.5можна звести до .5. import *могло бути import*. ''.join(k) forмає марний пробіл. Ви також повинні мати можливість зберігати dictзмінну та викликати її кожного разу, коли ви її використовуєте. Не перевіряли, наскільки це економить, але, зберігаючи dict(zip(a,b))в лямбда, яка виконує роботу, для двох рядків (a, b), вона повинна рубати деякі. +1.
Yytsi

7

C (GCC / linux), 402 353 352 302 300 298 296 288 байт

#define R rand()%
x,y,w,h,r;main(c){srand(time(0));scanf(
"%d%d",&w,&h);for(printf("\e[2J");x%~w*
(y%~h)||(c=R 8,(r=R 4)&1?x=1+R w,y=r&2
?1:h:(y=1+R h,x=r&2?1:w));usleep('??'))
printf("\e[%dm\e[%d;%dH\342\224%c\e[H\n",
30+c,y,x,2*"@J_FHAF__L@HL_JA"[r*4|(r^=R 5
?0:1|R 4)]),x+=--r%2,y+=~-r++%2;}

Завдяки edc65 за збереження напрямку в одному 4-бітному номері.

Читає ширину / висоту на stdin перед тим, як назавжди зациклитись на заставці. Наприклад:

gcc -w golf.c && echo "25 25" | ./a.out

Або для заставки на весь екран:

gcc -w golf.c && resize | sed 's/[^0-9]*//g' | ./a.out

Для читабельності я додав нові рядки. Потрібна машина Linux з терміналом з дотриманням ANSI-кодів. Має кольори! Якщо ви видалите кольорову підтримку, вона коштує на 17 байт менше.

приклад


5

Рубі, 413 403 396 байт

Рубінові труби

Функція, яка приймає кількість вказівників і ширини в якості введення і повертає кінцевий екран у вигляді рядка. Не могли б сумніватися більше гольфу.

->t,w{k=[-1,0,1,0,-1]
b=(" "*w+$/)*w
f=->t,a=[[0,m=rand(w),2],[w-1,m,0],[m,0,1],[m,w-1,3]].sample{n,m,i=a
d=k[i,2]
q=->n,m,i{_,g,j=rand>0.2?[[1,0],[3,0],[0,1],[2,1]].assoc(i):"021322033132243140251350".chars.map(&:to_i).each_slice(3).select{|c,|c==i}.sample
v,u=k[j||=i,2]
y=n+v
x=m+u
[g,y,x,j]}
g,y,x,j=q[n,m,i]
b[n*w+n+m]="─│┌┐┘└"[g]
y>=0&&y<w&&x>=0&&x<w ?t>1?f[t-1,[y,x,j]]:b:f[t]}
f[t]}

Дивіться це на repl.it: https://repl.it/Db5h/4

Щоб побачити це в дії, після рядка, який починається, вставіть наступне b[n*w+n+m]=:

puts b; sleep 0.2

... потім призначте лямбду змінній, наприклад, pipes=->...і назвіть її як pipes[100,20](для 100 галочок та екрана 20x20).

Необурені та пояснення

# Anonymous function
# t - Number of ticks
# w - Screen width
->t,w{
  # The cardinal directions ([y,x] vectors)
  # Up = k[0..1], Right = k[1..2] etc.
  k = [-1, 0, 1, 0, -1]

  # An empty screen as a string
  b = (" " * w + $/) * w

  # Main tick function (recursive)
  # t - The number of ticks remaining
  # a - The current position and vector index; if not given is generated randomly
  f = ->t,a=[[0,m=rand(w),2], [w-1,m,0], [m,0,1], [m,w-1,3]].sample{
    # Current row, column, and vector index
    n, m, i = a
    d = k[i,2] # Get vector by index

    # Function to get the next move based on the previous position (n,m) and direction (d)
    q = ->n,m,i{
      # Choose the next pipe (`g` for glyph) and get the subsequent vector index (j)
      _, g, j = (
        rand > 0.2 ?
          [[1,0], [3,0], [0,1], [2,1]].assoc(i) : # 80% of the time go straight
          "021322033132243140251350".chars.map(&:to_i).each_slice(3)
            .select{|c,|c==i}.sample
      )

      # Next vector (`v` for vertical, `u` for horizontal)
      # If straight, `j` will be nil so previous index `i` is used
      v, u = k[j||=i, 2]

      # Calculate next position
      y = n + v
      x = m + u

      # Return next glyph, position and vector index
      [g, y, x, j]
    }

    # Get next glyph, and subsequent position and vector index
    g, y, x, j = q[n, m, i]

    # Draw the glyph
    b[n * w + n + m] = "─│┌┐┘└"[g]

    # Check for out-of-bounds
    y >= 0 && y < w && x >=0 && x < w ?
      # In bounds; check number of ticks remaining
      t > 1 ?
        f[t-1, [y,x,j]] : # Ticks remain; start next iteration
        b : # No more ticks; return final screen

      # Out of bounds; repeat tick with new random start position
      f[t]
  }
  f[t]
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.