【DXRuby】入れ替えパズルをつくってみる。(10)-点数計算状態処理~完成

前回記事はこちらです。↓

いよいよ、完成です!!。

それでは、点数計算処理を作成して、ゲームを完成させます!。

点数計算状態の追加

まずは、和了り形や役の情報を格納する変数を”Windows.loop”の前で宣言します。

agari_list = []         #和了り形などを格納する配列
agari_idx = 0           #処理対象の和了り形(agari_list)(0 or 1)
agari_result = []       #点数計算結果
agari_result_view = []  #結果表示情報
th = false              #地和判定

#和了り結果表示エリアのバックグラウンド(透過黒)
bg = Image.new(tile_w*14, tile_h*10, [191, 0, 0, 0])

point = 0               #点数

Window.loop do

#略

end

次に、和了り形ができた後に、点数や役を表示する状態”和了形完成状態 ”を、新たに設定します。

  case state  #case文で条件分岐
  when "start"  #配牌直後状態
  
	#略
	
  when "agari" #和了形完成状態
  
	#ここに処理を追加
	
	end

点数計算処理

それでは、和了り形ができた時の処理を作成していきます。

まずは、和了り形完成状態の処理を作成します。

  case state  #case文で条件分岐
  
  #略
  
   when "agari" #和了形完成状態
    agari_result_view=[]
    agari_cnt = agari_list.count
    agari_result = point_check(agari_list[agari_idx][0], stage_list[stage_num][1], 31, agari_list[agari_idx][1], th)

    sorted =tiles[agari_list[agari_idx][2]].sort  #理牌用

    if (agari_result[1][1].include?("役満")) then
      agari_result_view[0] = "#{agari_result[1][1]} #{agari_result[1][0]}点"
      agari_result[0].each_with_index do |a,i|
        agari_result_view[i + 2] = "#{a[0]}"
      end
    else
      agari_result_view[0] = "#{agari_result[1][1][0]}飜 #{agari_result[1][1][1]}符 #{agari_result[1][0]}点"
      agari_result[0].each_with_index do |a,i|
        agari_result_view[i + 2] = "#{a[1]}飜 #{a[0]}"
      end
    end
    #表示後、点数を加算
    if Input.mouse_release?(0) then
      point += agari_result[1][0]
      agari_idx += 1
      #その後、各変数を初期化
      if agari_idx >= agari_cnt then
        agari_idx = 0
        agari_list = []
        agari_result = []
        agari_result_view = []
        th = false

        stage_num+=1

        state= "steel"
      end
    end
  end #ここまでがcase文

“agari_result”に、点数計算関数”point_check”の返り値を格納し、それを元に”agari_result_view”に、表示用の文字列を格納しています。

地和判定

まれに、ゲーム開始直後に和了り形ができている場合(地和)があるため、配牌直後状態に和了り判定を行い、地和になっていたら”和了り形完成状態”に移動します。

#略

Window.loop do
  # ここにゲームの処理を書く
  agari_y=false  #和了判定変数
  # update
  case state  #case文で条件分岐
  when "start"  #配牌直後状態
    #配牌直後に和了りが成立していないか(地和)チェック
    tiles.each_with_index do |t,i|
      r = false
      if t.include?(99) then
        r = false
      else
        r = agari_check(t)
      end
      if r!=false then
        agari_y_list << i
        t.sort!
        rest+=8
        th = true                       #追加
        agari_list << [r,tiles[i][0],i] #追加
      end
    end
    agari_list==[] ? state= "steel" : state= "agari"  #変更
  when "steel"	#選択待機状態
  
	#略
	
end

点数と和了り役の表示

それでは、和了りの中身を表示していきます。

#略

Window.loop do

	#略
	
  #点数表示
  Window.draw_font(672 - (point.zero? ? 1 : Math.log10(point.abs).to_i + 1)* 16,900 - 32,point.to_s,font,{:color => C_WHITE})
  #和了り表示
  if state == "agari" then
    sorted.each_with_index do |v,i|
      Window.draw(tile_w*i,tile_h * 11,hai_images[v])
    end

    Window.draw(0,0,bg)
    agari_result_view.each_with_index do |a,i|
      Window.draw_font(0, 32 * i,a.to_s,font,{:color => C_WHITE})
    end
  end
end	

以上の内容をまとめると、以下のようになります。

