Pong nel codice più breve


28

La sfida è semplice Fornisci il codice più breve possibile per riprodurre il classico gioco a 2 giocatori di pong http://en.wikipedia.org/wiki/Pong . Il livello di grafica e funzionalità dovrebbe essere il più vicino possibile a questa dimostrazione javascript http://codeincomplete.com/posts/2011/5/14/javascript_pong/demo.html (ma senza le opzioni extra è possibile fare clic sulla sinistra o le informazioni sul frame, fps ecc. in basso a destra).

Come sempre il codice deve essere scritto in un linguaggio libero (in entrambi i sensi) e deve essere eseguibile su Linux. Le biblioteche utilizzate devono anche essere libere, facilmente disponibili e non devono essere scritte ai fini di questo concorso (e inoltre non devono già contenere una versione funzionante di Pong!).


Onestamente, questa domanda è un po 'troppo difficile per il golf di codice. La fisica della palla per Pong è piuttosto complicata.
beary605

@ beary605, non penso che la fisica della palla sia troppo complicata. La mia soluzione è "il più vicino possibile" alla dimostrazione javascript e la fisica è abbastanza semplice.
stand

Solo per riferimento ci sono altri [code-golf] che durano abbastanza a lungo. Costruisci un motore per un gioco labirinto , Noughts and Crosses (aka Tic-Tac-Toe) (entrambi potrebbero usare voci aggiuntive, a cui piace "vincere" per impostazione predefinita?), Scrivere un piccolo server HTTP , Interprete autointerpretante , Auto- compilatore di compilazione , Compile Regexes ...
dmckee

@felipa, puoi formalizzare 'il più vicino possibile'? Non so perché la mia soluzione sed non sia in testa.
stand dal

Risposte:


24

Javascript, 883 (+ 70 HTML)

c=document.getElementById('c').getContext('2d')
c.fillStyle="#FFF"
c.font="60px monospace"
w=s=1
p=q=a=b=0
m=n=190
x=300;y=235
u=-5;v=3
setInterval(function(){if(w&&!s)return;s=0
c.clearRect(0,0,640,480)
for(i=5;i<480;i+=20)c.fillRect(318,i,4,10)
m+=p;n+=q
m=m<0?0:m;m=m>380?380:m
n=n<0?0:n;n=n>380?380:n
x+=u;y+=v
if(y<=0){y=0;v=-v}
if(y>=470){y=470;v=-v}
if(x<=40&&x>=20&&y<m+110&&y>m-10){u=-u+0.2;v+=(y-m-45)/20}
if(x<=610&&x>=590&&y<n+110&&y>n-10){u=-u-0.2;v+=(y-n-45)/20}
if(x<-10){b++;x=360;y=235;u=5;w=1}
if(x>640){a++;x=280;y=235;u=-5;w=1}
c.fillText(a+" "+b,266,60)
c.fillRect(20,m,20,100)
c.fillRect(600,n,20,100)
c.fillRect(x,y,10,10)},30)
document.onkeydown=function(e){k=(e||window.event).keyCode;w=w?0:k=='27'?1:0;p=k=='65'?5:k=='81'?-5:p;q=k=='40'?5:k=='38'?-5:q;}
document.onkeyup=function(e){k=(e||window.event).keyCode;p=k=='65'||k=='81'?0:p;q=k=='38'||k=='40'?0:q}


/* Variable index:
a -> left player score
b -> right player score
c -> context
e -> event
i -> counter for dashed line
k -> keycode
m -> left paddle y
n -> right paddle y
p -> left paddle y velocity
q -> right paddle y velocity
s -> is start of game
u -> ball x velocity
v -> ball y velocity
w -> game is waiting (paused)
x -> ball x
y -> ball y
*/

Lo script può essere posizionato alla fine <body>o chiamato onLoad. Ha bisogno del seguente elemento canvas:

<canvas id="c"width="640"height="480"style="background:#000"></canvas>

