どうもこんばんは。最近はチーム制作や個人制作のタスクが多くて忙しそうなワイルです。
1つのゲームを最後まで完成させるのはなかなか大変なこと。
やっぱりうまく仕事をこなすコツは息抜きや気分転換を大事にして、良い精神状態を保つことだと思うんだよね...。(サボりとか言わない)
精神状態が良くないと仕事も手につかないからね。僕の場合はいつもだけど。
で、ゲーム作りに飽きた(飽きてない)僕はふと思った。
「なんか単純なゲーム作りてえな、スライドパズルみたいな。」
と...。
いやいやいや、なんでゲーム制作の息抜きでゲーム制作をやるんだ!って突っ込まれそうだけど意外と上手くできたから今回はそんな話を書いていく。
まあ同じ作業を続けるのが疲れただけで、プログラミング自体は好きだからね。
ちなみに開発環境はUnityとC#。理由は楽だから。
◆簡単に作り方を考えてみる
今回作るのは4×4のマス内で1~15までの数字が書いてあるパネルを順番に並べていくタイプのやつ。15パズルとも呼ばれてるな。
・まず開始したら1~15までを完全ランダムに並べ替える。右下が空白なのは固定で。
・プレイヤー操作開始。十字キーで空白のマスに隣接してるパネルを動かせる。
・順番になるように並び替えられたらクリア。数秒経ったらまた新たなゲームが始まる。
この3ステップの処理だけ作ればいけるな。よし簡単...
...ではないんだよなぁ。
ここで僕は重大な事実を知ってしまった。
なんと、スライドパズルには絶対に解けないパターンが存在するらしい。
マジかよ。
それは「最後が15、14で並んでる状態」のように、隣接したパネルが1つだけ入れ替えられてしまったパターン。
完全ランダムに並べ替えるとすると、解けない問題が出てくる確率は1/2。なんとしてもこうならないようにしないとただのクソゲーになっちまうな。
簡単そうだからって理由だけで作り始めたけどなんだかんだでめんどくさくなってきたぞ。
そういうわけでめっちゃ調べたらいい感じの方法が分かってきたから試してみる。
まず1~15までの数字を一次元配列に格納してランダムに並び替えるぞ。
雑に描いたとか言わない。雑に描いたけど。
で、ランダムにしたら次に左から順番にその数字が正しい位置なのか判定していくんだって。
この図だと1番目は1で正しい。でも2番目は2じゃないから、2を探し出して持ってきてやる。
2を2マス動かした。この動かしたマスの数が大事!
次も同じ感じで3番目に3を持ってくる。
3を1マス動かした。ここまでの合計移動距離は3マス。
こんな感じで最終的に{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }の並びになるまで繰り返して、
合計移動距離が偶数なら解ける問題。
合計移動距離が奇数なら解けない問題。
らしいぞ!マジか。先人の知恵凄すぎるだろ。
これならプログラムで判定できそうだな、やってみるか。
◆処理を書いていく
並び替え処理。伝われ!!!
defaultkunってのはデフォルトの並びをリストにした見本のようなもの。デフォルトくんって安直すぎだろ...
このデフォルトくんの中からランダムで1つずつ選んでpositionっていう一次元配列に入れていく。これをfor文で15回分。
で、最後尾には0を入れておく。空白の部分だね。
そしたらpositionlistっていうリストを作ってそこにpositionの中身を全部入れる!理由は配列よりもリストをいじる方が楽だったから。プログラミングって8割は気分と気まぐれでできてる気がする。(だめだと思う。)
二重のfor文とか使ってさっき言ってた入れ替え処理を書く。
合計移動距離は突然出てきた変数countで数えるぞ。
countが偶数だったら配置開始して再処理フラグをfalse、奇数だったら再処理フラグをtrueにして、奇数の場合はもう一回最初っからやり直し。これで偶数が出ればゲームスタート!
途中でposっていう二次元配列にpositionの中身を入れ直してるけど、これもこっちの方が楽だからっていう理由。
二次元配列にすれば
{ 1, 2, 3, 4}
{ 5, 6, 7, 8}
{ 9, 10, 11, 12}
{ 13, 14, 15, 0}
こんな感じの並びの横と縦をそのままX座標とY座標で配置できるからね。
良い感じ!これでちゃんとクリア可能なパターンだけが出るようになったぜ!
しかしまだ動かないので入力処理も簡単に作る。
・下キーを押したとき、空白の上(一次元配列の空白から4つ前)にパネルがあったら空白と上のパネルを交換。
・上キーを押したとき、空白の下(一次元配列の空白から4つ後)にパネルがあったら空白と下のパネルを交換。
みたいな感じで、一次元配列positionの方を動かしていく。
理由はもちろん楽だから。
技術的にじゃなくて、僕が考えるのが。(おい)
で、一回のキー入力が終わったら一次元配列positionの変化を二次元配列posに反映して...
二次元配列posの変化をパネル側で座標に反映させる。
あらやだめんどくさいわね。なにこれ。
絶対もっといいやり方あるだろうし間違ってるところもあるかもしれないけど、とりあえず息抜きに作ったものだしちゃんと動いたからいいや。(いいのか?)
配列の変化を反映させてる都合上、移動アニメーション等は一切無い...。動いてる感がないのは寂しいけど、1マスの移動時間が約1フレームって考えるとめっちゃテンポサクサクだな!ぱぱーっと解ける。最高。
あとは仮で入れてた画像が雑すぎたから変更。
よし、動いた!
クリア判定の処理も作ったから、解き終わったら「完成!」の文字が表示されて次の問題を出してくれるぞ。これで永遠に遊べるな。永遠に終わらない悪夢。
◆感想的な何か
なんか...難しい話が多くなってしまって申し訳ない。
まあ要はあれだ、「作りたいゲームの抽象的なイメージだけ考えててもゲームは作れないから、どういう順序で処理していけばいいのかをよく考えて作り始めようね」ってことだな。(そんな話してたっけ?)
僕の学校は「授業中は自分で作ったゲーム以外のゲームを遊んではいけない」っていうすごくあたりまえなルールがあるんだけど、このスライドパズルなら授業中にどれだけ遊んでても怒られないな!いつかは飽きるだろうけど。
今回作ったゲームは一応配布とかしてみようかな。永遠にスライドパズルやるだけのゲームをやってみたい人がいたらやってみてね。↓
ということで今回はこの辺で。それではまた。