ASCII Ball in Box Animation


11

Tulis program yang menampilkan bola ASCII bergerak *di dalam persegi panjang (20 dengan 10 karakter termasuk perbatasan). Bola tidak boleh melewati kotak, misalnya menabrak ketika menyentuh dinding. Adegan harus dibersihkan dan digambar ulang setiap 0,1 detik dan bola harus menggerakkan 1 karakter dalam arah x dan y setiap frame. Program terpendek yang ditulis dalam bahasa apa pun menang.

Contoh output (frame 1)

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

Contoh output (bingkai 2)

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

Contoh output (frame 8)

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

Contoh output (frame 9)

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

4
Apakah mencetak 99 baris baru memenuhi syarat sebagai membersihkan layar?
Ventero

Tidak pada monitor saya dengan 1080x1920resolusi :)
mellamokb

Jawaban:


7

Ruby 1.9, 115 karakter

Logika Gerakan ini sangat mirip dengan Danko 's jawaban .

Versi ini telah diuji di Linux saja.

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}

Dengan Ruby 1.9.3 di bawah Windows 7, puts"\e[2J"cukup cetak ←[2J(dan baris baru) di layar.
res

@res Lihat hasil edit saya untuk versi yang seharusnya berjalan pada Windows (sayangnya tidak dapat mengujinya sendiri).
Ventero

Menggunakan clstidak bekerja untuk saya, tetapi system ("cls")tidak.
res

@res gunakan `cls`. Backticks literal.
Mark Reed

@ MarkReed - Itulah yang saya coba tulis .. Lagipula, tidak berhasil. Windows tampaknya membutuhkan sistem ("cls").
res

4

Powershell, 144 karakter

Berdasarkan jawaban Joey yang luar biasa , menggunakan fakta bahwa koordinat bola adalah fungsi dari frame index (i), jadi jika Anda memiliki sesuatu seperti x=n-abs(n-(i mod (2*n))), x akan berubah dari 0 ke n, kembali ke 0, dan seterusnya ...

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}

Bagus Meskipun saya agak bangga dengan saya if(-1,18-eq$x){$a*=-1;$x+=2*$a}if(-1,8-eq$y){$b*=-1;$y+=2*$b}yang menggantikan empat ifs sebelumnya ;-). Tapi saya yakin harus ada formula.
Joey

3

Python 2, 234

Saya yakin ini bisa bermain golf lebih banyak, tetapi saya harus pergi jadi inilah yang saya miliki. akan bekerja lebih banyak lagi nanti

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)

Catatan: berfungsi pada konsol perintah Windows. Sistem operasi lain mungkin menggunakan perintah yang berbeda dari clsuntuk membersihkan layar, seperticlear


tidak print "\e[H\e[2J"berfungsi di windows?
Patrick Oscity

@padde - Sepertinya tidak berfungsi ketika saya menjalankan program Ruby Anda di Windows 7 (lihat komentar saya untuk posting Anda).
res

3

Ruby ( 179 174 147)

EDIT menghilangkan beberapa karakter lagi:

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 mencukur beberapa karakter, sekarang 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}

Tidak Disatukan:

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

Tidak seharusnya sleep .1bekerja juga?
Joey

Tidak, tidak di 1.9. SyntaxError: (irb):1: no .<digit> floating literal anymore; put 0 before dot. Tapi saya akan kembali ke itu jika saya membutuhkannya di masa depan, terima kasih!
Patrick Oscity

Jika Anda menggunakan 1,9, Anda dapat menggunakan char literals untuk mempersingkat beberapa hal, misalnya ?*alih-alih '*', dll.
Joey