Il giocatore 1 usa i tasti qe a, il giocatore 2 usa i tasti pe l. Premere il esctasto per mettere in pausa e qualsiasi tasto per avviare / continuare.

Puoi giocarci nel tuo browser qui .

Non ero sicuro della fisica da usare, quindi ho iniziato con un semplice metodo di riflessione e poi ho aggiunto un po 'di varietà e ho sperimentato un po'. La velocità della palla nella direzione y è influenzata da dove sulla paletta colpisci la palla, quindi hai un certo controllo su dove va la palla. La velocità della palla nella direzione x aumenta lentamente ad ogni colpo nel raduno.

Ho il sospetto che sarà battuto abbastanza facilmente dalle soluzioni che usano le librerie, ma mi sono divertito a farlo in javascript.


2
È un'implementazione davvero interessante.
Felipa,

1
Potrei giocare a golf un po 'di più, so che sono in ritardo di circa due anni. ma è possibile assegnare 20a una variabile denominata ge salvare un byte misero.
Zacharý,

Dannazione, è difficile suonare su una tastiera azerty ...
dim

38

sed, 35

Alzando un po ' la barra con un francobollo sed meditazione.

s/> / >/
s/ </< /
s/0</0>/
s/>1/<1/

La meditazione è goduta su stdin / stdout su due computer, non necessariamente collegati da una rete. La meditazione inizia nello stato

0         <       1

con guru zero a sinistra e uno a destra. La parentesi angolare si sposta a sinistra e a destra e se un guru manovra il proprio numero per contattare il cursore quando arriva dalla sua parte, il loro punteggio viene aumentato di uno e diventano euforici di gioia.

La meditazione viene iniziata digitando lo stato sopra sed -f medi.sede il computer risponde allo stato successivo. I guru diligenti scrivono nella meditazione, leggendo ad alta voce la chiave successiva che premeranno, con entrambi i guru che premono contemporaneamente la chiave sacra per enteril futuro. Il doveroso computer risponde con lo stato successivo. Questo, a sua volta, viene letto ad alta voce mentre digitato all'unisono come con l'ultimo. Continua ad avanzare nel futuro fino a raggiungere la felicità infinita.

I guru che desiderano una sfida possono giocare in modalità "turbo", in cui i guru tentano di prevedere in modo collaborativo il prossimo stato del computer e digitandolo nel prompt anziché nello stato corrente. I guru avranno la saggezza di verificare l'accordo tra le loro previsioni prima di entrare nel futuro.


23
Amico ... cosa ho appena letto?
MrZander

9
@MrZander Solo attraverso un'ampia contemplazione la saggezza della meditazione può essere rivelata. Questa contemplazione è aiutata al meglio attraverso l'esecuzione del programma.
stand dal

15

Python (con pygame ) 650 byte

Caratteristiche

  • Modalità 1 e 2 giocatori : quando inizia il gioco, premi 1per 1 giocatore o2 per 2 giocatori. Il gioco non inizierà finché non viene premuto uno di questi tasti.
  • Aumento della velocità della palla - Ad ogni tiro al volo, la velocità della palla viene aumentata in modo che dopo 10 volée sia aumentata di circa il 50%, dopo 20 sarà il 50% più veloce di così, ecc.
  • Deflessione della sfera variabile - La sfera si basa su due fattori: quale parte della paletta colpisce e se la paletta si muove o meno all'impatto. Se la palla colpisce la paletta vicino a una delle estremità, sarà deviata più fortemente che se colpisce vicino al centro (quasi come se fosse una superficie curva). Inoltre, se la paletta è in movimento, il movimento della paletta viene aggiunto alla deflessione. Per ottenere la massima flessione, la palla deve colpire vicino all'estremità della paletta e la paletta deve essere in movimento verso quella stessa estremità. Questo è molto simile al Pong originale per Atari 2600.
  • Pausa : il gioco può essere messo in pausa in qualsiasi momento premendo la Spacebarra. La riproduzione riprenderà premendo la barra spaziatrice una seconda volta.
  • Controlli - Come con l'esempio, il giocatore 1 si muove con i Qe Ale chiavi, e il giocatore 2 si sposta con Pe L.

