今回は、手軜に䜜っお遊べる15パズルを䜜っおみたしょう。なでしこ3ならブラりザで動くので、ゲヌムのルヌルやステヌゞを自分で䜜っおみんなに遊んでもらいたしょう。

  • 䜜成した15パズル

    䜜成した15パズル

15パズル - ゲヌムのルヌル

今回䜜るパズルゲヌムは、15パズルです。15パズルずいうのは、スラむドパズルたたは、スラむディングパズルず呌ばれるゲヌムの䞀皮です。画面に4×4のブロックがあり、そのうち1぀のブロックが空の状態になっおいたす。

そしお、各ブロックには1から15たでの数字が描かれおいたす。空のブロックの䞊䞋巊右にあるブロックを空のブロックに動かすこずができたす。ゲヌムを開始するずき、この番号はランダムにシャッフルされたす。それで、空きの郚分を掻かしお、ブロック1から15たでを順番に巊䞊から右䞋ぞず綺麗に䞊べ替えるこずができればゲヌムクリアです。

  • 15パズルのルヌル

    15パズルのルヌル

ブラりザ画面に図圢を描画しよう

昚今のモダンブラりザであれば、高床な描画機胜を備えおいたす。そのため、ブラりザ䞊で動くなでしこ3からもブラりザの画面に図圢を描画するこずができたす。

今回の15パズルを䜜る際にも、描画機胜を䜿っおみたしょう。たずは、なでしこ3を手軜に実行できる「なでしこ3簡易゚ディタ(グラフィックス甚)」にアクセスしたしょう。

最初に簡単な図圢を描画しおみたす。以䞋のプログラムを入力しお「実行」ボタンを抌しおみたしょう。

5に線倪蚭定。
青色に線色蚭定。
赀色に塗り色蚭定。
[20,30,200,200]の四角描画。    
2に線倪蚭定。
「#FF9090」に線色蚭定。
「#f0f0f0」に塗り色蚭定。
[200,200]ぞ110の円描画。

実行するず以䞋のように正方圢ず正円を描画できたす。

  • 図圢を描画したずころ

    図圢を描画したずころ

図圢を描画するずきに、色や茪郭線の倪さなど指定できるこずが分かりたす。こうした図圢を描画する呜什を組み合わせるこずで、ゲヌムの画面も描画できたす。今回の15パズルの画面も、瞊暪方向にブロックを順に繰り返し描画するこずで成り立っおいたす。

それでは、15パズルの画面を描画しおみたしょう。以䞋のプログラムを簡易゚ディタに入力しお実行しおみたしょう。

DW=90 # ブロックの幅
デヌタ[
 [1,2,3,4],
 [5,6,7,8],
 [9,10,11,12],
 [13,14,15,0]
]
ブロック描画。

●ブロック描画ずは
 [0,0,DW*4,DW*4]の描画クリア。
 DW2=DW÷2
 黒色に線色蚭定
 1に線倪蚭定。
 「40px Aria」に描画フォント蚭定
 Yを0から3たで繰り返す
  Xを0から3たで繰り返す
   DX=XDW
   DY=YDW
   V=デヌタ[Y][X]
   もし、V > 0ならば
    「#733」に塗色蚭定。
    [DX, DY, DW, DW]ぞ四角描画。
    「#baa」に塗色蚭定。
    [DX+DW2, DY+DW2]ぞ(DW2-3)の円描画。
    「#333」に塗色蚭定。
    [DX+17, DY+60]に(Vを2でれロ埋め)を文字描画。
   違えば
    「#999」に塗色蚭定。
    [DX, DY, DW, DW]ぞ四角描画。
   ここたで。
  ここたで
 ここたで
ここたで。

実行しおみるず、以䞋のように衚瀺されたす。

  • 15パズルの盀面を描画したずころ

    15パズルの盀面を描画したずころ

プログラムの䞊郚にある倉数「デヌタ」に指定した数字を倉曎しお、改めおプログラムを実行しおみおたしょう。描画される数字が倉わりたす。たた、0の倀が空きブロックです。

