Erstellen Sie den Windows ME-Bildschirmschoner als ASCII neu

19

Diese Herausforderung ist von dieser Antwort beim Ask Ubuntu Stack Exchange inspiriert .

Intro

Erinnern Sie sich an den Windows ME-Bildschirmschoner mit den Pipes ? Zeit, die Nostalgie zurückzubringen!

Bildbeschreibung hier eingeben

Herausforderung

Sie sollten ein Programm oder eine Funktion schreiben, die eine ASCII-Darstellung des Bildschirmschoners ausgibt. Im Bildschirmschoner sollte sich eine einzelne Pipe befinden, die in zufälligen Richtungen wächst.
Der Rohranfang wird zufällig an einem der Ränder des Bildschirms platziert, und das Rohrstück sollte senkrecht zum Rand stehen (die Ecken der ersten Rohre können entweder horizontal oder vertikal sein). Mit jedem Tick wächst die Pfeife in die Richtung, in die sie weist (horizontal / vertikal), 80%oder biegt bei Gelegenheit um eine Ecke 20%.

Rohrdarstellung

Zum Erstellen der Pipe werden 6 Unicode-Zeichen verwendet

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

Eingang

Das Programm / die Funktion nimmt 3 Eingabewerte an, die über Funktionsparameter erfasst oder an den Benutzer weitergeleitet werden können.

  • Anzahl der Zecken
  • Bildschirmbreite
  • Bildschirmhöhe

Anzahl der Zecken

Für jeden Tick wird ein Stück Pfeife zum Bildschirm hinzugefügt. Pipes überschreiben alte Pfeifenteile, wenn sie an derselben Position erscheinen.

Nehmen Sie zum Beispiel einen Bildschirm der Größe 3x3

ticks == 3
─┐ 
 ┘ 


ticks == 4
─┐ 
└┘ 


ticks == 5
│┐ 
└┘ 

Immer wenn eine Pipe den Bildschirm verlässt, wie im letzten Beispiel mit 5 Ticks, erscheint eine neue Pipe an einer zufälligen Grenze. Beispielsweise:

ticks == 6
│┐ 
└┘ 
  ─

Das neue Rohr sollte eine Chance von 50% haben, horizontal oder vertikal zu sein.

Bildschirmbreite / -höhe

Die Bildschirmbreite und -höhe können zu einem einzigen Wert kombiniert werden, wenn dies in der Sprache Ihrer Wahl bevorzugt wird. Die Breite und Höhe des Bildschirms hat immer einen Mindestwert von 1 und einen Höchstwert von 255. Wenn Ihre Sprache eine Konsole oder einen Ausgabebildschirm unterstützt, der kleiner als ein Zeichenraster von 255 x 255 ist, können Sie davon ausgehen, dass Breite und Höhe dies auch tun Überschreiten Sie niemals die Grenzen Ihrer Konsole. (Beispiel: Windows 80x25 cmd-Fenster)

Ausgabe

Die Ausgabe Ihres Programms / Ihrer Funktion sollte auf dem Bildschirm gedruckt oder von einer Funktion zurückgegeben werden. Für jeden Programmlauf sollte ein anderer Satz von Pipes generiert werden.

Testfälle

Die folgenden Testfälle sind alle zufällige Beispiele für gültige Ausgaben

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

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

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

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

Je mehr Zecken aufgetreten sind, desto schwieriger wird es natürlich, die Gültigkeit Ihres Programms zu beweisen. Aus diesem Grund wird es bevorzugt, ein GIF Ihrer Ausgabe zu veröffentlichen. Wenn dies nicht möglich ist, veröffentlichen Sie bitte eine Version Ihres Codes, die das Drucken der Ausgabe umfasst. Offensichtlich wird dies nicht auf Ihre Punktzahl angerechnet.

Regeln

  • Dies ist , die kürzeste Anzahl von Bytes gewinnt
  • Es gelten Standardlücken
  • Wenn Sie die Unicode-Pipe-Zeichen in Ihrem Quellcode verwenden, können Sie sie als ein einzelnes Byte zählen

