Tái tạo trình bảo vệ màn hình Windows ME dưới dạng ASCII


19

Thử thách này được lấy cảm hứng từ câu trả lời này tại Ask Ubuntu Stack Exchange.

Giới thiệu

Ghi nhớ trình bảo vệ màn hình Windows ME với các đường ống ? Thời gian để mang nỗi nhớ trở lại!

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

Thử thách

Bạn nên viết một chương trình hoặc chức năng sẽ tạo ra một đại diện ASCII của trình bảo vệ màn hình. Trong trình bảo vệ màn hình nên có một đường ống duy nhất sẽ phát triển theo hướng bán ngẫu nhiên.
Điểm bắt đầu của đường ống sẽ được đặt ngẫu nhiên tại bất kỳ đường viền nào của màn hình và đoạn ống phải vuông góc với đường viền (góc đầu tiên - đường ống có thể là ngang hoặc dọc). Mỗi đánh dấu đường ống sẽ phát triển theo hướng nó đang đối mặt (ngang / dọc) một cách 80%tình cờ hoặc có một góc ở một 20%cơ hội.

Đại diện ống

Để tạo đường ống, 6 ký tự unicode sẽ được sử dụng

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

Đầu vào

Chương trình / chức năng sẽ lấy 3 giá trị đầu vào, có thể được tập hợp thông qua các tham số chức năng hoặc được nhắc cho người dùng.

  • Số lượng bọ ve
  • Độ rộng màn hình
  • Chiều cao màn hình

Số lượng bọ ve

Đối với mỗi đánh dấu, một đoạn ống sẽ được thêm vào màn hình. Ống sẽ ghi đè lên các mảnh ống cũ nếu chúng sinh ra ở cùng một vị trí.

Ví dụ: chụp màn hình kích thước 3x3

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

Bất cứ khi nào một đường ống thoát khỏi màn hình, như trong ví dụ cuối cùng ở mức 5 tick, thì một đường ống mới sẽ sinh ra ở một đường viền ngẫu nhiên. Ví dụ:

ticks == 6
│┐ 
└┘ 
  ─

Các đường ống mới nên có 50% cơ hội là ngang hoặc dọc.

Chiều rộng / chiều cao màn hình

Chiều rộng và chiều cao màn hình có thể được kết hợp thành một giá trị nếu điều đó phù hợp với ngôn ngữ bạn chọn. Chiều rộng và chiều cao màn hình sẽ luôn có giá trị tối thiểu là 1 và giá trị tối đa là 255. Nếu ngôn ngữ bạn chọn hỗ trợ màn hình điều khiển hoặc màn hình đầu ra nhỏ hơn lưới 255x255 thì bạn có thể cho rằng chiều rộng và chiều cao sẽ không bao giờ vượt quá ranh giới của giao diện điều khiển của bạn. (Ví dụ: cửa sổ Windows 80x25 cmd)

Đầu ra

Đầu ra của chương trình / chức năng của bạn phải được in ra màn hình hoặc được trả về từ một chức năng. Đối với mỗi lần chạy chương trình của bạn, một bộ ống khác nhau sẽ được tạo.

Các trường hợp thử nghiệm

Các trường hợp kiểm tra sau đây là tất cả các ví dụ ngẫu nhiên về đầu ra hợp lệ

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

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

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

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

Rõ ràng, càng nhiều dấu vết đã xảy ra, càng khó chứng minh tính hợp lệ của chương trình của bạn. Do đó, đăng một gif của đầu ra của bạn đang chạy sẽ được ưu tiên. Nếu điều này là không thể, xin vui lòng gửi một phiên bản mã của bạn bao gồm in đầu ra. Rõ ràng, điều này sẽ không được tính vào điểm số của bạn.

Quy tắc

  • Đây là , số lượng byte chiến thắng ngắn nhất
  • Áp dụng sơ hở tiêu chuẩn
  • Nếu bạn sử dụng các ký tự ống unicode trong mã nguồn của mình, bạn có thể tính chúng là một byte đơn

Đây là một thử thách khá khó có thể giải quyết bằng nhiều cách sáng tạo, bạn được khuyến khích viết câu trả lời bằng ngôn ngữ dài dòng hơn mặc dù đã có câu trả lời bằng esolang ngắn. Điều này sẽ tạo ra một danh mục các câu trả lời ngắn nhất cho mỗi ngôn ngữ. Thưởng upvote cho gifs màu ưa thích;)

Chúc bạn chơi golf vui vẻ!

Tuyên bố miễn trừ trách nhiệm: Tôi biết rằng các ký tự Unicode không phải là ASCII, nhưng vì không có tên hay hơn nên tôi chỉ gọi nó là nghệ thuật ASCII. Đề xuất được chào đón :)


9
Các ký tự unicode mà bạn muốn trong đầu ra không phải là ASCII.
Thuật sĩ lúa mì

2
Tôi nghĩ rằng điều này nên được gắn thẻ ascii-artthay vì graphical-output- tham khảo
admBorkBork

13
Nỗi nhớWindows ME không phù hợp trên cùng một dòng
Luis Mendo

1
Trình bảo vệ màn hình 3D Faucet có trước Windows ME.
Neil

1
@Jordan Tôi nghĩ anh ấy có nghĩa là tuples.
KarlKastor

Câu trả lời:


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

Đếm các ký tự vẽ unicode là 1 byte mỗi ký tự. (Theo quy định của OP)

Ít chơi gôn

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

Kiểm tra hoạt hình

Lưu ý: cố gắng giữ thời gian hoạt hình dưới 30 giây, nhiều cú đánh giúp tốc độ hoạt hình nhanh hơn

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>


Ngay khi tôi nghĩ QBasic thực sự có thể chiến thắng một thử thách golf. ;) Có một upvote.
DLosc