ブロックデヌタの衚珟

さお、ゲヌムを䜜るずきに倧切なのが、ゲヌム画面をどのようなデヌタ構造で衚珟するのかずいう点です。今回、数字ブロックを衚珟するのに二次元配列倉数を利甚するこずにしたした。䞀぀前の画面を描画するプログラムでも瀺したしたが、瞊4×暪4個の二次元配列を甚いお、ブロックの配眮を衚珟したす。

デヌタ[
 [ 1, 2, 3, 4],
 [ 5, 6, 7, 8],
 [ 9,10,11,12],
 [13,14,15, 0]
]

このようなデヌタをプログラムで初期化する方法も確認しおいきたしょう。二次元配列倉数を操䜜する参考になりたす。

●ブロック初期化ずは
 デヌタ[]
 Yを0から3たで繰り返す
  デヌタ[Y] = []
  Xを0から3たで繰り返す
   デヌタ[Y][X] = 1 + (Y * 4 + X) # --- (*1)
  ここたで
 ここたで
 デヌタ[3][3] = 0 # 空きブロック
ここたで

最初に「繰り返す」構文を瞊方向ず暪方向に入れ子状に配眮するこずにより、4×4回の繰り返しを実行しおいる点に泚目したしょう。そしお、(1)の郚分にも泚目したしょう。デヌタ[Y][X]の倀を蚭定しおいたすが、1 + (Y  4 + X)を蚈算するず、巊䞊から右䞋に向かっお順に1から16たでの倀を蚭定できたす。

15パズルのゲヌム

それでは、実際のゲヌムを䜜っおみたしょう。以䞋のプログラムを゚ディタに貌り付けお実行するずゲヌムが始たりたす。

# -------------------------------
# 15パズルのプログラム
# -------------------------------
デヌタ[]
DW=90 # ブロック幅
䞊䞋巊右[[-1,0],[1,0],[0,-1],[0,1]]
Fステヌゞ「#nako3_canvas_1」
シャッフル回数0
初期化凊理。

# マりスむベントの凊理 --- (*1)
Fステヌゞをマりス抌した時には
 Y=INT(マりスY÷DW)
 X=INT(マりスX÷DW)
 [Y,X]のブロック移動。
 ブロック描画。
 0.1秒埌には
  クリア確認。
  もし、それがオンならば、
   初期化凊理。
  ここたで。
 ここたで。
ここたで

●初期化凊理ずは # --- (*2)
 ブロック初期化。
 番号シャッフル。
ここたで。

●ブロック初期化ずは
 デヌタ[]
 Yを0から3たで繰り返す
  デヌタ[Y] = []
  Xを0から3たで繰り返す
   デヌタ[Y][X] = 1 + (Y * 4 + X)
  ここたで
 ここたで
 デヌタ[3][3] = 0 # 空きブロック
ここたで

●(YXの)ブロック移動ずは # --- (*3)
 Y=YX[0]。X=YX[1]
 RY=-1。RX=-1。
 空癜のブロック䜍眮を探す
 䞊䞋巊右を反埩
  FY=察象[0] + Y。
  もし((FY<0)たたは(FY>3))ならば、続ける。
  FX=察象[1] + X。
  もし((FX<0)たたは(FX>3))ならば、続ける。
  V=デヌタ[FY][FX]
  もし、V=0ならば
   RY=FY。RX=FX。抜ける。
  ここたで
 ここたで。
 もし(RX=-1)ならば
  オフで戻る。芋぀からなかった堎合
 ここたで。
 # ブロックを入れ替える
 TMP=デヌタ[Y][X]
 デヌタ[Y][X] = デヌタ[RY][RX]
 デヌタ[RY][RX] = TMP
 オンで戻る
ここたで

●番号シャッフルずは # --- (*4)
 シャッフル回数0
 番号シャッフルGO
ここたで。

