【DXRuby】入れ替えパズルをつくってみる。(6)-メインルーチン(5)-牌交換待機状態

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

“牌交換待機状態”で、牌を交換する。

横方向か縦方向のみ、牌を交換する。

まずは、交換牌選択可能状態で選んだ牌と横方向にある牌を交換できるようにプログラムを組みます。

  case state  #case文で条件分岐
  when "steel"	#選択待機状態

    ##省略

  when "base_click"	#交換牌選択可能状態

    ##省略

  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
  
        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]
          end
          base_x=-1
          base_y=-1
          state= "steel"
        end
      end
    end
  end #ここまでがcase文

このプログラムを実行すると、以下のようになります。

同様に、縦方向にある牌と交換するプログラムを加えます。

  case state  #case文で条件分岐
  when "steel"	#選択待機状態

    ##省略

  when "base_click"	#交換牌選択可能状態

    ##省略

  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
  
        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]
          end
          base_x=-1
          base_y=-1
          state= "steel"
        else              #縦方向の交換
          if base_x==x then
            tiles[base_y][base_x], tiles[y][x] = tiles[y][x], tiles[base_y][base_x]
          end
          base_x=-1
          base_y=-1
          state= "steel"
        end
      end
    end
  end #ここまでがcase文

ここまでの内容をまとめたプログラムは以下の通りです。

require 'dxruby'

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

#牌生成
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 = "steel" #初期値:選択待機状態

#ガイド枠線(横)
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)

Window.loop do
  # ここにゲームの処理を書く
  # update
  case state  #case文で条件分岐
  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
        #選択された縦方向の位置を取得し、交換牌選択可能状態に進む
        if y>-1 then
          base_y=y
          sorted =tiles[base_y].sort  #理牌用
          state="base_click"
        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
        #クリックされた手牌が、選択待機状態時に選択された手牌と同じであれば、
        #選択された横方向の位置を取得し、牌交換待機状態に進む
        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

  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
  
        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]
          end
          base_x=-1
          base_y=-1
          state= "steel"
        else              #縦方向の交換
          if base_x==x then
            tiles[base_y][base_x], tiles[y][x] = tiles[y][x], tiles[base_y][base_x]
          end
          base_x=-1
          base_y=-1
          state= "steel"
        end
      end
    end
  end #ここまでがcase文
  
  # 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(0,tile_h*base_y,y_guide)
  #選択した牌の縦軸を枠線で囲む
  Window.draw(tile_w*base_x,0,x_guide)

end

交換可能回数を設定する。

これで、牌交換ができるようになりましたので、交換可能回数を設定し、ゲームらしくしていきます。

まずはWindow.loopメソッドの上に、入替回数を保持する変数を用意します。

#入替回数
rest=8

牌を交換したときに、この変数の値が1減るので、牌交換待機状態のプログラムを以下のように変更します。(20行目、28行目)

  case state  #case文で条件分岐
  when "steel"	#選択待機状態

    ##省略

  when "base_click"	#交換牌選択可能状態

    ##省略

  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
  
        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              #縦方向の交換
          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"
        end
      end
    end
  end #ここまでがcase文

次に、現在の入替回数を表示するようにします。

DXRubyで文字を表示させるときには、フォントに関する情報が必要なので、Windows.loopメソッドの上に、以下のコードを追加します。

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

Windows.loop内に、以下のコードを追加します。

  #入替回数表示
  Window.draw_font(0, tile_h * 10, "回数残 = #{rest}", font, {:color => C_WHITE})

入替回数が0になったら、ゲームが終了になるように、case文の後に、breakメソッドを追加します。

  case state  #case文で条件分岐
  
    ##省略

  end #ここまでがcase文
  break if rest <= 0  #入替回数0以下になったら終了。

ここまでの内容をまとめたプログラムは以下の通りです。

require 'dxruby'

#ウィンドウサイズ
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 = "steel" #初期値:選択待機状態

#入替回数
rest=8

#ガイド枠線(横)
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)

Window.loop do
  # ここにゲームの処理を書く
  # update
  case state  #case文で条件分岐
  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
        #選択された縦方向の位置を取得し、交換牌選択可能状態に進む
        if y>-1 then
          base_y=y
          sorted =tiles[base_y].sort  #理牌用
          state="base_click"
        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
        #クリックされた手牌が、選択待機状態時に選択された手牌と同じであれば、
        #選択された横方向の位置を取得し、牌交換待機状態に進む
        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

  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
  
        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              #縦方向の交換
          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"
        end
      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})
  #選択した手牌を枠線で囲む
  Window.draw(0,tile_h*base_y,y_guide)
  #選択した牌の縦軸を枠線で囲む
  Window.draw(tile_w*base_x,0,x_guide)

end

このプログラムを実行すると、以下のようになります。

以上で、入替回数内で牌を入れ替えるメインルーチンができました。

次回からは、和了判定を組み込んで、ゲームとして動くプログラムを作成します。

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

コメント

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