Pong en el código más corto

28

El desafío es simple. Proporcione el código más corto posible para reproducir el clásico juego de 2 jugadores de pong http://en.wikipedia.org/wiki/Pong . El nivel de gráficos y funcionalidad debe ser lo más cercano posible a esta demostración de JavaScript http://codeincomplete.com/posts/2011/5/14/javascript_pong/demo.html (pero sin las opciones adicionales, puede hacer clic a la izquierda o la información del cuadro, fps, etc. en la parte inferior derecha).

Como siempre, el código debe estar escrito en un lenguaje libre (en ambos sentidos) y debe ser ejecutable en Linux. Las bibliotecas utilizadas también deben ser gratuitas, fácilmente disponibles y no estar escritas para los propósitos de esta competencia (¡y tampoco deben contener una versión funcional de Pong!).

felipa
fuente
Honestamente, esta pregunta es demasiado difícil para el golf de código. La física de la pelota para Pong es bastante complicada.
beary605
@ beary605, no creo que la física de la pelota sea demasiado complicada. Mi solución es 'lo más cercana posible' a la demostración de JavaScript, y la física es bastante simple.
Boothby
Solo como referencia, hay algunos otros [code-golf] que duran bastante. Construya un motor para un juego de laberintos , Noughts and Crosses (también conocido como Tic-Tac-Toe) (ambos podrían usar entradas adicionales, ¿a quién le gusta "ganar" de forma predeterminada?), Escribir un pequeño servidor HTTP , Intérprete de autointerpretación , Auto- compilando compilador , compila expresiones regulares ...
dmckee
@felipa, ¿Puedes formalizar 'lo más cerca posible'? No sé por qué mi solución sed no está a la cabeza.
Boothby
1
@ beary605 demasiado difícil?
FantaC

Respuestas:

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
*/

La secuencia de comandos se puede colocar al final <body>o llamar onLoad. Necesita el siguiente elemento de lienzo:

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

El jugador 1 usa las teclas qy a, y el jugador 2 usa las teclas py l. Presione la esctecla para pausar y cualquier tecla para iniciar / continuar.

Puedes jugarlo en tu navegador aquí .

No estaba seguro de la física que usaría, así que comencé con un método simple de reflexión y luego agregué algo de variedad y experimenté un poco con él. La velocidad de la pelota en la dirección y se ve afectada por el lugar en el que golpeas la pelota, por lo que tienes cierto control sobre dónde va la pelota. La velocidad de la pelota en la dirección x aumenta lentamente con cada golpe en el rally.

Sospecho que las soluciones que usan bibliotecas pueden superarlo con bastante facilidad, pero me divertí haciéndolo en JavaScript simple.

grc
fuente
2
Esa es una muy buena implementación.
felipa
1
Podría jugar un poco más de golf, sé que llego dos años tarde aquí. pero puede asignar 20a una variable llamada gy guardar un byte miserable.
Zacharý
Maldición, es difícil tocar en un teclado azerty ...
tenue
38

sed, 35

Elevar un poco el listón con una meditación de sed con sello postal.

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

La meditación se disfruta en stdin / stdout en dos computadoras, no necesariamente conectadas por una red. La meditación comienza en el estado.

0         <       1

con guru zero a la izquierda y uno a la derecha. El corchete angular se mueve hacia la izquierda y hacia la derecha, y si un gurú maniobra su número para contactar con el cursor cuando llega a su lado, su puntaje aumenta en uno y se llenan de alegría.

La meditación se inicia escribiendo el estado anterior en sed -f medi.sed, y la computadora responde con el siguiente estado. Los gurús obedientes escriben en la meditación, leen en voz alta la siguiente tecla que presionarán, y ambos gurús presionan la tecla sagrada hacia enterel futuro al mismo tiempo. La computadora obediente responde con el siguiente estado. Esto, a su vez, se lee en voz alta mientras se escribe al unísono como con el último. Continúa avanzando hacia el futuro hasta alcanzar la dicha infinita.

Los gurús que deseen un desafío pueden jugar el modo 'turbo', en el que los gurús intentan predecir en colaboración el siguiente estado de la computadora y lo escriben en el indicador en lugar del estado actual. Los gurús tendrán la sabiduría de verificar el acuerdo entre sus predicciones antes de ingresar al futuro.

boothby
fuente
23
Amigo ... ¿qué acabo de leer?
MrZander
99
@MrZander Solo a través de una amplia contemplación se puede revelar la sabiduría de la meditación. Esta contemplación es mejor ayudada a través de la ejecución del programa.
Boothby
15

Python (con pygame ) 650 bytes

Caracteristicas

  • Modos de 1 y 2 jugadores : cuando comience el juego, presione 1para 1 jugador o 2para 2 jugadores. El juego no comenzará hasta que se presione una de estas teclas.
  • Aumento de la velocidad de la pelota : en cada volea, la velocidad de la pelota aumenta de modo que después de 10 voleas aumenta en aproximadamente un 50%, después de 20 será un 50% más rápido que eso, etc.
  • Desviación variable de la pelota: la desviación de la pelota se basa en dos factores: qué parte de la pala golpea y si la pala se mueve o no al impactar. Si la pelota golpea la paleta cerca de uno de los extremos, se desviará con más fuerza que si golpea cerca del medio (casi como si fuera una superficie curva). Además, si la paleta está en movimiento, el movimiento de la paleta se agrega a la desviación. Para obtener la desviación más fuerte, la pelota debe golpear cerca del extremo de la pala, y la pala debe estar en movimiento hacia ese mismo extremo. Esto es muy similar al Pong original para Atari 2600.
  • Pausa : el juego puede pausarse en cualquier momento presionando la Spacebarra. El juego se reanudará al presionar la barra espaciadora por segunda vez.
  • Controles - Al igual que con el ejemplo, el jugador 1 se mueve con el Qy Allaves, y el jugador 2 se mueve con Py L.