12

Không có gì nói nỗi nhớ khá giống ...

QBasic, 332 byte

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 là ngôn ngữ phù hợp cho nhiệm vụ vì:

  • Mã hóa của nó bao gồm các ký tự vẽ hộp - không cần Unicode
  • LOCATE cho phép bạn in ra bất kỳ vị trí nào trên màn hình, ghi đè lên những gì trước đó
  • Microsoft ®

Cụ thể

Đây là QBasic được đánh gôn, được viết và thử nghiệm trên QB64 với chế độ tự động tắt đã tắt. Nếu bạn nhập / dán nó vào IDE QBasic thực tế, nó sẽ thêm một loạt các khoảng trắng và mở rộng ?thànhPRINT , nhưng nó sẽ chạy chính xác như vậy.

Chương trình nhập ba giá trị được phân tách bằng dấu phẩy: dấu, chiều rộng và chiều cao. Sau đó, nó yêu cầu một hạt giống số ngẫu nhiên. (Nếu hành vi này không được chấp nhận, hãy thay đổi dòng thứ hai thànhRANDOMIZE TIMER +6 byte.) Cuối cùng, nó sẽ vẽ các đường ống lên màn hình.

Kích thước tối đa có thể được nhập là 80 (chiều rộng) bằng 25 (chiều cao). Đưa ra chiều cao 25 ​​sẽ dẫn đến hàng dưới cùng bị cắt khi QBasic nói "Nhấn phím bất kỳ để tiếp tục."

Làm sao?

TL; DR: Rất nhiều toán học.

Hàng và cột hiện tại là rc; hướng hiện tại là dvà hướng trước là b. Giá trị hướng 0-3 là xuống, phải, lên, trái. Số học chuyển chúng thành các giá trị bước chính xác cho rc , cũng như tọa độ cạnh chính xác để bắt đầu.

Hộp vẽ nhân vật │┐└─┘┌ là các điểm mã 179, 191, 192, 196, 217 và 218 trong QBasic. Chúng xuất hiện khá ngẫu nhiên, nhưng nó vẫn sử dụng ít ký tự hơn để tạo ra các số với một số phép toán (khá phức tạp, tôi không chắc chắn thậm chí tôi hiểu nó) hơn là thực hiện một loạt các câu lệnh có điều kiện.

Mã để thay đổi hướng tạo ra một số ngẫu nhiên trong khoảng -0.125 đến 1.125 và lấy sàn của nó. Điều này mang lại -110% thời gian, 080% thời gian và 110% thời gian. Sau đó chúng ta thêm giá trị này vào giá trị hiện tại của d, mod 4. Thêm 0 giữ hướng hiện tại; thêm +/- 1 lần lượt.

Đối với luồng điều khiển, WHILE t ... WENDvòng lặp chính là; phần trước nó, bắt đầu bằng số dòng 1( 1b=INT(RND*4)), khởi động lại đường ống ở một cạnh ngẫu nhiên. Bất cứ khi nào rcở ngoài cửa sổ, chúng tôi GOTO 1.

Cho tôi xem ảnh GIF!

Ở đây bạn đi:

Ống!

Điều này được tạo ra bởi một phiên bản hơi vô căn cứ với hình ảnh động, màu sắc và một hạt giống ngẫu nhiên tự động:

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

Tôi đã nhập cái này vào MS-DOS v6.22 VM của tôi :-)
Neil

9

Python 2.7, 624 616 569 548 552 byte

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

Tham số đầu tiên là một hạt giống, cùng các hạt giống sẽ tạo ra cùng một đầu ra, in mỗi bước với độ trễ 500 ms.

  • -10 byte nhờ @TuukkaX

thay thế nó

Chạy ví dụ

f(5,6,3,3)

sẽ xuất

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

phiên bản dài dòng

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
Có một khoảng trắng vô dụng tại if x*y<0 or. 0.5có thể được giảm xuống .5. import *có thể import*. ''.join(k) forcó một khoảng trắng vô dụng. Bạn cũng có thể giữ dictmột biến và gọi nó mỗi khi bạn sử dụng nó. Chưa kiểm tra xem cái này tiết kiệm được bao nhiêu, nhưng bằng cách tiết kiệm dict(zip(a,b))trong lambda thực hiện công việc cho hai chuỗi (a, b), nó sẽ cắt một số. +1.
Yytsi

7

C (GCC / linux), 402 353 352 302 300 298 296 288 byte

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

Tín dụng cho edc65 để lưu trữ hướng trong một số 4 bit duy nhất.

Đọc chiều rộng / chiều cao trên stdin trước khi lặp trình bảo vệ màn hình mãi mãi. Ví dụ:

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

Hoặc đối với trình bảo vệ màn hình toàn màn hình:

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

Để dễ đọc tôi đã thêm các dòng mới. Yêu cầu một máy linux có thiết bị đầu cuối tôn trọng mã ANSI. Có màu sắc! Nếu bạn loại bỏ hỗ trợ màu, chi phí ít hơn 17 byte.

thí dụ


5

Ruby, 413 403 396 byte

Ruby ống

Một hàm lấy một số đánh dấu và chiều rộng làm đầu vào và trả về màn hình cuối cùng dưới dạng một chuỗi. Không thể nghi ngờ được chơi golf nhiều hơn.

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

Xem nó trên repl.it: https://repl.it/Db5h/4

Để xem nó hoạt động, chèn đoạn sau vào sau dòng bắt đầu b[n*w+n+m]=:

puts b; sleep 0.2

... sau đó gán lambda cho một biến, ví dụ pipes=->... và gọi nó nhưpipes[100,20] (cho 100 tick và màn hình 20x20).

Ung dung & giải thích

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