ASCII Ball in Box Animation


11

Schreiben Sie ein Programm, das eine sich bewegende ASCII-Kugel *in einem Rechteck anzeigt (20 x 10 Zeichen einschließlich Rand). Der Ball darf das Rechteck nicht überqueren, z. B. beim Auftreffen auf die Wand abprallen. Die Szene muss alle 0,1 Sekunden gelöscht und neu gezeichnet werden, und der Ball muss in jedem Bild 1 Zeichen in x- und y-Richtung bewegen. Das kürzeste Programm, das in einer Sprache geschrieben wurde, gewinnt.

Beispielausgabe (Bild 1)

+------------------+
|*                 |
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
+------------------+

Beispielausgabe (Bild 2)

+------------------+
|                  |
| *                |
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
+------------------+

Beispielausgabe (Bild 8)

+------------------+
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
|       *          |
+------------------+

Beispielausgabe (Bild 9)

+------------------+
|                  |
|                  |
|                  |
|                  |
|                  |
|                  |
|        *         |
|                  |
+------------------+

4
Qualifiziert das Drucken von 99 Zeilenumbrüchen das Löschen des Bildschirms?
Ventero

Nicht auf meinem Monitor mit 1080x1920Auflösung :)
Mellamokb

Antworten:


7

Ruby 1.9, 115 Zeichen

Die Bewegung Logik ist ganz ähnlich wie Danko ‚s Antwort .

Diese Version wurde nur unter Linux getestet.