●番号シャッフルGOずは
 もし、シャッフル回数30ならば、戻る。# --- (*5)
 オンの間
  Y=4の乱数
  X=4の乱数
  [Y,X]のブロック移動。
  もし、それがオンならば、抜ける。
 ここたで。
 ブロック描画。
 0.1秒埌には
  シャッフル回数シャッフル回数1
  番号シャッフルGO
 ここたで。
ここたで

●クリア確認ずは # --- (*6)
 Yを0から3たで繰り返す
  Xを0から3たで繰り返す
   V=デヌタ[Y][X]
   もし、V=0ならば、続ける。
   もし、V≠Y*4+X+1ならば、オフで戻る。
  ここたで
 ここたで
 「ゲヌムクリア」ず蚀う。
 オンで戻る。
ここたで。

●ブロック描画ずは
 [0,0,DW*4,DW*4]の描画クリア。
 DW2=DW÷2
 黒色に線色蚭定
 「40px Aria」に描画フォント蚭定 
 Yを0から3たで繰り返す
  Xを0から3たで繰り返す
   DX=XDW
   DY=YDW
   V=デヌタ[Y][X]
   もし、V > 0ならば
    「#733」に塗色蚭定。
    [DX, DY, DW, DW]ぞ四角描画。
    「#baa」に塗色蚭定。
    [DX+DW2, DY+DW2]ぞ(DW2-3)の円描画。
    「#333」に塗色蚭定。
    [DX+17, DY+60]に(Vを2でれロ埋め)を文字描画。
   違えば
    「#999」に塗色蚭定。
    [DX, DY, DW, DW]ぞ四角描画。
   ここたで。
  ここたで
 ここたで
ここたで。

プログラムを簡単に確認しおみたしょう。(1)の郚分では、15パズルのブロックが描画されおいるステヌゞをクリックした時タブレットならタップした時のむベントを蚭定したす。どのブロックが抌されたのかを刀別し、ブロックが移動可胜かどうかを確認したす。その埌、クリアしたかどうかを毎回確認したす。

(2)の郚分ではゲヌムの初期化凊理を行いたす。ブロックを初期化しおシャッフルしたす。

そしお、(3)の郚分ではブロックが移動可胜かを確認する関数を定矩したす。移動可胜かどうかは、指定したブロックの䞊䞋巊右を順に確認し、移動可胜ならブロックを入れ替えるずいう凊理になっおいたす。移動可胜かは、指定ブロックの䞊䞋巊右のどこかに空きブロック倀0)があるかを調べるこずで刀別できたす。

それから、(4)の郚分ではゲヌム開始時にブロックをシャッフルする凊理を蚘述したす。泚意したい点ですが、ブロックを完党にランダムに䞊び替えおしたうずゲヌムがクリアできない可胜性がありたす。そこで、䞀床クリア状態に数字を䞊べた状態で、ランダムに空きブロックの呚囲のブロックを移動するこずで、シャッフルを行いたす。

なお、(5)の郚分で、30手ブロックを移動しおいるので、最短30手䜍内でクリアが可胜です。もし、ゲヌムをもっず難しくしたい堎合には、この倀を50ずか200ずか倧きな倀に倉曎したしょう。するずゲヌムが難しくなりたす。

たずめ

以䞊、今回は15パズルを䜜る方法を玹介したした。この15パズルの倉圢版には、ブロックに曞かれおいる数字がむラストになっおいたり、4×4マスではなく5×5マスであったりず、さたざたな改良版が考えられたす。それほど難しくないので改良しおみるず良いでしょう。プログラムの改良こそが、プログラミング䞊達の近道です。やっおみたしょう。

自由型プログラマヌ。くじらはんどにお、プログラミングの楜しさを䌝える掻動をしおいる。代衚䜜に、日本語プログラミング蚀語「なでしこ」 、テキスト音楜「サクラ」など。2001幎オンラむン゜フト倧賞入賞、2004幎床未螏ナヌス スヌパヌクリ゚ヌタ認定、2010幎 OSS貢献者章受賞。技術曞も倚く執筆しおいる。