タイルを動かして、1-15の順番に並べるゲームで、各数字に割り当てるx座標y座標をMathfloorのwidth,heightで割って、配列しています。var moveCountの数字を動かすことによって、ゲームの難易度を変更します。
reference
clientX Property:returns the horizontal coordinate (according to the client area) of the mouse pointer when a mouse event was triggered.The client area is the current window.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>15puzzle</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> </style> </head> <body> <canvas id="stage" width="280" height="280"> Canvas not supported ... </canvas> <script> (function(){ 'use strict'; var canvas = document.getElementById('stage'); var context; var image; var IMAGE_URL = '15puzzle.png'; var tiles = []; var ROW_COUNT = 4; var COL_COUNT = 4; var PIC_WIDTH = 280; var PIC_HEIGHT = 280; var TILE_WIDTH = PIC_WIDTH / COL_COUNT; var TILE_HEIGHT = PIC_HEIGHT / ROW_COUNT; var UDLR = [ [ 0, -1], [ 0, 1], [ -1, 0], [ 1, 0], ]; var moveCount = 3; function initTiles(){ var row, col; for (row = 0; row < ROW_COUNT; row++){ tiles[row] = []; for (col = 0; col < COL_COUNT; col++){ tiles[row][col] = row * COL_COUNT + col; } } tiles[ROW_COUNT - 1][COL_COUNT - 1] = -1; } function drawPuzzle(){ var row, col; var sx, sy; var dx, dy; for (row = 0; row < ROW_COUNT; row++){ for (col = 0; col < COL_COUNT; col++){ dx = col * TILE_WIDTH; dy = row * TILE_HEIGHT; if (tiles[row][col] === -1){ context.fillStyle = '#eeeeee'; context.fillRect(dx, dy, TILE_WIDTH, TILE_HEIGHT); }else { sx = (tiles[row][col] % COL_COUNT) * TILE_WIDTH; sy = Math.floor((tiles[row][col] / ROW_COUNT)) * TILE_HEIGHT; context.drawImage(image, sx, sy, TILE_WIDTH, TILE_HEIGHT, dx, dy, TILE_WIDTH, TILE_HEIGHT); } } } /*context.drawImage(image, 0, 0);*/ } function checkResult(){ var row, col; for (row = 0; row < ROW_COUNT; row++){ for (col = 0; col < COL_COUNT; col++){ if (row === ROW_COUNT -1 && col === COL_COUNT -1){ return true; } if (tiles[row][col] !== row * COL_COUNT + col){ return false; } } } } function moveBlank(count){ var blankRow, blankCol; var targetPosition; var targetRow, targetCol; blankRow = ROW_COUNT -1; blankCol = COL_COUNT -1; while(true){ targetPosition = Math.floor(Math.random() * UDLR.length); targetRow = blankRow + UDLR[targetPosition][1]; targetCol = blankCol + UDLR[targetPosition][0]; if(targetRow < 0 || targetRow >= ROW_COUNT){ continue; } if(targetCol < 0 || targetCol >= COL_COUNT){ continue; } tiles[blankRow][blankCol] = tiles[targetRow][targetCol]; tiles[targetRow][targetCol] = -1; blankRow = targetRow; blankCol = targetCol; if(!--count){ break; } } } if (!canvas.getContext){ alert('canvas not supported ...'); return } context = canvas.getContext('2d'); image = document.createElement('img'); image.src = IMAGE_URL; image.addEventListener('load', function(){ initTiles(); moveBlank(moveCount); drawPuzzle(); }); canvas.addEventListener('click', function(e){ var x, y; var rect; var row, col; var i; var targetRow, targetCol; rect = e.target.getBoundingClientRect(); x = e.clientX - rect.left; y = e.clientY - rect.top; row = Math.floor(y / TILE_HEIGHT); col = Math.floor(x / TILE_WIDTH); if (tiles[row][col] === -1){ return; } for (i = 0; i < UDLR.length; i++) { targetRow = row + UDLR[i][1]; targetCol = col + UDLR[i][0]; if (targetRow < 0 || targetRow >= ROW_COUNT) { continue; } if (targetCol < 0 || targetCol >= COL_COUNT) { continue; } if (tiles[targetRow][targetCol] === -1) { tiles[targetRow][targetCol] = tiles[row][col]; tiles[row][col] = -1; drawPuzzle(); if (checkResult()){ alert('Game Clear!') } break; } } }); })(); </script> </body> </html>