require 'dxruby'
require_relative './agari_check.rb'
require_relative './point_check.rb'

#ウィンドウサイズ
Window.resize 672,900
#キャプション
Window.caption = "mjpzl"
#バックグラウンド色(濃い緑色)
Window.bgcolor=[63, 0, 63, 0]

font = Font.new(32) #サイズ32の文字(フォント)を使用する。

#牌生成
hai_type=[
   1, 2, 3, 4, 5, 6, 7, 8, 9,	#萬子
  11,12,13,14,15,16,17,18,19,	#索子
  21,22,23,24,25,26,27,28,29,	#筒子
  31,33,35,37,								#風牌
  41,43,45,										#三元牌
  99													#裏牌
]

#牌の数は各牌4枚
hais = hai_type*4

#牌をランダムにシャッフル
hais.shuffle!

#牌を14*10に並べる
tiles =Array.new
(0..9).each do |y|
  tiles[y]=Array.new
  (0..13).each do |x|
	#haisの先頭からtilesにひとつずつ代入していく。
    tiles[y][x]=hais.shift
  end
end

#牌画像
hai_images=Array.new
(1..9).each do |i|
  hai_images[     i] = Image.load("./image/p_ms#{i}_1.png")
  hai_images[ 10 +i] = Image.load("./image/p_ps#{i}_1.png")
  hai_images[ 20 +i] = Image.load("./image/p_ss#{i}_1.png")
end
hai_images[31] = Image.load("./image/p_ji_e_1.png")
hai_images[33] = Image.load("./image/p_ji_s_1.png")
hai_images[35] = Image.load("./image/p_ji_w_1.png")
hai_images[37] = Image.load("./image/p_ji_n_1.png")

hai_images[41] = Image.load("./image/p_no_1.png")
hai_images[43] = Image.load("./image/p_ji_h_1.png")
hai_images[45] = Image.load("./image/p_ji_c_1.png")

hai_images[99] = Image.load("./image/p_bk_1.png")

tile_w = 48	#牌画像の幅
tile_h = 64	#牌画像の高さ

base_x =-1  #選択された横方向の位置
base_y =-1  #選択された縦方向の位置

sorted =Array.new #理牌用変数

#状態変数
state = "start" #初期値:配牌直後状態

#入替回数
rest=8

#和了手牌格納
agari_y_list =[]

#ガイド枠線(横)
y_guide=Image.new(tile_w*14,tile_h   ).box(0,0,tile_w*14,tile_h   ,C_CYAN)
                                      .box(1,1,tile_w*14-1,tile_h-1,C_CYAN)
                                      .box(2,2,tile_w*14-2,tile_h-2,C_CYAN)
                                      .box(3,3,tile_w*14-3,tile_h-3,C_CYAN)

#ガイド枠線(縦)
x_guide=Image.new(tile_w   ,tile_h*10).box(0,0,tile_w  ,tile_h*10  ,C_CYAN)
                                      .box(1,1,tile_w-1,tile_h*10-1,C_CYAN)
                                      .box(2,2,tile_w-2,tile_h*10-2,C_CYAN)
                                      .box(3,3,tile_w-3,tile_h*10-3,C_CYAN)
#和了り枠線
agai_guide_list=[]
(0..9).each do |i|
  agai_guide_list[i]=Image.new(tile_w*14,tile_h).box(0,0,tile_w*14,tile_h,C_RED)
  .box(1,1,tile_w*14-1,tile_h-1,C_RED)
  .box(2,2,tile_w*14-2,tile_h-2,C_RED)
  .box(3,3,tile_w*14-3,tile_h-3,C_RED)
end

#局
stage_list=Array.new
stage_list[0]=["東一局     北家",37,0]
stage_list[1]=["東二局     西家",35,0]
stage_list[2]=["東三局     南家",33,0]
stage_list[3]=["東四局     東家",31,0]
stage_list[4]=["東四局 一本場 東家",31,1]
stage_list[5]=["東四局 二本場 東家",31,2]
stage_list[6]=["東四局 三本場 東家",31,3]
stage_list[7]=["東四局 四本場 東家",31,4]
stage_list[8]=["東四局 五本場 東家",31,5]
stage_list[9]=["東四局 六本場 東家",31,6]

stage_num=0

agari_list = []         #和了り形などを格納する配列
agari_idx = 0           #処理対象の和了り形(agari_list)(0 or 1)
agari_result = []       #点数計算結果
agari_result_view = []  #結果表示情報
th = false              #地和判定