Come nota finale, vorrei richiedere che questa soluzione non sia selezionata come risposta accettata, per vari motivi.

from pygame import*
init();d=display;s=d.set_mode((640,480))
g=p=16;j=q=80;x=y=200;o=t=h=v=1;z=m=n=0;w=[255]*3
while s.fill(time.wait(3)):
 event.get();k=key.get_pressed();t^=o*k[32];o=1-k[32];z=z or-k[49]-k[50]*2;e=k[113]-k[97];f=[k[112]-k[108],(h>0)*cmp(y,q-32)][z];a=p<g;b=q-[y,x][a]
 if p%608<g:m,n,p,h,v=[m+1-a,m,n+a,n,g+a*592,p,1-a*2,h/-.96,1,b/32.+~[f,e][a]][-g<b<j::2]
 for r in[(0,x,g,j),(624,y,g,j),(p,q,g,g)]+[(316,i*31,8,15)for i in range(g)]:draw.rect(s,w,r)
 if z*t:v*=(0<q<464)*2-1;x-=(0<x-e<400)*e/.6;y-=(0<y-f<400)*f/.6;p+=h;q+=v
 c=font.SysFont('monospace',j,1).render('%3d %%-3d'%m%n,1,w);s.blit(c,(320-c.get_width()/2,0));d.flip()

Schermata di esempio:

Nota: il carattere utilizzato per il punteggio può variare da sistema a sistema.


Il punteggio mostra nella metà sinistra per me e penso che la deflessione sia troppo forte, ma è comunque piuttosto interessante :)
aditsu

@aditsu stai operando con Linux? Vedrò se riesco a trovare un'alternativa che funzioni indipendentemente dalla faccia del carattere selezionata. L'idea alla base della deflessione è che sarebbe possibile deviare la palla a una velocità maggiore (massimo 2,5 sulla mia scala) di quanto la paletta possa muoversi ( 1.67 ). Questo è possibile solo se gli dai un po 'di spin. Se la paletta non si muove quando la palla colpisce, il massimo è la velocità sarà 1,5 .
primo

