15 PUZZLE Ver.1.01(ちょっと手直し)

20131111

ゲームクリア後に原画を3秒だけ表示するようにしてみました。

3秒経過後は、ポップアップを表示します。

PCのブラウザ(Firefox)で表示するとこんな感じ。

右の画像をクリックすると実際のゲームページを開きます。



また、画像を5つ増やしました。以下の10個からランダム選択となります。

<!doctype html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<title>15パズル</title>
	<meta name="viewport" content="width=600">
	<link rel="stylesheet" type="text/css" href="../css/15-puzzle.css">
	<script type="text/javascript" src="../js/15-puzzle101.js">
	</script>
</head>
<body onload="init()">
	<h1>15 PUZZLE</h1>
	<canvas id="gameCanvas" width="600" height="600"></canvas>
</body>
</html>

// 各種設定
var PICTURES = ["nobana.jpg", "risu.jpg", "matterhorn.jpg", "beach.jpg", "foods.jpg","Blue_Moon.jpg","golden_gate_bridge.jpg","orgel.jpg","rose.jpg","sweets.jpg"];
var PICTURE_URL = "nobana.jpg";	// 画像ファイルのURL
var BLOCK_W = 150;	// ブロックの幅
var BLOCK_H = 150;	// ブロックの高さ
var ROW_COUNT = 4;	// 列を何枚に切るか
var COL_COUNT = 4;	// 行を何枚に切るか
var NUM_BLOCKS = ROW_COUNT * COL_COUNT;
// 上下左右の相対座標を定義したもの
var UDLR = [[0,-1],[0,1],[-1,0],[1,0]];
// ゲーム全体で使う変数
var context, image;	// 描画用
var blocks = [];	// 各ブロックを管理する配列変数
var isLock;	// マウス操作をロックするかどうか

// 初期化処理
function init() {
	// 描画コンテキストの取得
	var canvas = document.getElementById("gameCanvas");
	if (!canvas.getContext) {
		alert("Canvasをサポートしていません。");
		return;
	}
	context = canvas.getContext("2d");
	// マウスイベントの設定
	canvas.onmousedown = mouseHandler;
	// 画像を選択
	selectImage();
};

// 画像をランダムに選択
function selectImage() {
	r = Math.floor(Math.random() * PICTURES.length);
	PICTURE_URL = PICTURES[r];
	// メイン画像を読み出す
	image = new Image();
	image.src = PICTURE_URL;
	image.onload = initGame;	// 読み込んだらゲームを初期化
}

// ゲームの初期化
function initGame() {
	isLock = true;	// ユーザ操作をロックする
	// パズルのブロックを作成する
	for (var i = 0; i < NUM_BLOCKS; i++) {
		blocks[i] = i;
	}
	// 末尾(右下)を空きブロックとする
	blocks[NUM_BLOCKS -1] = -1;
	drawPuzzle();	// 見本を表示する
	// 1秒後にシャッフルを開始する
	setTimeout(shufflePuzzle,1000);
}
// パズルの各ピースをシャッフルする
function shufflePuzzle() {
	var scount = 160;	// シャッフルする回数を指定
	var blank = NUM_BLOCKS - 1;	// 空きブロック位置
	// 一回のみシャッフルを行う関数
	var shuffle = function () {
		scount--;
		if (scount <= 0) {
			isLock = false;	// ゲーム開始
			return;
		}
		var r, px, py, no;
		while (1) {
			r = Math.floor(Math.random() * UDLR.length);
			px = getCol(blank) + UDLR[r][0];
			py = getRow(blank) + UDLR[r][1];
			if (px < 0 || px >= COL_COUNT) continue;
			if (py < 0 || py >= ROW_COUNT) continue;
			no = getIndex(px, py);
			break;
		}
		blocks[blank] = blocks[no]
		blocks[no] = -1;
		blank = no;
		drawPuzzle();
		setTimeout(shuffle, 10);
	};
	shuffle();
}
// パズルの画面を描画する
function drawPuzzle() {
	for (var i = 0; i < NUM_BLOCKS; i++) {
		// 描画先座標を計算
		var dx = (i % COL_COUNT) * BLOCK_W;
		var dy = Math.floor(i / COL_COUNT) * BLOCK_H;
		// 描画元座標を計算
		var no = blocks[i];
		if (no < 0) {	// 空きブロック
			context.fillStyle = "#0000FF";
			context.fillRect(dx, dy, BLOCK_W, BLOCK_H);
		} else {
			var sx = (no % COL_COUNT) * BLOCK_W;
			var sy = Math.floor(no / COL_COUNT) * BLOCK_H;
			// 画像の一部を切り取って描画
			context.drawImage(image, sx, sy, BLOCK_W, BLOCK_H, dx, dy, BLOCK_W, BLOCK_H);
		}
		// 描画の枠を表示
		context.beginPath();
		context.strokeStyle = "white";
		context.lineWidth = 3;
		context.rect(dx, dy, BLOCK_W, BLOCK_H);
		context.stroke();
		context.closePath();
		// ブロック番号を描画する
		context.fillStyle = "rgba(255, 255, 255, 0.8)";
		context.font = "bold 48px Arial";
		var cx = dx + (BLOCK_W - 40) / 2;
		var cy = dy + BLOCK_H /2;
		context.fillText((no+1), cx, cy);
		context.strokeStyle = "black";
		context.strokeText((no+1), cx, cy);
	}
}
// マウスで移動先をクリックした時の処理
function mouseHandler(t) {
	if (isLock) return;
	// タッチ座標の取得
	var px = t.offsetX, py = t.offsetY;
	if (px == undefined) {	// FireFox対策
		var p = t.currentTarget;
		px = t.layerX - p.offsetLeft;
		py = t.layerY - p.offsetTop;
	}
	// 何番目のピースを動かしたいのか計算する
	var px2 = Math.floor(px / BLOCK_W);
	var py2 = Math.floor(py / BLOCK_H);
	var no = getIndex(px2, py2);
	// 空白ブロックなら動かせない
	if (blocks[no] == -1) return;
	// 上下左右に動かせるブロックがあるか確認
	for (var i = 0; i < UDLR.length; i++) {
		var pt = UDLR[i];
		var xx = px2 + pt[0];
		var yy = py2 + pt[1];
		var no = getIndex(xx, yy);
		if (xx < 0 || xx >= COL_COUNT) continue;
		if (yy < 0 || yy >= ROW_COUNT) continue;
		if (blocks[no] == -1) {	// 移動可能か
			blocks[no] = blocks[getIndex(px2,py2)];
			blocks[getIndex(px2,py2)] = -1;
			drawPuzzle();
			checkClear();
			break;
		}
	}
}
// クリアしたかどうかチェックする
function checkClear() {
	var flag = true;
	for (var i = 0; i < (NUM_BLOCKS -1); i++) {
		if (blocks[i] != i) { flag = false; break; }
	}
	if (flag) {
		context.drawImage(image, 0, 0);	// 元画像を描画する
		setTimeout('msgdsp()', 3000);	//3秒後にゲームクリア表示
	}
}

function msgdsp() {
	alert("ゲームクリアしました!");
	selectImage();	// 再度ゲームを実行
}

// 列と行からブロック番号を調べる関数
function getIndex(col, row) {
	return row * COL_COUNT + col;
}
function getCol(no) { return no % COL_COUNT; }
function getRow(no) {
	return Math.floor(no / COL_COUNT);
}

* {
	padding:0;
	margin:0;
	text-align:center;
}

h1 {
	background-color:blue;
	color:white;
	font-size:20px;
	padding:4px;
}