Dies ist eine ziemlich schwierige Herausforderung, die möglicherweise auf viele kreative Arten gelöst werden kann. Sie werden aufgefordert, eine Antwort in einer ausführlicheren Sprache zu verfassen, obwohl es bereits Antworten in kurzen Esolangs gibt. Dadurch wird ein Katalog mit kürzesten Antworten pro Sprache erstellt. Bonus Upvotes für ausgefallene farbige Gifs;)

Viel Spaß beim Golfen!

Haftungsausschluss: Ich bin mir bewusst, dass Unicode-Zeichen kein ASCII-Zeichen sind, aber mangels eines besseren Namens nenne ich es einfach ASCII-Kunst. Vorschläge sind willkommen :)

Bassdrop Cumberwubwubwub
quelle
9
Die in der Ausgabe gewünschten Unicode-Zeichen sind nicht ASCII-Zeichen.
Weizen-Assistent
2
Ich denke, dies sollte markiert werden, ascii-artanstatt graphical-output- Referenz
AdmBorkBork
13
Nostalgie und Windows ME passen nicht gut in eine Linie
Luis Mendo
1
Der 3D Pipes-Bildschirmschoner war älter als Windows ME.
Neil
1
@Jordan Ich dachte, er meinte Tupel.
KarlKastor

Antworten:

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

Zählen der Unicode-Zeichen als jeweils 1 Byte. (Wie vom OP angegeben)

Weniger golfen

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

Animierter Test

Hinweis: Wenn Sie versuchen, die Animationszeit unter 30 Sekunden zu halten, beschleunigen mehr Stärken die Animation

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>

edc65
quelle
Gerade als ich dachte, QBasic könnte tatsächlich eine Golf Challenge gewinnen. ;) Habe ein positives Votum.
DLosc
12

Nichts sagt Nostalgie so wie ...

QBasic, 332 Bytes

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 ist die richtige Sprache für die Aufgabe, weil:

  • Die Kodierung beinhaltet Box-Zeichen - Unicode ist nicht erforderlich
  • LOCATE Mit dieser Option können Sie an eine beliebige Stelle auf dem Bildschirm drucken und die zuvor dort vorhandenen Daten überschreiben
  • Microsoft ®

Besonderheiten

Dies ist Golf QBasic, geschrieben und getestet auf QB64 mit deaktivierter Autoformatierung. Wenn Sie es in die eigentliche QBasic IDE Typ / einfügen, wird es eine Reihe von Räumen hinzufügen und erweitern ?in PRINT, aber es sollte genau gleich laufen.

Das Programm gibt drei durch Kommas getrennte Werte ein: Häkchen, Breite und Höhe. Anschließend wird nach einem Zufallszahlen-Startwert gefragt. (Wenn dieses Verhalten nicht akzeptabel ist, ändern Sie die zweite Zeile in RANDOMIZE TIMERfür +6 Bytes.) Zum Schluss werden die Pipes auf den Bildschirm gezeichnet.

Die maximalen Abmessungen, die eingegeben werden können, sind 80 (Breite) mal 25 (Höhe). Bei einer Höhe von 25 wird die untere Reihe abgeschnitten, wenn QBasic sagt "Drücken Sie eine beliebige Taste, um fortzufahren."

Wie?

TL; DR: Viel Mathe.

Die aktuelle Zeile und Spalte sind rund c; Die aktuelle Richtung ist dund die vorherige Richtung ist b. Richtungswerte 0-3 sind unten, rechts, oben, links. Arithmetik übersetzt diese in die richtigen Schrittwerte für rund csowie die richtigen Kanten-Koordinaten, mit denen begonnen werden soll.

