コンピュータを楽しもう!!

今、自分が面白くていろいろやってみたことを書き綴りたいと思います。連絡先はtarosa.yでgmail.comです。

動物将棋 (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()のループの中でも、使用するようにしました。

これで、引き分けの判定はありませんが、ほぼ、動物将棋として遊べるようにはなりました。
後は、やっぱり「待った」と「投了」が欲しいと思うので、棋譜関連の実装をしていきたいと思います。