RPGツクールMZ脱出ゲーム(スライドパズル)

左の図は空白のピースと隣り合った数字のピースはスライドさせる事が出来ます。
上手くスライドさせていって右の図と同じ配置にすればクリアです!

何か不都合があった場合はそっと上部に設置してありますリセットボタンを押して下さい…。

【スライドパズルの作り方】
Image

マップのどこでも良いので正解の座標の配置、座標を配置するスクリプトを設置します。

自動実行→セルフスイッチONでゲーム開始時に1回だけ起動させるようにします。

// 正解の座標の配列を変数に入れる
const correct = [
[1のx座標, 1のy座標],[2のx座標, 2のy座標],[3のx座標, 3のy座標],
[4のx座標, 4のy座標],[5のx座標, 5のy座標],[6のx座標, 6のy座標],
[7のx座標, 7のy座標],[8のx座標, 8のy座標],[空白のx座標, 空白のy座標]
];
$gameVariables.setValue(1, correct);

// シャッフル関数
function shuffle(array) {
const newArray = array.slice();
for (let i = newArray.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[newArray[i], newArray[j]] = [newArray[j], newArray[i]];
}
return newArray;
}

// 解決可能かどうか判定する関数
function isSolvable(puzzle) {
let inversions = 0;

// 空白(9)を除外
const flatPuzzle = puzzle.filter(num => num !== '9');

for (let i = 0; i < flatPuzzle.length; i++) {
for (let j = i + 1; j < flatPuzzle.length; j++) {
if (parseInt(flatPuzzle[i]) > parseInt(flatPuzzle[j])) {
inversions++;
}
}
}
return inversions % 2 === 0;
}

// メインの処理
let coordinate;
do {
coordinate = shuffle(['1', '2', '3', '4', '5', '6', '7', '8', '9']);
} while (!isSolvable(coordinate));

// 座標を配置する
for (let i = 0; i < 9; i++) {
const eventId = parseInt(coordinate[i]);
$gameMap.event(eventId).setPosition(correct[i][0], correct[i][1]);

// 空白(9)の位置を記録
if (coordinate[i] === '9') {
$gameVariables.setValue(変数ID, correct[i][0]); // 空白X位置
$gameVariables.setValue(変数ID, correct[i][1]); // 空白Y位置
}
}

Image
↑正解の座標を入れる際、「4,6」の数字が書いてある辺りにイベント毎の座標が書いてあると思います。

シャッフル部分ですが、スライドパズルは単純なランダム配置ではパズルが解けないようになってしまう場合があるので色々複雑な計算をして行きます…!
(数学的な話になるので興味のある方は検索して下さい)

そして座標の配置は

coordinate = shuffle(['1', '2', '3', '4', '5', '6', '7', '8', '9']);

の数字がそのままイベントIDの数字とリンクしていますので変更のある場合はこちらを変更下さい。

Image

次に各ピースのイベントにスクリプトを設置します。

// イベントIDを取得
const nam = $gameMap.event(番号のイベントID).eventId()

// ピースの位置を取得
const pieceX = this.character(nam).x;
const pieceY = this.character(nam).y;

// 空白ピースの位置を変数から取得
const emptyX = $gameVariables.value(変数ID);
const emptyY = $gameVariables.value(変数ID);

// 移動可能かどうかの判定
const canMove = (Math.abs(pieceX - emptyX) + Math.abs(pieceY - emptyY)) === 1;

if (canMove) {
// ピースの位置を空白の位置と交換
$gameVariables.setValue(変数ID, pieceX);
$gameVariables.setValue(変数ID, pieceY);
  
// ピースを移動
this.character(nam).setPosition(emptyX, emptyY);
this.character(空白のイベントID).setPosition(pieceX, pieceY);
}

1番のピースには1番のイベントID、2番のピースには2番のイベントID…と言うように全ての番号のイベントにスクリプトを設置しておきます。
(空白は空のイベントを設置しています)

Image

次に鉄格子のイベントにスクリプトを設置します。

// 現在の座標リストを作成し、配列に保存する
let coordinate = [];
for (let i = 開始するイベントID; i <= 9; i++) {
coordinate.push([$gameMap.event(i).x, $gameMap.event(i).y]);
}

// 正解の配列とプレイヤーが完成させた配列を判定
if ($gameVariables.value(変数ID).toString() == coordinate.toString()) {
$gameSwitches.setValue(スイッチID, true); 
} else {
$gameMessage.setFaceImage("指定したファイル", 番号)
$gameMessage.setSpeakerName("名前")
$gameMessage.add("パズル未完成のセリフ");
}

左の図と右の図が同じだったらスイッチを押して2ページ目のエンディングページに飛ばして完成です!

コメント