Como nota final, me gustaría solicitar que esta solución no se seleccione como la respuesta aceptada, por varias razones.

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

Captura de pantalla de muestra:

Nota: la fuente utilizada para la partitura puede variar de un sistema a otro.

primo
fuente
El puntaje se muestra en la mitad izquierda para mí, y creo que la desviación es demasiado fuerte, pero de todos modos es bastante genial :)
aditsu
@aditsu ¿estás operando bajo Linux? Veré si puedo encontrar una alternativa que funcione independientemente de la fuente seleccionada. La idea detrás de la desviación es que sería posible desviar la pelota a una velocidad más rápida (máximo 2.5 en mi escala) que la paleta puede moverse ( 1.67 ). Esto solo es posible si le das un 'giro'. Si la pala no se mueve cuando la pelota golpea, la velocidad máxima será 1.5 .
primo
Sí, estoy usando Linux. Me resulta extraño que la pelota pueda realmente "retroceder" (arriba o abajo) después de golpear la pala, en lugar de continuar en la misma dirección (quizás en un ángulo diferente). Pero tal vez la versión de Atari hizo eso, no lo sé.
aditsu
@aditsu Cuesta unos pocos bytes, pero creo que la puntuación debe centrarse independientemente de la fuente elegida (siempre que sea monoespacio). Avísame si te funciona. Y sí, la desviación es muy similar (aunque una distribución más suave) a la versión de Atari con la que estaba familiarizado. Si imagina la paleta como una superficie curva (convexa) (como una paleta de hockey de aire), creo que debería ser más intuitiva.
primo
Sí, ahora está centrado
aditsu
8

HTML y JavaScript (toma 2) - 525

Dado que al OP no parecía importarle mucho la parte "lo más cercana posible", aquí hay una solución alternativa que simplifiqué, despojé y jugué sin piedad. Q / A y P / L para jugar, pero cualquier otra tecla también tiene un efecto. Una vez más, el código es totalmente autónomo y lo probé en Chromium 25 en Linux. Puedo jugarlo aún más si puedes aceptar pequeños errores o una mayor degradación de la calidad gráfica / juego.

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

Gracias Shmiddty

aditsu
fuente
No entiendo la objeción. Hasta donde puedo recordar, la versión de 715 bytes (editada 3 horas antes de esta publicación) es casi idéntica a la versión original de Pong que tenía para mi Atari 2600.
primo
@primo Supongo que está hablando de mi afirmación implícita de que su solución no cumple con el criterio "lo más cercano posible". Bueno, el OP no mencionó la versión Atari 2600, sino una implementación de javascript específica a la que se vinculó. Y a primera vista hay 2 diferencias evidentes en su código: sin reproductor de computadora y sin pantalla de puntaje de "7 segmentos". Probablemente hay muchas más diferencias en la "mecánica". Si estas cosas no son importantes, entonces creo que esta solución también debería ser válida.
aditsu
Este es mi error. Realmente quise decir "lo más cerca posible" por lo que su primera solución es la mejor hasta ahora
felipa
puedes quitar el c=window.c. Estás asignando una variable global a sí mismo.
Shmiddty
Puedes guardar 1 personaje más moviéndote ++S[n]dentro de.random(++S[n])
Shmiddty
5

HTML y JavaScript - 1663

Contra mi mejor juicio, tomé el enfoque loco de jugar al golf el código real de la demostración. Eliminé algunas características y elementos de la interfaz, pero en general funciona exactamente igual: 0, 1 o 2 para elegir la cantidad de jugadores humanos, Q / A y P / L para mover.

A menos que haya cometido algunos errores, el juego debe ser idéntico, píxel por píxel y milisegundos por milisegundo, al original en 640 * 480 (pista: cambiar el tamaño de la ventana del navegador cambia el tamaño del juego en la demostración). Simplemente no da instrucciones, no anuncia al ganador y no maneja esc.

El código es totalmente autónomo y lo probé en Chromium 25 en Linux. A Firefox no le gusta mucho.

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

Algunos créditos a Shmiddty por mejoras

aditsu
fuente
4

Procesamiento, 487 caracteres

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

Captura de pantalla de muestra:

ingrese la descripción de la imagen aquí

Este código se hizo teniendo en cuenta la brevedad, por lo que es bastante defectuoso (la pelota a veces atraviesa la paleta o se envuelve). Los controles son Q / A para el jugador 1 y O / L para el jugador 2.

segfaultd
fuente
1
Como juego, tu versión de Pong también parece bastante injusta, ya que solo se registran las claves de un jugador por cuadro: P
Jonathan Frech
2

C # - 1283 caracteres

Esto se puede jugar un poco más de golf, pero aquí está.

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

Editar: No vi el requisito de un lenguaje libre, ejecutable por Linux ...

Brandon
fuente
2

Tcl / Tk , 932 bytes

Debe ejecutarse en el shell interactivo

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 versión muy mínima de Pong, donde la pelota solo corre en ángulos diagonales y siempre tiene la misma velocidad.

ingrese la descripción de la imagen aquí

sergiol
fuente
Outgolf fallido: bit.ly/2VSIGz8
sergiol