p=0
loop{u=(?|+?\s*18+"|
")*8
u[165-21*(7-p%14).abs-(17-p%34).abs]=?*
p+=1
puts"\e[2J",r=?++?-*18+?+,u,r
sleep 0.1}

Mit Ruby 1.9.3 unter Windows 7 wird puts"\e[2J"nur ←[2J(und eine neue Zeile) auf dem Bildschirm gedruckt.
Res

@res In meiner Bearbeitung finden Sie eine Version, die unter Windows ausgeführt werden soll (ich kann sie leider nicht selbst testen).
Ventero

Verwenden clsfunktioniert bei mir nicht, funktioniert aber system ("cls").
Res

@res benutze `cls`. Wörtliche Backticks.
Mark Reed

@ MarkReed - Das habe ich versucht zu schreiben. Wie auch immer, es funktioniert nicht. Windows scheint ein System ("cls") zu benötigen.
Res

4

Powershell, 144 Zeichen

Basierend auf Joeys hervorragender Antwort unter Verwendung der Tatsache, dass die Ballkoordinaten eine Funktion des Rahmenindex (i) sind. Wenn Sie also so etwas haben x=n-abs(n-(i mod (2*n))), geht x von 0 auf n, zurück auf 0 und so weiter ...

for(){cls
($l="+$('-'*18)+")
7..0|%{$j=$_
"|$(-join(17..0|%{'* '[$j-[Math]::abs(7-$i%14)-or$_-[Math]::abs(17-$i%34)]}))|"}
$l;$i++;sleep -m 100}

Schön. Obwohl ich ein bisschen stolz auf meine war, if(-1,18-eq$x){$a*=-1;$x+=2*$a}if(-1,8-eq$y){$b*=-1;$y+=2*$b}die vier ifs früher ersetzt hat ;-). Ich war mir jedoch sicher, dass es eine Formel geben musste.
Joey

3

Python 2, 234

Ich bin mir sicher, dass dies mehr Golf gespielt werden kann, aber ich muss gehen, also hier ist, was ich bisher habe. werde später mehr daran arbeiten

import os,time
a,b,c,d,e,n='+- |*\n'
w=d+c*18+d+n
s=a+b*18+a+n
x,y=0,0
g,h=17,7
j,k=1,1
while 1:
 if 0>x or x>g:j*=-1;x+=j
 if 0>y or y>h:k*=-1;y+=k
 os.system('cls');print s+w*y+d+c*x+e+c*(g-x)+d+n+w*(h-y)+s;x+=j;y+=k;time.sleep(0.1)

Hinweis: Funktioniert auf der Windows-Befehlskonsole. Andere Betriebssysteme verwenden möglicherweise einen anderen Befehl als clszum Löschen des Bildschirms, zclear


funktioniert print "\e[H\e[2J"unter Windows?
Patrick Oscity

@padde - Es scheint nicht zu funktionieren, wenn ich Ihr Ruby-Programm unter Windows 7 ausführe (siehe meinen Kommentar zu Ihrem Beitrag).
Res

3

Ruby ( 179 174 147)

EDIT hat einige weitere Zeichen entfernt:

l=?++?-*18+?++?\n
c=?|+?\s*18+?|+?\n
p=22
u=v=1
loop{f=l+c*8+l
f[p]=?*
puts"\e[2J"+f
p+=(u=f[p+u]==' '?u:-u)+21*(v=f[p+21*v]==' '?v:-v)
sleep 0.1}

EDIT rasierte einige Zeichen ab, jetzt 174:

l="+#{'-'*18}+\n";f=l+"|#{' '*18}|\n"*8+l;x=y=u=v=1
loop{f[21*y+x]='*';$><<"\e[2J\e[f"+f;f[21*y+x]=' '
u=f[21*y+x+u]==' '?u:-u;v=f[21*(y+v)+x]==' '?v:-v
x+=u;y+=v;sleep 0.1}

Ungolfed:

l="+#{'-'*18}+\n"           # top and bottom lines 
f=l+"|#{' '*18}|\n"*8+l     # complete box as string
x=y=u=v=1                   # x,y position; u,v next move
loop {                      #
  f[21*y+x]='*'             # add ball to box
  $> << "\e[2J\e[f"+f       # clear screen and print box with ball
  f[21*y+x]=' '             # remove ball from box
  u=f[21*y+x+u]==' '?u:-u   # next move in x direction
  v=f[21*(y+v)+x]==' '?v:-v # next move in y direction
  x+=u                      # perform move
  y+=v                      # --"--
  sleep 0.1                 # .zZZ...
}                           #

Sollte nicht auch sleep .1funktionieren?
Joey

Nein, nicht in 1.9. SyntaxError: (irb):1: no .<digit> floating literal anymore; put 0 before dot. Aber ich werde darauf zurückkommen, wenn ich es in Zukunft brauche, danke!
Patrick Oscity

Wenn Sie auf 1.9 sind, können Sie char-Literale verwenden, um einige Dinge zu verkürzen, z. B. ?*anstelle von '*'usw.
Joey

Mit Ruby 1.9.3 unter Win7 werden Rechtecke nacheinander (unter) gedruckt, die jeweils ←[2J←[f+------------------+die erste Zeile enthalten.
Res

dann wechseln Sie $> << "\e[2J\e[f"+fzu 'cls';$><<f(verwenden Sie Backticks für cls)
Patrick Oscity

2

JavaScript (275 283 )

s=Array(19).join(' ');n='\n';z=Array(9).join('|'+s+'|'+n).split(n,8);
x=y=0;a=b=1;t='+'+s.replace(/ /g,'-')+'+';
setInterval(function(){u=z[y];z[y]=u.replace(eval('/( {'+x+'}) /'),'$1*');
$('#o').text(t+n+z.join('\n')+n+t);z[y]=u;x+=a;y+=b;if(!x|x==17)a=-a;if(!y|y==7)b=-b},100)

Demo: http://jsfiddle.net/eKcfu/2/

Ich habe das ziemlich schnell geschrieben, daher bin ich mir sicher, dass es noch viel Raum für Verbesserungen gibt. Vorschläge sind willkommen :)

Bearbeiten 1 : Unnötigen separaten Funktionsaufruf entfernen, direkt einbetten setInterval.


2

Haskell, 212 Zeichen

import System
main=mapM_ f$s 19`zip`s 9
s n=[2..n]++[n-1,n-2..3]++s n
f p=r"clear">>putStr(unlines[[" |-+*"!!(19#i+2*(9#j)+4*e((i,j)==p))|i<-[1..20]]|j<-[1..10]])>>r"sleep 0.1"
b#n=e$n<2||n>b
e=fromEnum
r=system

Verwendet einen funktionaleren Ansatz zur Berechnung der Koordinaten, indem die unendliche Sequenz für jede Koordinate separat erstellt und dann zusammen gezippt wird (Zeilen 2 und 3). Der Rest ist Zeichnungscode.


2

PowerShell, 184 185 215

Nur halb Golf, da mein Gehirn nicht richtig funktioniert, wenn ich krank bin ...

Ein paar nette Tricks.

for($a=$b=1){cls
($l="+$('-'*18)+")
0..7|%{$j=$_
"|$(-join(0..17|%{'* '[$j-$y-or$_-$x]}))|"}
$l
$x+=$a;$y+=$b
if(-1,18-eq$x){$a*=-1;$x+=2*$a}if(-1,8-eq$y){$b*=-1;$y+=2*$b}sleep -m 100}

[Bearbeiten]: Das Schleifen über das Feld ist viel kürzer.


2

QBasic (QB64), 178 173 Bytes

a$="+------------------+
?a$
for c=1to 8
?"|                  |
next
?a$
do
x=19-abs(17-(i mod 34))
y=9-abs(7-(i mod 14))
locate y,x
?"*
_delay .1
locate y,x
?" "
i=i+1
loop

-5 Bytes dank DLosc


Nett! Für die Endlosschleife können Sie DO ... LOOPanstelle von WHILE 1 ... WEND5 Bytes verwenden und diese speichern.
DLosc

1

Perl 5, 141 Zeichen

print"\e[H\e[2J",$h="+"."-"x18 ."+
",(map{"|".$"x$q,(abs$t%14-7)-$_?$":"*",$"x(17-$q),"|
"}0..7),$h,select'','','',0.1while$q=abs$t++%34-17,1

Beginnt nicht in der oberen linken Ecke wie die Beispielausgabe, dies wird jedoch nicht als Voraussetzung angegeben.


1

Ruby 1.9, 162 Zeichen

35 Zeichen scheuen @ Venteros Antwort, aber ich war beeindruckt, dass ich es so weit schaffen konnte, während ich immer noch einen relativ einfachen Ansatz für die eigentliche Logik verwendete. Das ^ [ist ein wörtlicher ESC (1 Zeichen).

x=y=0
v=h=1
s=' '
loop{puts"^[[2J"+b="+#{?-*18}+",*(0..7).map{|i|"|#{i!=y ?s*18:s*x+?*+s*(17-x)}|"},b
y+=v
y+=v*=-1if y<0||y>7
x+=h
x+=h*=-1if x<0||x>17
sleep 0.1}

1

R, 233 Zeichen

s=c("\n+",rep("-",18),"+");for (j in 1:8){cat(s,sep="");cat(rep(c("\n|",rep("",17),"|"),j-1));cat(c("\n|",rep(" ",j-1),"*",rep(" ",18-j),"|"),sep="");cat(rep(c("\n|",rep("",17),"|"),8-j));cat(s,sep="");Sys.sleep(0.1);system("clear")}

1

Ein weiterer Bash-Eintrag - 213 204 Zeichen

Nicht wirklich ein Preisträger, aber es hat trotzdem Spaß gemacht. Für die Zeichnung werden vt100-Zeichenfolgen verwendet. (Der hier angegebene Code verwendet 215 Zeichen zur besseren Lesbarkeit. 2 Zeichen können durch Escapezeichen entfernt werden, z. B. '*' -> \ *

e(){ printf "\e[$1";}
e 2J;e H
h='+------------------+'
echo $h
for((;++j<9;));do printf '|%18s|\n';done
echo $h
e '3;2H*'
while :;do
e 'D '
((i/17%2))&&e D||e C
((++i/7%2))&&e A||e B
e 'D*'
sleep .1
done

1

Powershell, 139 Bytes

Inspiriert von Danko Durbićs Antwort .

for(){cls
,"+$('-'*18)+
"*2-join("|$(' '*18)|
"*8-replace"^(\W{$(21*[Math]::abs(7-$i%14)+[Math]::abs(17-$i++%34))}.) ",'$1*')
sleep -m 100}

Dieses Skript verwendet den -replaceOperator, um *innerhalb des Rechtecks zu zeichnen .

Weniger Golfskript, um zu erklären, wie es funktioniert:

for(){
    cls
    $y=[Math]::abs(7-$i%14)
    $x=[Math]::abs(17-$i++%34)
    $b="+$('-'*18)+`n"
    $m="|$(' '*18)|`n"*8-replace"^(\W{$(21*$y+$x)}.) ",'$1*'
    ,$b*2-join($m)          # draw it
    sleep -m 100
}

0

Bash 278 300, 296

h="+------------------+"
w="|                  |"
g(){
echo -e "\e[$2;$1H$3"
}
g 1 1 $h
for i in {1..8}
do
echo "$w"
done
echo $h
x=4
y=4
p=1
q=1
for((;;))
do
((x==19&&p==1||x==2&&p==-1))&&p=-$p
((y==9&&q==1||y==2&&q==-1))&&q=-$q
x=$((x+p))
y=$((y+q))
g $x $y \*
sleep .1
g $x $y " "
done

Das \ e in der Zeile echo -e "\e[$2;$1H$3"kann von erzeugt werden

echo -e "\x1b"

um es zu ersetzen. Als binäres 0x1b ist es 3 Zeichen kürzer; Ich zähle nur 1 für "\ e", weil mich nur die Layout-Software zur Verwendung zwingt \e.


Eine anonyme Benutzer vorgeschlagen Änderungen , die entfernen $Symbole innen ((...))und ersetzen x=$(($x+$p))mit ((x+=p))und in ähnlicher Weise in der folgenden Zeile. (Sie schlugen auch vor, \efür das Escape-Zeichen zu verwenden).
Peter Taylor

Ich würde zusätzlich vorschlagen, dass dies \*als Ersatz für funktionieren könnte "*".
Peter Taylor

@ PeterTaylor: Danke an den anonymen Benutzer. Ich habe Vorschlag Nr. 1 aufgenommen und Nr. 2 in modifizierter Form und Ihren verwendet.
Benutzer unbekannt

@userunknown: Ihr Repräsentant 1,337muss dauerhaft an Ort und Stelle gesperrt sein: P
mellamokb

1
@ Mellamokb: Es ist weg.
Benutzer unbekannt

0

TI Basic, 169 167 Bytes

1→X
1→Y
1→S
1→T
While 1
ClrHome
Output(Y,X,"*
S(X>1 and X<20)+(X=1)-(X=20→S
T(Y>1 and Y<10)+(Y=1)-(Y=10→T
X+S→X
Y+T→Y
For(N,1,20,19
For(O,1,10,9
Output(O,N,"+
End
End
For(N,2,19
For(O,1,10,9
Output(O,N,"-
End
End
For(O,2,9
Output(O,1,"|
Output(O,20,"|
End
End

Schrecklich langsam, aber es funktioniert.


(X=20)→Skann sein (X=20→S, und Sie können Ans nutzen, um ein paar Bytes in der letzten For (Schleife zu speichern. Ich bin sicher, dass die Zeilen 8 und 9 gespielt werden können, aber ich bin mir nicht sicher, wie im Moment.
MI Wright

@MIWright Wo würde ich die Ans platzieren?
Phase

"| \ Output(O,1,Ans \ Output(O,20,Anssollte arbeiten.
MI Wright

@MIWright Aber ersetzt das nicht eine zweistellige Zeichenfolge durch eine dreistellige Zeichenfolge? Und die zwei Zeichenfolgen darüber hinzufügen, so dass es +4 ist?
Phase

Was meinen Sie? Ansist ein Ein-Byte-Token , mit dem getippt wird 2nd (-). Dadurch wird ein Byte eingespart, da das |Token zwei Bytes im Taschenrechner enthält.
MI Wright

0

PHP, 196 186 148 Bytes

Ich habe entfernt, um einen Ganzzahlüberlauf zu vermeiden, um 6 Bytes zu sparen. Es wird 29 Milliarden Jahre laufen, bevor es überläuft. noch 6,8 Jahre auf einem 32-Bit-System. Ich würde sagen, das ist akzeptabel.

Durch die Berechnung der Position anstelle der Anpassung wurde viel gespart, und die vollständige Vorlage wurde sofort für ein weiteres Los vorbereitet.

for(;++$i;$s[-3-21*abs($i%14-7)-abs($i%34-17)]="*",print$f(_,9e5,"
").$s.$z,usleep(1e5))$s=($f=str_pad)($z=$f("+",19,"-")."+
",189,$f("|",19)."|
");
").$z;

Laufen Sie mit -nr. Benötigt PHP 7.1.

Aufschlüsselung :

for(;++$i;      # infinite loop:
                    # 2. set asterisk at appropriate position
    $s[-3-21*abs($i%14-7)-abs($i%34-17)]="*";
                    # 3. clear screen: print 900k newlines
    print$f(_,9e5*0+2,"\n")
            .$s.$z, # 4. print field
    usleep(1e5))    # 5. sleep 100000 microseconds
                    # 1. create template
    $s=($f=str_pad)($z=$f("+",19,"-")."+\n",189,$f("|",19)."|\n");
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.