# ASCII Ball in Box Animation

Write a program that displays a moving ASCII ball * inside a rectangle (20 by 10 chars including border). The ball must not cross the rectangle, e.g. bump off when it hits the wall. The scene must be cleared and redrawn every 0.1 seconds and the ball must move 1 char in x and y direction every frame. The shortest program written in any language wins.

Example output (frame 1)

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


Example output (frame 2)

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


Example output (frame 8)

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


Example output (frame 9)

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

• Does printing 99 newlines qualify as clearing the screen? – Ventero Apr 27 '12 at 13:52
• Not on my monitor with 1080x1920 resolution :) – mellamokb Apr 27 '12 at 14:10
• – Titus Nov 29 '18 at 14:13

## Ruby 1.9, 115 characters

The movement logic is quite similar to Danko's answer.

This version has been tested on Linux only.

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}

• With Ruby 1.9.3 under Windows 7, puts"\e[2J" just prints ←[2J (and a newline) on the screen. – r.e.s. Apr 27 '12 at 1:55
• @r.e.s. See my edit for a version which should run on Windows (can't test it myself unfortunately). – Ventero Apr 27 '12 at 2:06
• Using cls doesn't work for me, but system ("cls") does. – r.e.s. Apr 27 '12 at 4:14
• @r.e.s. use cls. Literal backticks. – Mark Reed Apr 27 '12 at 4:34
• @MarkReed - That's what I tried to write .. Anyway, it doesn't work. Windows seems to require system("cls"). – r.e.s. Apr 27 '12 at 5:43

## Powershell, 144 characters

Based on Joey's excellent answer, using the fact that the ball coordinates are a function of the frame index (i), so if you have something like x=n-abs(n-(i mod (2*n))), x will go from 0 to n, back to 0, and so on...

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}  • Nice one. Although I was kinda proud of my if(-1,18-eq$x){$a*=-1;$x+=2*$a}if(-1,8-eq$y){$b*=-1;$y+=2*$b} which replaced four ifs earlier ;-). I was sure there had to be a formula, though. – Joey Apr 27 '12 at 5:14 ## Python 2, 234 I'm sure this can be golfed more, but I gotta go so here's what I have sofar. will work more on it later 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)  note: works on Windows command console. Other operating systems may use a different command than cls to clear the screen, such as clear • does print "\e[H\e[2J" work on windows? – Patrick Oscity Apr 26 '12 at 21:00 • @padde - It doesn't seem to work when I run your Ruby program under Windows 7 (see my comment to your post). – r.e.s. Apr 27 '12 at 1:41 ## Ruby (179174 147) EDIT got rid of some more chars: 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 shaved off some chars, now 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
$('#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)  I wrote this up pretty quickly so I'm sure there's still quite a bit of room for improvement. Suggestions are welcome :) Edit 1: Remove unnecessary separate function call, embed directly in setInterval. ## Haskell, 212 characters import System main=mapM_ f$s 19zips 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"
$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}  : Looping over the field is much shorter. ## 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 thanks to DLosc

• Nice! For the infinite loop, you can use DO ... LOOP in place of WHILE 1 ... WEND and save 5 bytes. – DLosc Jun 25 '18 at 1:11

## Perl 5, 141 characters

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  Does not start on the upper left corner as the example output does, but that is not stated as a requirement. ## Ruby 1.9, 162 characters 35 chars shy of @Ventero's answer, but I was impressed that I could get it down this far while still using a relatively straightforward approach to the actual logic. The ^[ is a literal ESC (1 char). 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}  ## R, 233 characters 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")}  Another bash entry - 213 204 chars Not really a prize winner, but it was fun nonetheless. It uses vt100 char sequences for the drawing. (the code reported here uses 215 chars for readability, 2 chars can be removed by escaping, e.g. '*' -> \* 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


# Powershell, 139 bytes

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


This script uses the -replace operator to draw * inside the rectangle.

Less golfed script to explain how it works:

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
}


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


The \e in the line echo -e "\e[$2;$1H$3" can be produced by echo -e "\x1b"  to replace it. As binary 0x1b it is 3 chars shorter; I count just 1 for "\e", because only the layouting software forces me to use \e. • An anonymous user suggested edits to remove the $ symbols inside ((...)) and replace x=$(($x+$p)) with ((x+=p)) and similarly on the following line. (They also suggested using \e for the escape character). – Peter Taylor Apr 27 '12 at 11:20 • I would suggest in addition that \* might work as a replacement for "*". – Peter Taylor Apr 27 '12 at 11:28 • @PeterTaylor: Thanks to the anonymous user. I incorporated suggestion no 1, and use no 2 in modified form, and yours. – user unknown Apr 27 '12 at 11:34 • @userunknown: You're rep of 1,337 needs to be permanently locked in place :P – mellamokb Apr 27 '12 at 19:08 • @mellamokb: It's gone. – user unknown Apr 28 '12 at 23:49 # 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  Horribly slow, but it works. • (X=20)→S can be (X=20→S, and you can take advantage of Ans to save a few bytes in the final For( loop. I'm positive lines 8 and 9 can be golfed, but I'm not sure how at the moment. – M. I. Wright Jun 24 '15 at 22:56 • @M.I.Wright Where would I put the Ans? – phase Jun 24 '15 at 22:59 • "| \ Output(O,1,Ans \ Output(O,20,Ans should work. – M. I. Wright Jun 24 '15 at 23:00 • @M.I.Wright But isn't that replacing a two character string with a three character string? And adding the two character string above it, making it +4? – phase Jun 24 '15 at 23:02 • What do you mean? Ans is a one-byte token, typed with 2nd (-). That'll end up saving one byte, since the | token is two bytes on the calculator. – M. I. Wright Jun 24 '15 at 23:04 # PHP, 196 186 148 bytes I removed avoiding an integer overflow to save 6 bytes. It will run for 29 billion years before overflow; still 6.8 years on a 32 bit system. I´d say that´s acceptable. Calculating the position instead of adjusting it saved a lot, preparing the complete template at once another lot. 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;


Run with -nr. Requires PHP 7.1.

breakdown:

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