Pong no código mais curto

28

O desafio é simples. Dê o código mais curto possível para reproduzir o clássico jogo de pong para dois jogadores http://en.wikipedia.org/wiki/Pong . O nível de gráficos e funcionalidade deve ser o mais próximo possível desta demonstração javascript http://codeincomplete.com/posts/2011/5/14/javascript_pong/demo.html (mas sem as opções extras, você pode clicar no lado esquerdo ou o quadro, fps etc. no canto inferior direito).

Como sempre, o código deve ser escrito em um idioma livre (em ambos os sentidos) e deve ser executável no linux. Todas as bibliotecas utilizadas também devem ser gratuitas, facilmente disponíveis e não devem ser escritas para os fins desta competição (e também não devem conter uma versão funcional do Pong!).

felipa
fonte
Honestamente, essa pergunta é um pouco difícil para o código de golfe. A física da bola para Pong é bastante complicada.
beary605
@ beary605, não acho que a física da bola seja muito complicada. Minha solução é 'o mais próximo possível' da demonstração de javascript, e a física é bastante simples.
usar o seguinte comando
Apenas para referência, existem outros [code-golf] s que duram bastante. Construa um mecanismo para um jogo de labirinto , Noughts and Crosses (também conhecido como Tic-Tac-Toe) (ambos podem usar entradas adicionais, que gostam de "vencer" por padrão?), Escreva um pequeno servidor HTTP , Interpretador de auto-interpretação , Auto- compilando compilador , Compile Regexes ...
dmckee
@felipa, você pode formalizar 'o mais próximo possível'? Não sei por que minha solução sed não está na liderança.
Boothby
1
@ beary605 muito difícil?
FantaC

Respostas:

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

O script pode ser colocado no final <body>ou chamado onLoad. Ele precisa do seguinte elemento de tela:

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

O jogador 1 usa as teclas qe a, e o jogador 2 usa as teclas pe l. Pressione a esctecla para pausar e qualquer tecla para iniciar / continuar.

Você pode reproduzi-lo no seu navegador aqui .

Eu não tinha certeza da física a usar, então comecei com um método simples de reflexão e depois adicionei alguma variedade e experimentei um pouco. A velocidade da bola na direção y é afetada por onde, na raquete, você bate na bola, para que você tenha algum controle sobre onde a bola vai. A velocidade da bola na direção x aumenta lentamente a cada golpe no rally.

Eu suspeito que ele será facilmente superado por soluções usando bibliotecas, mas me diverti fazendo isso em javascript simples.

grc
fonte
2
Essa é uma implementação muito boa.
felipa 12/03/2013
1
Poderia jogar um pouco mais, sei que estou com dois anos de atraso aqui. mas você pode atribuir 20a uma variável chamada ge salvar um byte mísero.
Zacharý
Porra, é difícil tocar em um teclado azerty ...
dim
38

sed, 35

Levantando um pouco a barra com uma meditação sediada em selos postais.

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

A meditação é apreciada no stdin / stdout em dois computadores, não necessariamente conectados por uma rede. A meditação começa no estado

0         <       1

com o guru zero à esquerda e um à direita. O colchete angular move-se para a esquerda e para a direita e, se um guru manobra seu número para entrar em contato com o cursor ao lado, sua pontuação é aumentada em um e eles ficam felizes com a alegria.

A meditação é iniciada digitando o estado acima sed -f medi.sede o computador responde com o próximo estado. Os gurus obedientes digitam a meditação, lendo em voz alta a próxima tecla que pressionarão, com os dois gurus pressionando a tecla sagrada para entero futuro ao mesmo tempo. O computador obediente responde com o próximo estado. Isso, por sua vez, é lido em voz alta enquanto digitado em uníssono, como no último. Continue avançando no futuro até que a felicidade infinita seja alcançada.

Os gurus que desejam um desafio podem jogar o modo 'turbo', em que os gurus tentam prever colaborativamente o próximo estado do computador e digitando-o no prompt, em vez do estado atual. Os gurus terão a sabedoria de verificar o acordo entre suas previsões antes de entrar no futuro.

boothby
fonte
23
Cara ... o que eu acabei de ler?
MrZander
9
@MrZander Somente através de ampla contemplação a sabedoria da meditação pode ser revelada. Essa contemplação é melhor auxiliada pela execução do programa.
usar o seguinte comando
15

Python (com pygame ) 650 bytes

Recursos

  • Modos de 1 e 2 jogadores - Quando o jogo começar, pressione 1para 1 jogador ou 22 jogadores. O jogo não começará até que uma dessas teclas seja pressionada.
  • Aumento da velocidade da bola - A cada voleio, a velocidade da bola aumenta para que, após 10 voleios, aumente em aproximadamente 50%, após 20 seja 50% mais rápido que isso, etc.
  • Deflexão variável da bola - A deflexão da bola é baseada em dois fatores: qual parte da raquete ela atinge e se a raquete está ou não se movendo com o impacto. Se a bola bater na raquete perto de uma das extremidades, ela será desviada mais fortemente do que se estiver perto do meio (quase como se fosse uma superfície curva). Além disso, se a raquete estiver em movimento, o movimento da raquete será adicionado à deflexão. Para obter a deflexão mais forte, a bola deve bater perto do final da raquete, e a raquete deve estar em movimento na mesma direção. Isso é muito semelhante ao Pong original para o Atari 2600.
  • Pausa - O jogo pode ser pausado a qualquer momento pressionando a Spacebarra. A reprodução será retomada ao pressionar a barra de espaço uma segunda vez.
  • Controles - como acontece com o exemplo, o Jogador 1 move-se com o Qe Achaves, e o jogador 2 se move com Pe L.

