動物将棋 (8)
駒の操作が一段落したので、勝ち負けの判断ルーチンを作りたいと思います。
動物将棋の勝敗
動物将棋は下記の条件により勝ち負けが決定します。
勝敗はこの2つで決まります。また、引き分けとして千日手があります。これは同じ局面が三回出た時点で引き分けとなるのですが、こうなると、随時局面を記録していかなければならないので、これは後回しにしたいと思います。
相手のライオンを取る
勝ち負けを判断する関数として、chkSyobuari()という関数を作りました。この関数中でライオン駒が1つだけになったかどうかを調べています。勝負がついていないときは、0が返り、先手が勝ったときは1が、後手が勝ったときは2が返ります。
pu[1]とpu[2]が先手、後手のライオンの有無をチェックする変数です。forループ内のif文で、pxとpyにx,yを保持しているのは、ライオン駒が2つあるときに、どちらかが入玉していないか調べるために使うためです。
------------------------------------------ -- 勝負有りかどうかのチェック -- 0:勝負中、1:先手の勝ち、2:後手の勝ち ------------------------------------------ function chkSyobuAri() local x, y local ret = 0 local px={} local py={} local pu={} pu[1] = 0 pu[2] = 0 --相手のライオンが盤上にあるか調べる for y=1,4 do for x=1,3 do if( Ban[x][y]==15 )then --先手のライオンを見つけた px[1] = x py[1] = y pu[1] = 1 end if( Ban[x][y]==25 )then --後手のライオンを見つけた px[2] = x py[2] = y pu[2] = 1 end end end if( pu[1]==0 )then return 2 end --後手の勝ち if( pu[2]==0 )then return 1 end --先手の勝ち
入玉の判定
入玉の判定は、先手ならy座標が1のところ、後手ならy座標が4のところに居るときに、ライオンを取れる駒が無ければ、勝ちと判断しています。Ban[x][y]にいる駒が相手の駒かどうかを、getPlyer()を用いて調べ、相手の駒なら、chkMove()でその駒がライオンを取れるかどうかをチェックしています。取ることができれば、勝負はつかないという感じです。forループで12マス全ての駒を調べる必要は無いのですが、とりあえず、速度も気にならないので、全部ループしています。
--相手のエリアに入っているか調べる if( py[1]==1 )then ret = 1 for y=1,4 do for x=1,3 do if( getPlyer( Ban[x][y] )==2 and chkMove( x, y, px[1], py[1], Ban[x][y] )==1 )then ret = 0 end end end if( ret~=0 )then return ret end end if( py[2]==4 )then ret = 2 for y=1,4 do for x=1,3 do if( getPlyer( Ban[x][y] )==1 and chkMove( x, y, px[2], py[2], Ban[x][y] )==1 )then ret = 0 end end end if( ret~=0 )then return ret end end return 0
勝負あり
駒を動かす関数doTouchAction()は、while(true)doループしているので、勝負がついたらループを抜ける部分を追加しました。
--勝負がついたか調べます winner = chkSyobuAri() if( winner~=0 )then break end
これで、無限ループを抜けて、メイン関数に戻ってきます。
再ゲーム
ゲームの終了を判断できるようになったので、もう一度、動物将棋をするかどうかが選択できるようにしました。
メインのソースを以下に書きます。doTouchAction()関数は、勝った人の番号を返すようにしました。それを元に勝敗を表示します。OKが選ばれた場合は、「将棋盤を描く」からのループに戻ります。
------------------------------------------ --メインプログラム ------------------------------------------ function main() local dsyougibmp local x,y local winner, wstr local a --背景 canvas.drawCls( BGColor ) --ワークエリア画面をクリアします canvas.workCls() --ワークエリアの(0,0)-(287,287)に動物将棋画像を読み込みます dsyougibmp = LuaridaPath.."/".."dbsgb4.png" if( canvas.loadBmp( dsyougibmp, 0, 0, 287, 287 )==-1)then dialog( dsyougibmp, "ロードに失敗しました",1 ) do return end end while(true)do -- 将棋盤を描く drawSyogiBan() -- 将棋データを初期化します initKomadata() --盤上の駒と持ち駒を描画します drawAll() --どうぶつしょうぎスタート winner = doTouchAction() if( winner==1 )then wstr="せんて" else wstr="ごて" end a = dialog( wstr.."のかちです", "もういちど、さしますか",2 ) if( a~=1 )then break end end toast( "画面タッチで終了します", 0 ) touch(3) end
再ゲームできるように修正したことにより、将棋データの初期化ルーチンと駒配置の描画ルーチンを追加しました。下記にソースを書きます。
------------------------------------------ -- 将棋データを初期化します ------------------------------------------ function initKomadata() Ban={} Ban[1] = { 23,0,0,14 } Ban[2] = { 25,21,11,15 } Ban[3] = { 24,0,0,13 } Mochi = {} Mochi[1] = {0,0,0,0,0,0} Mochi[2] = {0,0,0,0,0,0} end ------------------------------------------ -- 盤上の駒と持ち駒を描画します ------------------------------------------ function drawAll() local i,j --盤上の駒を描く for j=1,4 do for i=1,3 do dput( i, j, Ban[i][j] ) end end --持ち駒を描く for i=1,6 do mput( 1, i, Mochi[1][i] ) mput( 2, i, Mochi[2][i] ) end canvas.putflush() end
drawAll()は、doTouchAction()のループの中でも、使用するようにしました。
これで、引き分けの判定はありませんが、ほぼ、動物将棋として遊べるようにはなりました。
後は、やっぱり「待った」と「投了」が欲しいと思うので、棋譜関連の実装をしていきたいと思います。