Sì, sto usando Linux. Trovo strano che la palla possa effettivamente "tornare indietro" (su o giù) dopo aver colpito la paletta, invece di continuare nella stessa direzione (forse con un'angolazione diversa). Ma forse la versione Atari l'ha fatto, non lo so.
aditsu,

@aditsu È costato pochi byte, ma credo che il punteggio debba essere centrato indipendentemente dal font scelto (purché sia ​​monospaziale). Fammi sapere se funziona per te. E sì, la deflessione è molto simile (anche se una distribuzione più fluida) alla versione Atari che conoscevo. Se immagini la paletta come una superficie curva (convessa) (come una paletta da air hockey), penso che dovrebbe essere più intuitiva.
primo

Sì, ora è centrato
aditsu

8

HTML e JavaScript (take 2) - 525

Dal momento che l'OP non sembrava preoccuparsi molto della parte "il più vicino possibile", ecco una soluzione alternativa che ho semplificato senza pietà, spogliato e giocato a golf. Q / A e P / L per giocare, ma anche ogni altro tasto ha un effetto. Ancora una volta, il codice è completamente autonomo e l'ho testato in Chromium 25 su Linux. Posso giocare a golf ancora di più se puoi accettare piccoli bug o un peggioramento della qualità grafica / del gameplay.

<canvas id=c><script>C=c.getContext('2d');f=C.fillRect.bind(C)
S=[-1,I=J=0];A=B=210;X=Y=1
function g(n){++S[n];N=Math.random(M=n*613+9)*471}D=document
D.onkeydown=D.onkeyup=function(e){d=!!e.type[5];k=e.keyCode
k&1?I=k&16?d:-d:J=k&4?-d:d}
g(0);setInterval(function(){A-=A<I|A>420+I?0:I
B-=B<J|B>420+J?0:J
M+=X;N+=Y
N<0|N>471?Y=-Y:0
M==622&N>B&N<B+51|M==9&N>A&N<A+51?X=-X:M>630?g(0):M||g(1)
f(0,0,c.width=640,c.height=480)
C.fillStyle='tan';C.font='4em x';C.fillText(S,280,60)
f(0,A,9,60);f(631,B,9,60);f(M,N,9,9)},6)</script>

Grazie Shmiddty


Non capisco l'obiezione. Per quanto posso ricordare, la versione da 715 byte (modificata 3 ore prima di questo post) è quasi identica alla versione originale di Pong che avevo per il mio Atari 2600.
primo

@primo Suppongo che tu stia parlando della mia affermazione implicita che la tua soluzione non soddisfa il criterio "il più vicino possibile". Bene, l'OP non ha menzionato la versione Atari 2600, ma un'implementazione javascript specifica a cui si è collegato. E a prima vista ci sono 2 differenze evidenti nel tuo codice: nessun lettore di computer e nessuna visualizzazione del punteggio "7 segmenti". Probabilmente ci sono molte più differenze nella "meccanica". Se queste cose non sono importanti, penso che anche questa soluzione dovrebbe essere valida.
aditsu,

Questo è il mio errore Intendevo davvero "il più vicino possibile", quindi la tua prima soluzione è la migliore finora.
Felipa,

puoi rimuovere il file c=window.c. Stai assegnando una variabile globale a se stessa.
Shmiddty,

Puoi salvare un altro personaggio spostandoti ++S[n]all'interno di.random(++S[n])
Shmiddty il

5

HTML e JavaScript - 1663

Contro il mio miglior giudizio, ho preso l'approccio folle di giocare a golf il codice reale dalla demo. Ho rimosso alcune funzionalità ed elementi dell'interfaccia, ma generalmente funziona esattamente allo stesso modo: 0, 1 o 2 per scegliere il numero di giocatori umani, Q / A e P / L da spostare.

A meno che non abbia commesso degli errori, il gameplay dovrebbe essere identico, pixel per pixel e millisecondi per millisecondo, rispetto all'originale a 640 * 480 (suggerimento: il ridimensionamento della finestra del browser modifica le dimensioni del gioco nella demo). Semplicemente non dà istruzioni, non annuncia il vincitore e non gestisce esc.

Il codice è completamente autonomo e l'ho testato in Chromium 25 su Linux. Firefox non piace molto.

<body bgcolor=0><canvas id=c height=480><script>R=Math.random
C=c.getContext('2d');f=C.fillRect.bind(C)
S=[l=G=I=J=K=L=0,0];r=17;u=463;o=24;q=12;z=10;s=640;v=36
function T(z,t,u,v){P=0;if(e=v*E-u*F){a=(u*t-v*z)/e;b=(E*t-F*z)/e
a<0|a>1|b<0|b>1?0:P={x:M+a*E,y:N+a*F,d:u,s:0,X:X,Y:Y}}}function
i(p,q,h){T(p-22*(E<0),q,0,h)
P?0:T(p,q-h*(F<0),22,0)}function
U(p){if(p.a)if(M<p.x&X<0|M>p.x+q&X>0)p.u=0
else{P=p.P;if(P&&P.X*X>0&P.Y*Y>0&P.s<p.l/z)P.s+=t
else{E=X*z;F=Y*z;i(M-p.x+5,s*q,s*o)
if(p.P=P){y=P.y;while(y<r|y>u)y=y<r?34-y:y>u?u+u-y:y
P.y=y+R(e=(p.l+2)*(X<0?M-p.x-q:p.x-M)/64)*2*e-e}}P?p.u=P.y<p.y+25?1:P.y>p.y+35?-1:0:0}y=p.y-p.u*t*198
p.y=y<q?q:y>408?408:y}function
W(n,x){a=9.6;b=[~8,3,62,31,75,93,~2,7,-1,u][n]
b&4&&f(x,o,v,a);b&64&&f(x,o,a,o)
b&2&&f(x+v,o,-a,o);b&8&&f(x,43.2,v,a)
b&32&&f(x,48,a,o);b&1&&f(x+v,48,-a,o)
b&16&&f(x,72,v,-a)}A={u:0,x:0,y:210};B={u:0,x:628,y:210}
function g(n){if(++S[n]>8)G=A.a=B.a=0
else{N=R(M=n?635:5)*446+r;Y=157.5;X=n?-Y:Y
A.l=z+S[0]-S[1];B.l=20-A.l}}D=document
D.onkeydown=D.onkeyup=function(e){d=!!e.type[5]
k=e.keyCode-45;if(k>2&k<6&d&!G){G=S=[-1,0];A.a=k<4;B.a=k<5
g(0)}k^31?k^35?k^20?k^v?0:I=d:J=d:K=d:L=d
A.a?0:A.u=I-J;B.a?0:B.u=K-L}
setInterval(function(){t=new Date()/1000-l;l+=t;U(A);U(B)
if(G){E=t*X+4*t*t;F=t*Y+4*t*t
x=M+E;y=N+F;m=X+t*(X>0?8:-8);n=Y+t*(Y>0?8:-8)
if(n>0&y>u){y=u;n=-n}if(n<0&y<r){y=r;n=-n}p=m<0?A:B
i(M-p.x+5,N-p.y+5,70)
if(P){if(P.d){y=P.y;n=-n}else{x=P.x;m=-m}n*=n*p.u<0?.5:p.u?1.5:1}M=x;N=y
X=m;Y=n;M>645?g(0):M<-5&&g(1)}c.width=s;C.fillStyle='#fff'
f(0,0,s,q);f(0,468,s,q);for(j=o;j--;)f(314,6+o*j,q,q)
W(S[0],266.5);W(S[1],338.5)
f(0,A.y,q,60);f(s,B.y,-q,60);G&&f(M-5,N-5,z,z)},50/3)</script>

Alcuni crediti a Shmiddty per miglioramenti


4

Elaborazione, 487 caratteri

int a=320,b=240,c=2,d=2,e=0,f=0,g=0,h=0,i=15,j=80,k=640,
l=160,m;void setup(){size(k,b*2);}void draw(){background
(0);if(keyPressed){if(key=='q'&&g>0)g-=i;if(key=='a'&&g<
j*5)g+=i;if(key=='o'&&h>0)h-=i;if(key=='l'&&h<j*5)h+=i;}
rect(0,g,i,j);for(m=0;m<k;m+=30)rect(312,m,i,i);rect(a,b
,i,i);rect(625,h,i,j);a+=c;b+=d;c*=a<i&&(b>g&&b+i<g+j)||
a>610&&(b>h&&b+i<h+j)?-1:1;d*=b<0||b>=465?-1:1;if(a<0){f
++;a=0;b=240;c=2;}if(a>k){e++;a=625;b=240;c=-2;}textSize
(j);text(e,l,j);text(f,3*l,j);}

Schermata di esempio:

inserisci qui la descrizione dell'immagine

Questo codice è stato creato pensando alla carenza, quindi è piuttosto buggy (la palla a volte passa attraverso la paletta o la avvolge). I controlli sono Q / A per Player 1 e O / L per Player 2.


1
Come gioco la tua versione di Pong sembra anche abbastanza ingiusta, poiché per ogni frame sono registrate le chiavi di un solo giocatore: P
Jonathan Frech

2

C # - 1283 caratteri

Questo può essere giocato a golf un po 'di più, ma eccolo qui.

using System;using System.Drawing;using System.Runtime.InteropServices;using System.Windows.Forms;using r=System.Drawing.RectangleF;namespace f{public partial class f:Form{public f(){InitializeComponent();}private void f_Load(object sender,EventArgs e){var t=this;var s=new r(0,0,300,300);var q=new r(0,0,15,50);var o=new r(0,0,15,50);var x=new PointF(150,150);var v=.06F;var h=v;var b=new r(x.X,x.Y,15,15);var p1=0;var p2=0;var p=new PictureBox{Size=t.Size,Location=new Point(0,0)};t.Controls.Add(p);p.Paint+=(wh,n)=>{var g=n.Graphics;Action<Brush,r>f=g.FillRectangle;var k=new SolidBrush(Color.Black);var w=new SolidBrush(Color.White);var d=new byte[256];GetKeyboardState(d);var l=q.Location;var _1=.1F;q.Location=new PointF(0,d[90]>1?l.Y+_1:d[81]>1?l.Y-_1:l.Y);l=o.Location;o.Location=new PointF(269,d[77]>1?l.Y+_1:d[79]>1?l.Y-_1:l.Y);f(k,s);f(w,q);f(w,o);Func<r,bool>i=b.IntersectsWith;h=i(q)||i(o)?-h:h;v=b.Top<1||b.Bottom>t.Height-30?-v:v;b.Offset(h,v);if(b.Left<0){p2++;b.Location=x;}if(b.Right>290){p1++;b.Location=x;}f(w,b);for(int j=0;j<19;)f(w,new r(140,(j+(j++%2))*15,10,10));var a=new Font("Arial",20);g.DrawString(p1.ToString(),a,w,100,12);g.DrawString(p2.ToString(),a,w,170,12);p.Invalidate();};}[DllImport("user32.dll")]static extern bool GetKeyboardState(byte[]s);}}

Modifica: non ho visto i requisiti per un linguaggio gratuito, eseguibile su Linux ...


2

Tcl / Tk , 932 byte

Deve essere eseguito nella shell interattiva

gri [can .c -w 1024 -he 768 -bg #000]
proc A {} {set ::v [expr (int(rand()*36)+1)*20]}
proc R {C t\ X} {.c cr r $C -f #aaa -t $t}
proc I {} {incr ::v 20}
time {R "504 [I] 520 [I]"} 18
R "0 0 1024 20"
R "0 748 1024 768"
R "0 340 20 440" b
R "1004 340 1024 440" B
R "40 [A] 60 [I]" P
lmap n 4\ 5 T F\ S {.c cr t ${n}62 60 -ta $T -te 0 -fi #aaa -font {"" 56}}
proc C t\ n {lindex [.c coo $t] $n}
lmap {a b c d e} {q b 1 >20 -20 a b 3 <740 20 p B 1 >20 -20 l B 3 <740 20} {bind . $a "if \[C $b $c]$d {.c move $b 0 $e}"}
lassign {0 0 20 20} F S y x
proc M {} {lmap {_ a b c d e f} {0 <40 b 20 S 960 980 2 >984 B -20 F 80 100} {if [C P $_]$a {if [C P 1]>=[C $b 1]&&[C P 3]<=[C $b 3] {bell
set ::x $c} {.c itemco $d -te [incr ::$d]
if \$::$d>8 {tk_messageBox -message WINNER!
lmap T F\ S {.c itemco $T -te [set ::$T 0]}}
.c coo P $e [A] $f [I]}}}
.c move P $::x [set ::y [expr [C P 1]<40?20:[C P 3]>727?-20:$::y]]
after 99 M}
M
focus -f .

Nota:

 #There is an Enter at the end

Solo una versione molto minimale di Pong, in cui la palla corre solo in angoli diagonali e ha sempre la stessa velocità.

inserisci qui la descrizione dell'immagine


Outgolf fallito: bit.ly/2VSIGz8
sergiol
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.