Como nota final, eu gostaria de solicitar que esta solução não seja selecionada como a resposta aceita, por vários motivos.

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 tela de amostra:

Nota: a fonte usada para a pontuação pode variar de sistema para sistema.

primo
fonte
Os shows de pontuação na metade esquerda para mim, e eu acho que a deflexão é muito forte, mas é muito legal de qualquer maneira :)
aditsu
@aditsu você está operando no linux? Vou ver se consigo encontrar uma alternativa que funcione independentemente da fonte selecionada. A idéia por trás da deflexão é que seria possível desviar a bola a uma velocidade mais rápida (máximo 2,5 na minha escala) do que a raquete pode se mover ( 1,67 ). Isso só é possível se você der um giro. Se a raquete não estiver se movendo quando a bola bater, a velocidade máxima será de 1,5 .
Primo
Sim, eu estou usando Linux. Acho estranho que a bola possa realmente "voltar" (para cima ou para baixo) depois de bater no remo, em vez de continuar na mesma direção (talvez em um ângulo diferente). Mas talvez a versão da Atari tenha feito isso, eu não sei.
Aditsu 14/03/2013
@aditsu Custa alguns bytes, mas acredito que a pontuação deve ser centralizada, independentemente da fonte escolhida (desde que seja monoespaçada). Deixe-me saber se funciona para você. E sim, a deflexão é muito semelhante (embora uma distribuição mais suave) à versão do Atari com a qual eu estava familiarizado. Se você imaginar a raquete como uma superfície curva (convexa) (como uma raquete de air hockey), acho que deve ser mais intuitivo.
Primo
Sim, agora está centralizado
aditsu 14/03/2013
8

HTML e JavaScript (versão 2) - 525

Como o OP não parecia se importar muito com a parte "o mais próximo possível", eis uma solução alternativa que simplifiquei, despojei e joguei sem piedade. Q / A e P / L para tocar, mas todas as outras teclas também têm efeito. Novamente, o código é totalmente independente e eu o testei no Chromium 25 no Linux. Posso jogar ainda mais se você puder aceitar pequenos erros ou maior degradação da qualidade / jogabilidade dos gráficos.

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

Obrigado Shmiddty

aditsu
fonte
Eu não entendo a objeção. Tanto quanto me lembro, a versão 715 byte (editado 3 horas antes deste post) é quase idêntico à versão original de Pong eu tinha para o meu Atari 2600.
primo
@primo Suponho que você esteja falando da minha alegação implícita de que sua solução não atende ao critério "o mais próximo possível". Bem, o OP não mencionou a versão do Atari 2600, mas uma implementação específica de javascript à qual ele se vinculou. E à primeira vista, existem duas diferenças gritantes no seu código: nenhum reprodutor de computador e nenhuma exibição de pontuação de "7 segmentos". Provavelmente existem muito mais diferenças na "mecânica". Se essas coisas não são importantes, acho que essa solução também deve ser válida.
Aditsu 13/03/2013
Este é o meu erro. Eu realmente quis dizer "o mais próximo possível", então sua primeira solução é a melhor até agora.
Felipa # 13/13
Você pode remover o c=window.c. Você está atribuindo uma variável global a si mesma.
21813 Shmiddty
Você pode economizar mais de 1 personagem movendo ++S[n]dentro.random(++S[n])
Shmiddty
5

HTML e JavaScript - 1663

Contra meu melhor julgamento, adotei a abordagem maluca de jogar o código real da demo. Eu removi alguns recursos e elementos da interface, mas geralmente funciona exatamente da mesma maneira - 0, 1 ou 2 para escolher o número de jogadores humanos, Q / A e P / L a serem movidos.

A menos que eu tenha cometido alguns erros, a jogabilidade deve ser idêntica, pixel por pixel e milissegundo por milissegundo, ao original em 640 * 480 (dica: redimensionar a janela do navegador altera o tamanho do jogo na demo). Apenas não dá instruções, não anuncia o vencedor e não lida com esc.

O código é totalmente independente e eu testei no Chromium 25 no Linux. O Firefox não gosta muito.

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

Alguns créditos para Shmiddty por melhorias

aditsu
fonte
4

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

Exemplo de captura de tela:

insira a descrição da imagem aqui

Esse código foi feito com a falta de atenção em mente, por isso é bastante complicado (a bola às vezes passa pela raquete ou envolve-a). Os controles são Q / A para o Player 1 e O / L para o Player 2.

segfaultd
fonte
1
Como jogo, sua versão do Pong também parece bastante injusta, pois apenas as chaves de um jogador são registradas por quadro: P
Jonathan Frech
2

C # - 1283 caracteres

Isso pode ser jogado um pouco mais, mas aqui 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);}}

Edit: Não viu o requisito para uma linguagem gratuita, executável em linux ...

Brandon
fonte
2

Tcl / Tk , 932 bytes

Deve ser executado no shell interativo

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

Apenas uma versão muito mínima do Pong, onde a bola corre apenas em ângulos diagonais e sempre tem a mesma velocidade.

insira a descrição da imagem aqui

sergiol
fonte
Outgolf com falha: bit.ly/2VSIGz8
sergiol 16/01