#和了り結果表示エリアのバックグラウンド(透過黒)
bg = Image.new(tile_w*14, tile_h*10, [191, 0, 0, 0])

point = 0               #点数

Window.loop do
  # ここにゲームの処理を書く
  agari_y=false  #和了判定変数
  # update
  case state  #case文で条件分岐
  when "start"  #配牌直後状態
    #配牌直後に和了りが成立していないか(地和)チェック
    tiles.each_with_index do |t,i|
      r = false
      if t.include?(99) then
        r = false
      else
        r = agari_check(t)
      end
      if r!=false then
        agari_y_list << i
        t.sort!
        rest+=8
        th = true                       #追加
        agari_list << [r,tiles[i][0],i] #追加
      end
    end
    agari_list==[] ? state= "steel" : state= "agari"  #変更
  when "steel"	#選択待機状態
    #選択待機状態の処理を書く
    base_y =-1  #選択された縦方向の牌の位置
    if Input.mouse_release?(0) then
      #牌が表示されている範囲をクリックしたら以下を処理
      if (Input.mouse_x > 0) && (Input.mouse_x < tile_w * 14) && (Input.mouse_y > 0 ) && (Input.mouse_y < tile_h * 10) then
        #クリックされた箇所が上から何段目かを取得
        y = Input.mouse_y/tile_h

        #すでに和了っている横軸をクリックしても何もない。
        agari_y_list.each do |v|
          agari_y=true if v==y
        end
        if agari_y==false then  #クリックした牌が和了形でなければ、その状態での処理を実施
          #選択された縦方向の位置を取得し、交換牌選択可能状態に進む
          if y>-1 then
            base_y=y
            sorted =tiles[base_y].sort  #理牌用
            state="base_click"
          end
        end
      end
    end
  when "base_click"	#交換牌選択可能状態
    #交換牌選択可能状態の処理を書く
    base_x =-1  #選択された横方向の牌の位置
    if Input.mouse_release?(0) then
      #牌が表示されている範囲をクリックしたら以下を処理する
      if (Input.mouse_x > 0) && (Input.mouse_x < tile_w * 14) && (Input.mouse_y > 0) && (Input.mouse_y < tile_h * 10) then
        #クリックされた箇所が上から何段目かを取得
        y =Input.mouse_y/tile_h
        #クリックされた箇所が左から何番目かを取得
        x = Input.mouse_x/tile_w

    		#すでに和了っている横軸をクリックしても何もない。
        agari_y_list.each do|v|
          agari_y=true if v==y
        end
        if agari_y==false then
          #クリックされた手牌が、選択待機状態時に選択された手牌と同じであれば、
          #選択された横方向の位置を取得し、牌交換待機状態に進む
          if base_y==y then
            base_x=x
            state="change_steel"
          else
            #違う手牌を再選択
            base_y = y
            sorted =tiles[base_y].sort  #理牌用
            state="base_click"
          end
        end
      end
    end

  when "change_steel" #牌交換待機状態
    #牌交換待機状態の処理を書く
    if Input.mouse_release?(0) then
      if (Input.mouse_x > 0) && (Input.mouse_x < tile_w * 14) && (Input.mouse_y > 0) && (Input.mouse_y < tile_h * 10) then
        y = Input.mouse_y/tile_h
        x = Input.mouse_x/tile_w

        #すでに和了っている横軸をクリックしても何もない。
        agari_y_list.each do |v|
          agari_y=true if v==y
        end
        if agari_y==false then
          if base_y==y then #横方向の交換
            if base_x!=x then
              tiles[base_y][base_x], tiles[y][x] = tiles[y][x], tiles[base_y][base_x]
              rest-=1	#牌を交換したら、入れ替え回数を1減らす。
            end
            base_x=-1
            base_y=-1
            state= "steel"
          else              #縦方向の交換
            ah0 = -1 #和了り牌
            ah1 = -1 #和了り牌
            if base_x==x then
              tiles[base_y][base_x], tiles[y][x] = tiles[y][x], tiles[base_y][base_x]
              #和了判定
              #tiles[base_y]に"99"があればresult0=falseとする。
              if tiles[base_y].include?(99) then
                result0=false
              else
                result0=agari_check(tiles[base_y])
              end
              #tiles[y]に"99"があればresult1=falseとする。
              if tiles[y].include?(99) then
                result1=false
              else
                result1=agari_check(tiles[y])
              end
              
              if result0==false&&result1==false then
                rest-=1 #入れ替えた手牌が和了りになっていなかったら、入れ替え回数を1減らす。
              else
                if result0!=false then
                  ah0 = tiles[base_y][base_x]
                  agari_y_list << base_y
                  tiles[base_y].sort!
                  rest+=8
                  #stage_num+=1
                  agari_list << [result0,ah0,base_y] #追加
                end
                if result1!=false then
                  ah1 = tiles[y][x]
                  agari_y_list << y
                  tiles[y].sort!
                  rest+=8
                  #stage_num+=1
                  agari_list << [result1,ah1,y] #追加
                end
              end
              #ここまでが和了判定
            else
              state="change_steel"            
            end
            base_x=-1
            base_y=-1
            agari_list==[] ? state= "steel" : state= "agari"  #変更
          end
        end
      end
    end
  when "agari" #和了形完成状態
    agari_result_view=[]
    agari_cnt = agari_list.count  #2列の完成がほとんどだが、まれに2列同時に完成する場合あり
    agari_result = point_check(agari_list[agari_idx][0], stage_list[stage_num][1], 31, agari_list[agari_idx][1], th)

    sorted =tiles[agari_list[agari_idx][2]].sort  #理牌用

    if (agari_result[1][1].include?("役満")) then
      agari_result_view[0] = "#{agari_result[1][1]} #{agari_result[1][0]}点"
      agari_result[0].each_with_index do |a,i|
        agari_result_view[i + 2] = "#{a[0]}"
      end
    else
      agari_result_view[0] = "#{agari_result[1][1][0]}飜 #{agari_result[1][1][1]}符 #{agari_result[1][0]}点"
      agari_result[0].each_with_index do |a,i|
        agari_result_view[i + 2] = "#{a[1]}飜 #{a[0]}"
      end
    end
    #表示後、点数を加算
    if Input.mouse_release?(0) then
      point += agari_result[1][0]
      agari_idx += 1
      #その後、各変数を初期化
      if agari_idx >= agari_cnt then
        agari_idx = 0
        agari_list = []
        agari_result = []
        agari_result_view = []
        th = false

        stage_num+=1

        state= "steel"
      end
    end
  end #ここまでがcase文
  break if rest <= 0  #入替回数0以下になったら終了。
  # draw
  tiles.each_with_index do |rows,y|
    rows.each_with_index do |v,x|
      Window.draw(tile_w * x, tile_h * y, hai_images[v])
    end
  end
  #理牌表示
  if base_y>-1 then
    sorted.each_with_index do |v,i|
      Window.draw(tile_w*i,tile_h * 11,hai_images[v])
    end
  end
  #入替回数表示
  Window.draw_font(0, tile_h * 10, "回数残 = #{rest}", font, {:color => C_WHITE})
 #和了り枠線表示
  agari_y_list.each do |v|
    Window.draw(0,tile_h * v,agai_guide_list[v])
  end
 #選択した手牌を枠線で囲む
  Window.draw(0,tile_h*base_y,y_guide)
  #選択した牌の縦軸を枠線で囲む
  Window.draw(tile_w*base_x,0,x_guide)
  #局表示
  Window.draw_font(0, tile_h*12,stage_list[stage_num][0],font,{:color => C_WHITE})
  #点数表示
  Window.draw_font(672 - (point.zero? ? 1 : Math.log10(point.abs).to_i + 1)* 16,900 - 32,point.to_s,font,{:color => C_WHITE})
  #和了り表示
  if state == "agari" then
    sorted.each_with_index do |v,i|
      Window.draw(tile_w*i,tile_h * 11,hai_images[v])
    end

    Window.draw(0,0,bg)
    agari_result_view.each_with_index do |a,i|
      Window.draw_font(0, 32 * i,a.to_s,font,{:color => C_WHITE})
    end
  end
end

これで、麻雀牌入れ替えパズルの完成です!。

完成!!

後半は、かなり急ぎ足になりましたが、これで完成です。

このプログラムをrbCanvasで書き換えて、web上で遊べるようにしたものを置きますので、よろしければ、遊んでみてください。

次回を総括として、最終回にしたいと思います。

次回記事は、こちらです。↓

コメント

タイトルとURLをコピーしました