Menggunakan Ruby 1.9.3 di bawah Win7, ini mencetak persegi panjang satu setelah (di bawah) yang lain, masing-masing memiliki ←[2J←[f+------------------+sebagai baris pertama.
res

lalu ubah $> << "\e[2J\e[f"+fke 'cls';$><<f(gunakan backticks untuk 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/

Saya menulis ini dengan cukup cepat jadi saya yakin masih ada sedikit ruang untuk perbaikan. Saran dipersilahkan :)

Sunting 1 : Hapus panggilan fungsi terpisah yang tidak perlu, sematkan langsung di setInterval.


2

Haskell, 212 karakter

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

Gunakan pendekatan yang lebih fungsional untuk menghitung koordinat, dengan membuat urutan tak terbatas untuk masing-masing koordinat secara terpisah dan kemudian mengikatnya bersama-sama (baris 2 dan 3). Sisanya menggambar kode.


2

PowerShell, 184 185 215

Hanya semi-golf karena otak saya tidak berfungsi dengan baik ketika saya sakit ...

Tapi ada beberapa trik bagus di dalamnya.

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}

[Sunting]: Looping di atas lapangan jauh lebih pendek.


2

QBasic (QB64), 178 173 byte

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 byte berkat DLosc


Bagus! Untuk loop tak terbatas, Anda dapat menggunakan DO ... LOOPdi tempat WHILE 1 ... WENDdan menyimpan 5 byte.
DLosc

1

Perl 5, 141 karakter

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

Tidak mulai di sudut kiri atas seperti contoh output, tetapi itu tidak dinyatakan sebagai persyaratan.


1

Ruby 1.9, 162 karakter

35 karakter malu dengan jawaban @ Ventero, tapi saya terkesan bahwa saya bisa turun sejauh ini sambil masih menggunakan pendekatan yang relatif mudah ke logika yang sebenarnya. ^ [Adalah ESC literal (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}

1

R, 233 karakter

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

Entri bash lain - 213 204 karakter

Sebenarnya bukan pemenang hadiah, tapi tetap saja menyenangkan. Ini menggunakan urutan char vt100 untuk gambar. (kode yang dilaporkan di sini menggunakan 215 karakter untuk dibaca, 2 karakter dapat dihapus dengan melarikan diri, misalnya '*' -> \ *

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 byte

Terinspirasi oleh jawaban Danko Durbić .

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

Script ini menggunakan -replaceoperator untuk menggambar *di dalam persegi panjang.

Lebih sedikit skrip golf untuk menjelaskan cara kerjanya:

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

\ E di baris echo -e "\e[$2;$1H$3"dapat diproduksi oleh

echo -e "\x1b"

untuk menggantinya. Sebagai biner 0x1b, 3 karakter lebih pendek; Saya menghitung hanya 1 untuk "\ e", karena hanya perangkat lunak tata letak yang memaksa saya untuk menggunakannya \e.


Seorang pengguna anonim menyarankan suntingan untuk menghapus $simbol di dalamnya ((...))dan mengganti x=$(($x+$p))dengan ((x+=p))dan juga pada baris berikut. (Mereka juga menyarankan penggunaan \euntuk karakter pelarian).
Peter Taylor

Saya akan menyarankan sebagai tambahan yang \*mungkin berfungsi sebagai pengganti "*".
Peter Taylor

@PeterTaylor: Terima kasih kepada pengguna anonim. Saya memasukkan saran no 1, dan menggunakan no 2 dalam bentuk yang dimodifikasi, dan saran Anda.
pengguna tidak diketahui

@userunknown: Anda 1,337perlu dikunci secara permanen di tempat: P
mellamokb

1
@ellamokb: Sudah pergi.
pengguna tidak diketahui

0

TI Basic, 169 167 byte

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

Sangat lambat, tapi berhasil.


(X=20)→Sdapat (X=20→S, dan Anda dapat mengambil keuntungan dari Ans untuk menyimpan beberapa byte di akhir For (loop. Saya positif baris 8 dan 9 dapat golf, tapi saya tidak yakin bagaimana saat ini.
MI Wright

@ IMWright Di mana saya akan meletakkan Ans?
fase

"| \ Output(O,1,Ans \ Output(O,20,Ansharus bekerja.
MI Wright

@ IMWright Tapi bukankah itu menggantikan string dua karakter dengan string tiga karakter? Dan menambahkan dua karakter string di atasnya, menjadikannya +4?
fase

Maksud kamu apa? Ansadalah token satu byte , diketik dengan 2nd (-). Itu akhirnya akan menghemat satu byte, karena |tokennya dua byte pada kalkulator.
MI Wright

0

PHP, 196 186 148 byte

Saya menghapus menghindari integer overflow untuk menghemat 6 byte. Itu akan berjalan selama 29 miliar tahun sebelum meluap; masih 6,8 tahun pada sistem 32 bit. Saya katakan itu bisa diterima.

Menghitung posisi alih-alih menyesuaikannya banyak menghemat, menyiapkan templat lengkap sekaligus lot lain.

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;

Jalankan dengan -nr. Membutuhkan PHP 7.1.

kerusakan :

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");
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.