- Author:
- Rebecca
- Twitter:
- @
- GitHub:
- Facebook:
- Google+:
- +
- Reddit:
- /r/
- Pouet:
- Website:
- 23inch.de
- Compo:
- classic
- Demo link:
- https://js1k.com/2010-first/demo/562
- Shortlink:
- https://js1k.com/562
- Blog post:
- please update here!
- Bytes:
- 1023
- Chars:
- 1023
- Submission
eval("eval(\"C=document.body.children[0];X=C.getContext(g='2d');o=C.onmousemoveLx=(qX|0)-kQ5;y=qY-w-1Q5;Gp-(p=x*8+y)){n=x/W|yQ3?0:P[M=s[p]];Na,0,1,1);C.height=w*10;C.width=D;X.font='14px Arial';FText('Score: '+S+' Best: '+((Y=localStorage).h|0),w,320);EaIa<7;V'#ccc',N0,288+a++,D,1))Ec in [2,OBlur=3])Gc|!a)JOColor=[V'#'+'0eb2290'.substr(BH,3),'#000'][c],BHRc!=(nRsHjM)RN(iQ3)*w+2+k-a,z*w+w+a,w,w)}};(C.onclickLGg){W=16;l=W*W;w=32;v=w*W;k=(D-v)Q1;BUEi=n=S=gKMath.random()*4+1|0}Gn){S+=n*n;JGsHjM)l-=2,BHIExIx<B.length;Zx+7]?x+=8:B.splice(x,8))Ei=g=1;i<8;i++)G!Za=i+x]RZb=a-1])Za]=Zb],Zb]=iIk=(D-x*4)Q1}sUPUJ{P[sH=i]IGa=BH)Eb=1;b<9;b+=7)G(bj1Rz||bj8&i>7)RZi-b]ja){gIc=s[i-b];Ed in s)Gc-iRs[d]jc)s[d]=sH,PH++}}Gg){S-=l;GS>(Y.h|0))Y.h=S;k=D-w*12Q1;EiK'@h\0Ph\0\x10x\0x P'.charCodeAt(iQ3)&(1<<(z))?(i-11?4:1):0}p=v;o(e)})(0)\"_zi%8_qe.page_j==_ZB[_VFStyle=_U=[];_R&&_Q>>_OX.shadow_NFRect(_L=function(e){_KIi<8*W;i++)BH=_JEi in B)_I=0;_H[i]_Gif(_FX.fill_Efor(_DinnerWidth)".replace(/_(\w)([^_]*)(?!$)/g,".replace(/$1/g,'$2')"))
- Description
- SameGame(http://en.wikipedia.org/wiki/SameGame)
The goal is to remove as many blocks as possible.
Displays score and persistent high score.
Click to start a new game.
Update: Fixed 3 bugs, added bigger board and game over screen.
- Base64 encoded
ZXZhbCgiZXZhbChcIkM9ZG9jdW1lbnQuYm9keS5jaGlsZHJlblswXTtYPUMuZ2V0Q29udGV4dChnPScyZCcpO289Qy5vbm1vdXNlbW92ZUx4PShxWHwwKS1rUTU7eT1xWS13LTFRNTtHcC0ocD14KjgreSkpe249eC9XfHlRMz8wOlBbTT1zW3BdXTtOYSwwLDEsMSk7Qy5oZWlnaHQ9dyoxMDtDLndpZHRoPUQ7WC5mb250PScxNHB4IEFyaWFsJztGVGV4dCgnU2NvcmU6ICcrUysnICBCZXN0OiAnKygoWT1sb2NhbFN0b3JhZ2UpLmh8MCksdywzMjApO0VhSWE8NztWJyNjY2MnLE4wLDI4OCthKyssRCwxKSlFYyBpbiBbMixPQmx1cj0zXSlHY3whYSlKT0NvbG9yPVtWJyMnKycwZWIyMjkwJy5zdWJzdHIoQkgsMyksJyMwMDAnXVtjXSxCSFJjIT0oblJzSGpNKVJOKGlRMykqdysyK2stYSx6KncrdythLHcsdyl9fTsoQy5vbmNsaWNrTEdnKXtXPTE2O2w9VypXO3c9MzI7dj13Klc7az0oRC12KVExO0JVRWk9bj1TPWdLTWF0aC5yYW5kb20oKSo0KzF8MH1Hbil7Uys9bipuO0pHc0hqTSlsLT0yLEJISUV4SXg8Qi5sZW5ndGg7WngrN10/eCs9ODpCLnNwbGljZSh4LDgpKUVpPWc9MTtpPDg7aSsrKUchWmE9aSt4XVJaYj1hLTFdKVphXT1aYl0sWmJdPWlJaz0oRC14KjQpUTF9c1VQVUp7UFtzSD1pXUlHYT1CSClFYj0xO2I8OTtiKz03KUcoYmoxUnp8fGJqOCZpPjcpUlppLWJdamEpe2dJYz1zW2ktYl07RWQgaW4gcylHYy1pUnNbZF1qYylzW2RdPXNILFBIKyt9fUdnKXtTLT1sO0dTPihZLmh8MCkpWS5oPVM7az1ELXcqMTJRMTtFaUsnQGhcMFBoXDBceDEweFwweCBQJy5jaGFyQ29kZUF0KGlRMykmKDE8PCh6KSk/KGktMTE/NDoxKTowfXA9djtvKGUpfSkoMClcIl96aSU4X3FlLnBhZ2Vfaj09X1pCW19WRlN0eWxlPV9VPVtdO19SJiZfUT4+X09YLnNoYWRvd19ORlJlY3QoX0w9ZnVuY3Rpb24oZSl7X0tJaTw4Klc7aSsrKUJIPV9KRWkgaW4gQilfST0wO19IW2ldX0dpZihfRlguZmlsbF9FZm9yKF9EaW5uZXJXaWR0aCkiLnJlcGxhY2UoL18oXHcpKFteX10qKSg/ISQpL2csIi5yZXBsYWNlKC8kMS9nLCckMicpIikp
- Original source
canvas = document.body.children[0];
context = canvas.getContext(end='2d'); // game ended -> setup new game
/// move handler (drawing)
onmove = canvas.onmousemove = function(e)
{
/// map to board
// x defaults to -offset/32 if dummy event supplied
x = (e.pageX|0)-offset >> 5;
y = e.pageY-w-1 >> 5;
// if block already selected
if(mousep-(mousep=x*8+y)) {
// get selection and selection size
// or default to none if pointer outside the board
numSel = x/W|y>>3 ? 0:selCount[selected=selections[mousep]];
/// clear canvas
// Setting size would be enough to redraw but bug 49151 makes chrome
// clear only the 'active rectangle'. Setting the height to 0 first
// would fix this but make ff and opera incredibly slow so the shortest
// workaround is to expand the active space by adding a zero-size square
// to the top which - according to the specification - 'has no effect'
// and make chrome clear everything. Oh boy.
// Update: Safari on the other hand respects the spec but not enough to
// redraw by itself so I actually had to give the rectangle a size of 1.
context.fillRect(a,0,1,1);
canvas.height = w*10;
canvas.width = innerWidth;
context.font = '14px Arial';
/// print score and high score
context.fillText('Score: '+score+
' Best: '+((Y=localStorage).h|0),w,320);
/// draw board
// 7 times for perspective
for(a=0; a<7; context.fillStyle = '#ccc',context.fillRect(0,288+a++,innerWidth,1))
// c=0 => selected, c=1 => other
for(c in [2,context.shadowBlur=3])
// draw selected only once for flat effect
if(c|!a)
for(i in board)
// hint: colors are interlaced
context.shadowColor = [context.fillStyle='#'+'0eb2290'.substr(board[i],3),'#000'][c],
board[i] && c!=(numSel&&selections[i]==selected) && context.fillRect((i>>3)*w+2+offset-a,i%8*w+w+a,w,w)
// draw separator (see loop head)
}
};
/// click handler (game logic)
(canvas.onclick = function(e)
{
/// setup new game
if(end) {
// board width in blocks
W = 16;
// blocks left * 2
left = W*W;
// block size
w = 32;
// displayed board width
v = w*W;
// offset to center the board
offset = (innerWidth-v) >> 1;
/// setup board, #selected, score, game over
board = [];
for(i=numSel=score=end=0; i<8*W;i++)
board[i] = Math.random()*4+1|0
}
/// do move
if(numSel) {
// update score: (n-1)^2 for n blocks
score += numSel*numSel;
/// remove selected blocks
for(i in board)
if(selections[i]==selected)
left -= 2,
board[i] = 0;
/// block propagation
for(x=0; x<board.length; board[x+7]?x+=8:board.splice(x,8))
/// vertical
for(i=end=1; i<8; i++)
if(!board[a=i+x] && board[b=a-1])
board[a] = board[b],
board[b] = i = 0;
// horizontal (see loop head)
// count remaining columns for offset
offset = (innerWidth-x*4) >> 1
}
/// generate selections equivalence relation
// equivalence classes
selections = [];
// class sizes
selCount = [];
for(i in board) {
selCount[selections[i] = i] = 0;
if(a=board[i])
/// check top and left neighbour
for(b=1; b<9; b+=7)
if((b==1 && i%8 || b==8 & i>7) && board[i-b]==a) {
// game not finished
end = 0;
/// join classes of i and i-b
c = selections[i-b];
for(d in selections)
if(c-i && selections[d]==c)
selections[d] = selections[i],
selCount[i]++
}
}
if(end) {
// add game end score: -blocks*2
score -= left;
// update high score
if(score>(Y.h|0)) Y.h = score;
/// create nice game over screen
offset = innerWidth-w*12 >> 1;
for(i=0; i<8*W; i++)
// finish the game to see what's been encoded here ;)
// \x10 is escaped to avoid binary data
board[i] = '@h\0Ph\0\x10x\0x P'.charCodeAt(i>>3)&(1<<(i%8)) ? (i-11?4:1):0
}
/// mark next blocks immediately
mousep = v;
onmove(e)
})(0) // pass dummy event