-
-
Save veu/603535c10c8516de15cb to your computer and use it in GitHub Desktop.
<body onload="function M(c,d){for(i=H=16;i--;G|=p>>11)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?p-q?0:h=c?0:B[p?S+=B[m]*=2:B[i++,m]=q,n]=d:L=localStorage:0;)R=Math.random}function V(x){if(x)return(D>1?4-x:x-1)<<D%2*2|i-i%4>>D%2*2;for(i=H|R()*H;B[--i%H];);B[i%H]=2<<R()+.1}(onkeyup=function(e){D=e?e.which-37:B=[];D>>2||M()|V(e?h:V());for(D=h=4;D--;)M(1);for(h=(G|h?S+' / '+(L.S>S?L.S:L.S=S):S)+'<table border>';H;P.innerHTML=h+='<th width=50 height=50>'+[B[H]])H--%4?0:h+='<tr>'})(S=G=0)"id=P> |
And remove the whitespace after the return to save another byte as @subzey suggested:
http://jsbin.com/MMXLVIII/6
https://twitter.com/subzey/status/453203401187553280
Couldn't we replace Math.random with new Date%9 or new Date%H ?
Had the same idea about Math.random
but it is used twice here and will be shorter is stored in a var.
PS: This is a more "readable" version of the 421 version:
<body id=P onload="function M(c,d){for(i=H=16;i--
;)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?!p|p==q
&&(h=c?0:B[p?B[m]*=2:B[i++,m]=q,n]=d):1:0;)R=Math
.random}function V(x){if(x)return(D>1?4-x:x-1)<<D
%2*2|i-i%4>>D%2*2;for(i=H|R(D=4)*H;B[--i%H];);for
(B[i%H]=h=2<<R()+.1;D--;)M(1)}(onkeyup=function(e
){D=e?e.keyCode-37:B=[];M()|V(e?h:V());t='<pre>';
for(i=h=H;i--;P.innerHTML=t)t+=(' '+[B[i]]).
slice(-4)+(i%4?'|':'|\n')})()">
Alright. Good work then!
BTW, I made this 446b variation freturing a table instead of ASCII ART:
<body id=P onload="function M(c,d){for(i=H=16;i--;)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?!p|p==q&&(h=c?0:B[p?B[m]*=2:B[i++,m]=q,n]=d):1:0;)R=Math.random}function V(x){if(x)return(D>1?4-x:x-1)<<D%2*2|i-i%4>>D%2*2;for(i=H|R(D=4)*H;B[--i%H];);for(B[i%H]=h=2<<R()+.1;D--;)M(1)}(onkeyup=function(e){D=e?e.keyCode-37:B=[];M()|V(e?h:V());t='<table border>';for(i=h=H;i--;P.innerHTML=t)t+=(!(i%4-3)?'<tr>':'')+'<th width=50 height=50>'+(B[i]||'')})()">
It's worth 25b, isn't it?
You mean 16b, right? ;)
<body onload="function M(c,d){for(i=H=16;i--;)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?!p|p==q&&(h=c?0:B[p?B[m]*=2:B[i++,m]=q,n]=d):1:0;)R=Math.random}function V(x){if(x)return(D>1?4-x:x-1)<<D%2*2|i-i%4>>D%2*2;for(i=H|R(D=4)*H;B[--i%H];);for(B[i%H]=h=2<<R()+.1;D--;)M(1)}(onkeyup=function(e,t){D=e?e.keyCode-37:B=[];M()|V(e?h:V());for(i=h=H;i--;)P.innerHTML=t=(i%4-3?t:[t]+'<tr>')+'<th width=50 height=50>'+[B[i]]})()"><table border id=P>
I'm not too sure, but it seems,
p==q&&(h=c?0:/*…*/)
might be replaced with
p==q?h=c?0:/*…*/:0
That's 1 byte less
<body id=P onload="…">
to <body onload="…"id=P>
yields 1 more byte
Also, could we possibly rely on tabstops (in ASCII version)? t+=[B[i]]+(i%4?'\t|':'\n')
is much shorter.
@subzey The first two optimizations are great but tabs look weird because they're 8 spaces and the numbers would be left-aligned.
Updated with xem's table version, subzey's optimizations and a few more optimizations of my own. It's now 507 bytes.
If you're really only interested in raw mechanics and don't care how ugly it looks you can get it down to 357b.
<body onload="function V(x){if(x)return(D>1?4-x:x-1)<<D%2*2|i-i%4>>D%2*2;for(i=H|R()*H;B[--i%H];);B[i%H]=2<<R()+.1}(onkeyup=function(e,d){D=e?e.keyCode-37:B=[];for(i=k=H=16;i--;)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?p&&p-q?0:h=B[p?B[m]*=2:B[i++,m]=q,n]=d:1:0;)R=Math.random;V(e?h:V());h='<pre>';for(;k--;)P.innerHTML=h+=[B[k]]+'\t|'+[k%4?d:'\n']})()"id=P>
Obviously this doesn't keep the score or detect game over either.
@veu: That's what I'm looking for! Great golfing by using tabs and reordering the attributes!
You can save a ;
by moving h='<pre>'
into the for
initialization: http://jsbin.com/MMXLVIII/8
The tabs were subzey's idea. :) I moved a couple more variables around to get it down to 353. http://jsbin.com/lugidoyo
/*...*/:1:0;L=localStorage)R=Math.random}
/*...*/:L=localStorage:0;)R=Math.random} // -1 byte
As far as I understand, 1
here stands for something truthy, and LocalStorage is a good pick if supported by browser. If it's not supported, ReferenceError, just like it was before. I'm pretty sure this "if branch" would be activated at least once before gameover when L
is needed.
353...
boy, that escalated quickly. great golf guys!
Great work guys!
But why not save two bytes by using .which
instead of .keycode
? That should work in all modern browsers: http://jsbin.com/MMXLVIII/12/ – 351 …
Some ideas, but no time to try them:
e.which-37
→e.which%4
- join the two
function
s - get rid of
"
by avoiding>
like here
I think, p&&
check in p&&p-q
is redundant.
If I understand right, p
is taken from B
array, whose values may be only positive integers or undefineds. Thus, the only "falsy" value is undefined that is coerced to NaN in p-q
and whole condition becomes falsy.
.which
may work, have to try later- Changing it to
e.which%4
would require changing the mapping and also means that all keys can be used which is kind of ugly (at least for the fully featured version). - Joining the two functions is likely not worth it because of longer calls and bytes needed for
if
/else
orif
andreturn
. - The quotes are only two bytes whereas replacing
>>
everywhere would likely generate many more bytes.
@subzey You're right about p&&p-q
but I'll have to check whether that breaks assumptions made in the code that follows. Not sure whether I can use it.
for(i=H;i--;/*...*/)~i%4?0:h+='<tr>'
for(i=H;i;/*...*/)i--%4?0:h+='<tr>' // -1 byte
Upd: There's more maniacal version:
for(;H;/*...*/)H--%4?0:h+='<tr>' // -4 bytes
Although global "constant" H is changed, it doesn't affect M()
and V()
as in M()
its value is reverted to 16 and V()
is always called after M()
.
Haha, that's crazy. It's now 499 bytes with everything.
EDIT: And here's the bare-bones version with all suggested optimizations at 346 bytes.
<body onload="function V(x){if(x)return(D%3?x-1:4-x)<<2-D%2*2|i/4<<D%2*2;for(h=H|R()*H;B[--h%H];);B[h%H]=2<<R()+.1}(onkeyup=function(e,d){D=e?e.which%4:B=[];for(i=H=16;i--;)for(p=B[m=V(j=i%4+1)];--j?(q=B[n=V(j)])?p-q?0:h=B[p?B[m]*=2:B[i++,m]=q,n]=d:R=Math.random:0;);for(V(e?h:V());H--;H%4?0:d+='\n')P.innerHTML=d=[d]+[B[H]]+'\t|'})()"><pre id=P>
@subzey I tried that before and it doesn't work. M
doesn't get called after the game's over leading to an infinite loop over the now always negative H
.
@veu, I've removed D>>2|G||
part and the code seems to be working correctly: http://jsbin.com/vigohuso/1/
@subzey That works if you don't care that any pressed key moves tiles and the game continues after reaching 2048. Btw, I found a way to use your output loop optimization and it's now 496 bytes.
Oh… Right, sorry.
Btw, original game doesn't end with 2048 tile, you may pick "continue playing" and try to get 4096 or 8192
In that case removing |G
might actually be closer to the original as it would update the highscore when you've reached the 2048 tile but would let you keep playing.
Use oninput
instead of onkeyup
. It’s not shorter but it feels much faster.
Let's golf this: http://243game.com/ :)
And somehow the Game-Over logic is broken. At least on Chrome / Mac here. But that's okay for me and in my opinion you could reduce the board even further by removing the score at all.
See: http://jsbin.com/MMXLVIII/5: That are 422 bytes - A beautiful 2k number!