สร้างสกรีนเซฟเวอร์ Windows ME ใหม่เป็น ASCII


19

ความท้าทายนี้ได้รับแรงบันดาลใจจากคำตอบนี้ที่ Ask Ubuntu Stack Exchange

Intro

จำหน้าจอ Windows ME ด้วยไพพ์หรือไม่? ถึงเวลานำความคิดถึงกลับมาแล้ว!

ป้อนคำอธิบายรูปภาพที่นี่

ท้าทาย

คุณควรเขียนโปรแกรมหรือฟังก์ชั่นที่จะแสดงผลเป็นตัวแทน ASCII ของสกรีนเซฟเวอร์ ในสกรีนเซฟเวอร์ควรมีท่อเดียวซึ่งจะเติบโตในทิศทางกึ่งสุ่ม
จุดเริ่มต้นของท่อจะถูกวางแบบสุ่มที่ขอบใด ๆ ของหน้าจอและชิ้นส่วนท่อควรตั้งฉากกับเส้นขอบ (มุมแรก - ท่อสามารถเป็นแนวนอนหรือแนวตั้ง) แต่ละเห็บท่อจะเติบโตในทิศทางที่หันหน้าไปทาง (แนวนอน / แนวตั้ง) ที่80%บังเอิญหรือมีมุมที่มี20%โอกาส

ตัวแทนท่อ

ในการสร้างไปป์จะใช้อักขระ Unicode 6 ตัว

─    \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 ค่าซึ่งสามารถรวบรวมผ่านพารามิเตอร์ฟังก์ชันหรือแจ้งให้ผู้ใช้ทราบ

  • จำนวนเห็บ
  • ความกว้างของหน้าจอ
  • ความสูงของหน้าจอ

จำนวนเห็บ

สำหรับทุกเห็บจะมีการเพิ่มชิ้นส่วนของท่อไปยังหน้าจอ ท่อจะเขียนทับชิ้นส่วนท่อเก่าถ้าวางไข่ในตำแหน่งเดียวกัน

ตัวอย่างเช่นใช้หน้าจอขนาด 3x3

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 ของผลงานของคุณจะเป็นที่ต้องการ หากเป็นไปไม่ได้โปรดโพสต์รหัสของคุณซึ่งรวมถึงการพิมพ์ผลลัพธ์ เห็นได้ชัดว่าสิ่งนี้จะไม่นับรวมคะแนนของคุณ

กฎระเบียบ

  • นี่คือจำนวนไบต์ที่สั้นที่สุดชนะ
  • ช่องโหว่มาตรฐานใช้
  • หากคุณใช้อักขระไพพ์ยูนิโคดในซอร์สโค้ดของคุณคุณอาจนับเป็นไบต์เดียว

นี่เป็นความท้าทายที่ยากมากที่สามารถแก้ไขได้ด้วยวิธีการสร้างสรรค์มากมายคุณควรเขียนคำตอบด้วยภาษา verbose มากขึ้นแม้ว่าจะมีคำตอบใน esolang สั้น ๆ อยู่แล้ว สิ่งนี้จะสร้างแคตตาล็อกของคำตอบที่สั้นที่สุดต่อภาษา โบนัสอัปโหลดสำหรับ gif สีแฟนซี;)

มีความสุขในการเล่นกอล์ฟ!

ข้อจำกัดความรับผิดชอบ: ฉันรู้ว่าตัวอักษร Unicode ไม่ใช่ ASCII แต่ในกรณีที่ไม่มีชื่อที่ดีกว่าฉันเพิ่งเรียกมันว่า ASCII art ข้อเสนอแนะยินดีต้อนรับ :)


9
อักขระ Unicode ที่คุณต้องการในเอาต์พุตไม่ใช่ ASCII
ข้าวสาลีตัวช่วยสร้าง

2
ฉันคิดว่าควรติดแท็กascii-artแทนgraphical-output- อ้างอิง
AdmBorkBork

13
NostalgiaและWindows MEไม่ค่อยเข้ากันในบรรทัดเดียวกัน
Luis Mendo

1
สกรีนเซฟเวอร์ 3D Pipes ติดตั้ง Windows ME ไว้ล่วงหน้า
Neil

1
@ จอร์แดนฉันคิดว่าเขาหมายถึงสิ่งอันดับ
KarlKastor

คำตอบ:


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 ไบต์แต่ละตัว (ตามที่ระบุโดย OP)

น้อย golfed

(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 อาจชนะการแข่งขันกอล์ฟ ;) มี upvote
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แต่ควรจะทำงานเหมือนกันทุกประการ

โปรแกรมป้อนค่าที่คั่นด้วยเครื่องหมายจุลภาคสามค่า: ticks, width และ height จากนั้นจะขอให้มีการสุ่มหมายเลข (หากพฤติกรรมนี้ไม่เป็นที่ยอมรับเปลี่ยนบรรทัดที่สองเป็น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 และใช้พื้นที่ของมัน สิ่งนี้ให้-1เวลา 10% ของเวลา080% ของเวลาและ110% ของเวลา จากนั้นเราจะเพิ่มสิ่งนี้เป็นค่าปัจจุบันของd, mod 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 ms

  • -10 ไบต์ขอบคุณ @TuukkaX

ทำซ้ำ

ตัวอย่างการวิ่ง

f(5,6,3,3)

จะส่งออก

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

รุ่น verbose

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 * มีช่องว่างที่ไร้ประโยชน์ คุณควรจะสามารถเก็บไว้ในตัวแปรและเรียกมันทุกครั้งที่คุณใช้มัน ยังไม่ได้ทดสอบว่าจะประหยัดได้มากเพียงใด แต่ด้วยการบันทึกแลมบ์ดาที่ทำงานให้กับสองสาย (a, b) ก็ควรสับบางส่วน +1 import*''.join(k) fordictdict(zip(a,b))
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

Ruby, 413 403 396 ไบต์

ท่อทับทิม

ฟังก์ชันที่รับจำนวนของ ticks และความกว้างเป็นอินพุตและส่งคืนหน้าจอสุดท้ายเป็นสตริง ไม่ต้องสงสัยเลยว่าจะเล่นกอล์ฟได้มากขึ้น

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

Ungolfed & คำอธิบาย

# 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]
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.