g | x | w | all
Bytes Lang Time Link
314TIBASIC TI83 Plus250529T141640Zmadeforl
326TIBasic210624T130112ZMarcMush
650Python 2 with pygame130312T120449Zprimo
335K oK + iKe210623T163303ZRazetime
932Tcl/Tk171126T120849Zsergiol
1283C#141209T143932ZBrandon
487Processing141203T211255Zsegfault
035sed130308T042915Zboothby
1663HTML & JavaScript130311T173506Zaditsu q
525HTML & JavaScript take 2130312T203935Zaditsu q
nanJavascript130308T062821Zgrc

TI-BASIC (TI-83 Plus), 314 bytes

This one is pushing the limit a little, and is pretty bare-bones.

credits to MarcMush's answer in the same language for giving me ideas and being a super cool person who also code golfs in TI-BASIC

AxesOff
0→Xmin:0→Ymin
10→L
ΔY→W
9→E
9→F
-2→G
G→H
1→Z
1→S
Vertical 5
Line(0,B,0,B+2
Line(L,A,L,A+2
Pt-On(E,F
While 1
getKey→θ
If θ=25
-Z→Z
If θ=72
-S→S
Pt-Off(0,B+2(Z<0
Pt-On(0,B+2(Z=1
B+WZ→B
Pt-Off(L,A+2(S<0
Pt-On(L,A+2(S=1
A+WS→A
Pt-Change(E,F
If F≤0 or F>9
-H→H
If (E≤0 and F-B<2 and F-B>0) or (E≥L and F-A<2 and F-A>0
-G→G
E+GΔX→E
F+HW→F
Pt-Change(E,F
If E<-1 or E>L
Then
D+(E<-1→D
C+(E>L→C
randInt(4,7→E
randInt(4,7→F
Text(1,43,C,":",D
Pt-On(E,F
End
End

Each player uses one button each, to switch direction of the paddle. It is constantly moving

It works a bit the same as MarcMush's, and since I can't get a GIF of it, just take my word for it or put it in your own calculator.

TI-Basic, 328 326 bytes

AxesOff:ZInteger:GridOn
99→Xscl:2→Yscl:1→U:1→V
Pt-Change(0,0
Line(Xmin,0,Xmin,9
Line(Xmax,0,Xmax,9
While 1
If 30≤abs(Y
-V→V
Pt-Change(X,Y
If X≥46:Then
If Y≥E and Y≤E+9:Then
-U→U
Else
IS>(A,9
X-90→X
End
End
If X≤-46:Then
If Y≥D and Y≤D+5:Then
-U→U
Else
IS>(B,9
X+90→X
End
End
If 9<max(A,B
Stop
X+U→X:Y+V→Y
Pt-Change(X,Y
Text(1,43,A,":",B
getkey→G
If G=21
1→I
If G=41
-1→I
If G=25
1→J
If G=34
-1→J
I(G≠31→I
J(G≠26→J
D+I→D:E+J→E
For(θ,-1,9,10
Pt-Change(Xmin-not(I),D+θ-I/2
Pt-Change(Xmax+not(J),E+θ-J/2
End
End

This program is very basic (constant speed and angles) but since there's is no precise specifications, the strict minimum will do

Since a long press is not detectable (or 2 keys pressed at the same time), an extra key is used to stop the movement of the racket

Here is the result at ~5x speed:

program demo

Python 2 (with pygame) 650 bytes

Features

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

cmp is no longer defined in Python 3. The code above can be made Python 3 compatitble by prepending the following:

def cmp(a, b):
  return (a>b)-(a<b)

Sample screen capture:

Note: the font used for the score may vary from system to system.

K (oK) + iKe, 393 335 bytes

q:p:-15+h%2
d:w,h
b:-2+d%2
v:5 -1
s:t:0
tick:{b::v+0|d&b
$[$[0>*b;t+::1;w<*b;s+::1;0];b::-2+d%2;0]
v*::$[(&/(b>(0;p-5))&b<(10;p+30))|&/(b>(w-15;q-5))&b<(w;q+30);-1;1],1}
draw:{((;gray);(((0;p);(w-5;q));;30 5#1);(b;;5 5#1);((w%4;0);;~,/'+text(),$t);((-10+3*w%4;0);;~,/'+text(),$s))}
kd:{$[x=81;p-::5;x=65;p+::5;x=80;q-::5;x=76;q+::5;0]}

Try it online!

My first K answer!

Was really fun to do in K. Kinda sad that the question spec isn't too specific about the implementation.

This answer has points based scoring, involves two players and no AI.

Tcl/Tk, 932 bytes

Must be run in the interactive shell

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 .

Note:

 #There is an Enter at the end

Just a very minimal version of Pong, where the ball only runs in diagonal angles and always has same velocity.

enter image description here

C# - 1283 characters

This can be golfed quite a bit more but here it is.

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: Didn't see the requirement for a free, linux-runnable language...

Processing, 487 characters

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

Sample screenshot:

enter image description here

This code was made with shortness in mind, so it is pretty buggy (the ball sometimes goes through the paddle, or wraps around it). Controls are Q/A for Player 1 and O/L for Player 2.

sed, 35

Raising the bar a bit with a postage-stamp sed meditation.

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

The meditation is enjoyed on stdin/stdout on two computers, not necessarily connected by a network. The meditation begins in the state

0         <       1

with guru zero on the left and one on the right. The angle bracket moves left and right, and if a guru maneuvers their number to contact the cursor as it comes to their side, their score is increased by one, and they become elated with joy.

The meditation is initiated by typing the above state into sed -f medi.sed, and the computer responds with the next state. The dutiful guru types that state into the meditation, reading aloud the next key they will press, with both gurus pressing the holy key to enter the future at the same time. The dutiful computer replies with the next state. This, in turn, is read aloud while typed in unison as with the last. Continue advancing into the future until infinite bliss is achieved.

Gurus desiring a challenge may play 'turbo' mode, wherein the gurus attempt to collaboratively predict the computer's next state, and typing it into the prompt instead of the current state. Gurus will have the wisdom to verify agreement between their predictions before entering the future.

HTML & JavaScript - 1663

Against my better judgment, I took the crazy approach of golfing the actual code from the demo. I removed some features and interface elements, but generally it works exactly the same - 0, 1 or 2 to choose the number of human players, Q/A and P/L to move.

Unless I made some mistakes, gameplay should be identical, pixel for pixel and millisecond for millisecond, to the original at 640*480 (hint: resizing the browser window changes the game size in the demo). It just doesn't give instructions, doesn't announce the winner and doesn't handle esc.

The code is fully self-contained and I tested it in Chromium 25 on Linux. Firefox doesn't like it very much.

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

Some credits to Shmiddty for improvements

HTML & JavaScript (take 2) - 525

Since the OP didn't seem to care much about the "as close as possible" part, here's an alternative solution that I mercilessly simplified, stripped and golfed. Q/A and P/L to play, but every other key also has an effect. Again, the code is fully self-contained and I tested it in Chromium 25 on Linux. I can golf it even further if you can accept small bugs or greater degradation of graphics quality/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>

Thanks Shmiddty

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

The script can be placed at the end of <body> or called onLoad. It needs the following canvas element:

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

Player 1 uses the q and a keys, and player 2 uses the p and l keys. Press the esc key to pause and any key to start/continue.

You can play it in your browser here.

I wasn't sure of the physics to use, so I started off with a simple reflection method and then added some variety and experimented with it a bit. The ball's velocity in the y direction is affected by where on the paddle you hit the ball, so you have some control over where the ball goes. The ball's velocity in the x direction slowly increases with each hit in the rally.

I suspect that it will be beaten quite easily by solutions using libraries, but I had fun making it in plain javascript.