Die Zeichen │┐└─┘┌in der Box sind die Codepunkte 179, 191, 192, 196, 217 und 218 in QBasic. Diese scheinen ziemlich zufällig zu sein, aber es wurden immer noch weniger Zeichen verwendet, um die Zahlen mit etwas (ziemlich komplizierter, ich bin nicht sicher, ob ich das überhaupt verstehe) Mathematik zu generieren, als um eine Reihe von bedingten Anweisungen auszuführen.

Der Code zum Ändern der Richtung generiert eine Zufallszahl zwischen -0,125 und 1,125 und hat das Wort. Dies ergibt -110% der Zeit, 080% der Zeit und 110% der Zeit. Wir addieren dies dann zum aktuellen Wert von d, mod 4. Das Hinzufügen von 0 behält die aktuelle Richtung bei; Addieren von +/- 1 macht eine Wende.

Was den Steuerfluss betrifft, WHILE t ... WENDist der die Hauptschleife; Der Abschnitt davor beginnt mit der Zeilennummer 1( 1b=INT(RND*4)) und startet die Pipe an einer zufälligen Kante neu. Wann immer rund csind außerhalb des Fensters, wir GOTO 1.

Zeig mir das GIF!

Bitte schön:

Rohre!

Dies wurde durch eine etwas ungolfederte Version mit Animation, Farbe und einem automatischen Zufallssamen erzeugt:

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
DLosc
quelle
Ich habe dies in meine MS-DOS v6.22 VM eingegeben :-)
Neil
9

Python 2.7, 624 616 569 548 552 Bytes

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

Der erste Parameter ist ein Startwert. Dieselben Startwerte erzeugen dieselbe Ausgabe und drucken jeden Schritt mit einer Verzögerung von 500 ms.

  • -10 Bytes dank @TuukkaX

antworte

Beispiellauf

f(5,6,3,3)

wird ausgegeben

   

 ─┐ 
   

──┐ 
   

┘─┐ 
   
┐  
┘─┐ 

ausführliche Version

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
Stange
quelle
1
Es gibt ein nutzloses Leerzeichen bei if x*y<0 or. 0.5kann auf reduziert werden .5. import *könnte sein import*. ''.join(k) forhat ein nutzloses Leerzeichen. Sie sollten auch in der Lage sein, dicteine Variable beizubehalten und sie jedes Mal aufzurufen, wenn Sie sie verwenden. Habe nicht getestet, wie viel das spart, aber durch Speichern des dict(zip(a,b))in einem Lambda, das die Arbeit für zwei Saiten erledigt (a, b), sollte es einige hacken. +1.
Yytsi
7

C (GCC / Linux), 402 353 352 302 300 298 296 288 Bytes

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

Gutschrift an edc65 für das Speichern der Richtung in einer einzelnen 4-Bit-Zahl.

Liest eine Breite / Höhe auf stdin, bevor der Bildschirmschoner für immer geloopt wird. Z.B:

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

Oder für einen Vollbild-Bildschirmschoner:

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

Zur besseren Lesbarkeit habe ich Zeilenumbrüche hinzugefügt. Erfordert einen Linux-Computer mit einem Terminal, das ANSI-Codes berücksichtigt. Hat farben! Wenn Sie die Farbunterstützung entfernen, fallen 17 Byte weniger an.

Beispiel

orlp
quelle
5

Ruby, 413 403 396 Bytes

Rubinrote Pfeifen

Eine Funktion, die eine Anzahl von Ticks und eine Breite als Eingabe annimmt und den endgültigen Bildschirm als Zeichenfolge zurückgibt. Könnte ohne Zweifel mehr golfen werden.

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

Siehe es auf repl.it: https://repl.it/Db5h/4

Fügen Sie nach der Zeile, die beginnt, Folgendes ein, um sie in Aktion zu sehen b[n*w+n+m]=:

puts b; sleep 0.2

... ordnen Sie dann das Lambda zB einer Variablen zu pipes=->...und nennen Sie es wie pipes[100,20](für 100 Ticks und einen 20x20 Bildschirm).

Ungolfed & Erklärung

# 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]
}
Jordan
quelle