【講座?】CoRを触ってみる17~三目並べを作る5~【自分用メモ?】

投稿者:    mini 光楼(114) 投稿日:2017/05/13 15:28

【講座?】CoRを触ってみる16~三目並べを作る4~【自分用メモ?】←前回

今交響曲を作曲中でして、とりあえず第1楽章が完成したので宣伝してみる。
こちら

#このブログの情報は2017年5月13日現在のものです。今後変更になる可能性があります。

前回の続きです。
game.rbを開くのじゃ!

前回は敵に×を置かせる処理を書きました。
今回は勝敗の判定を作ります。

今更ですがゲームの流れを説明します。

プレーヤーターン → 描画 → 勝敗判定 → (描画) → 敵ターン → 描画 → 勝敗判定 → (描画)→ プレーヤーターン
です。

盤面が変化しない限り描画処理は行わないので、勝敗判定後の描画は実質スルーされます。

では早速、update内に勝敗判定用の処理を書いていきましょう。
#=====対戦=====#
scene 'game' do
  #変数定義
  bg_sprite = nil #背景
  mesh_sprite = nil #マス
  mark_sprite = nil #〇
  board_data = [0,0,0,0,0,0,0,0,0] #盤面情報 0:空白 1:〇 -1:×
  comparison_board_data = board_data.dup #盤面変化判定用配列
  turn = 0 #ターン

  ##### ↓追加分↓  #####
  decision = 0 #勝敗判定実行判定用
  ##### ↑追加分↑  #####
#後略

さて、update内のifturn%2==0……endの外側にif文を追加したいので、ifturn%2==0……endをもう一段階字下げしましょう!

1.ifturn%2==0……endを選択します。


2.Tabキーを押します。


はい、これで選択した部分が全体的に右側へ動いたと思います。
まぁ、この後ソースのせるのでやらなくていいのですが、知っておくと字下げが楽になります。

ちなみにこれ、TABインデントって言います。
Shift + Tabで逆TABインデントが可能です。

さて、勝敗判定用のターンを作りましょう。
#前略
  update do
    comparison_board_data = board_data.dup #配列コピー

    ##### ↓追加分↓  #####
    if decision % 2 == 0 #勝敗判定実行判断
      ####プレーヤーor敵ターン####
    ##### ↑追加分↑  #####

      if turn % 2 == 0
        ####プレーヤーのターン####
  
        #クリックまたはタップしたか
        if pointer.down?
          column = ((pointer.x - board_left_position) / board_size).floor #列を求める
          paragraph = ((pointer.y - board_up_position) / board_size).floor #段を求める
    
          #列が0~2、段も0~2の範囲か
          if (0..2) === column && (0..2) === paragraph
            block = column + paragraph * 3 #列・段からマス番号を求める
            if board_data[block] == 0 #選択したマスが空白か
              board_data[block] = 1
  
              turn += 1 #行動したらターン交代

              ##### ↓追加分↓  #####
              decision += 1
              ##### ↑追加分↑  #####

              #debug_log "#{block}番のマスをクリック\n #{board_data}\n #{comparison_board_data}"
            end
          end
        end
  
      else
        ####敵のターン####
        wait_time(500) #0.5秒待機
  
        #×配置場所選択
        while(board_data[result = rand(9)] != 0) do
          wait_time(100) #無限ループ対策
        end
  
        board_data[result] = -1 #盤面情報書き換え
        turn += 1 #ターン交代

        ##### ↓追加分↓  #####
        decision += 1
        ##### ↑追加分↑  #####
      end

    ##### ↓追加分↓  #####
    else
      ####勝敗判定####

      decision += 1
    end
    ##### ↑追加分↑  #####
  end
#後略


判定方法は簡単。縦3つ、横3つ、斜め2つをそれぞれ調べ、同じマークが3つそろっている列があるかを調べます。
因みにこの処理はユーザー定義関数(メソッド)で行います。

何故かって?
敵のAI作るときにこの処理が使えるからです。
ま、詳しいことは置いといて……。
#前略
#=====定義=====#
#スプライト
sprite 'メニュー背景' do
  image 'メニュー背景画像'
  origin :left_top

  animation '通常アニメ', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1], 20, true
end

sprite 'マス' do
  image 'マス画像'
end

sprite '〇' do
  image '〇画像'
  origin :left_top
end

sprite '×' do
  image '×画像'
  origin :left_top
end

##### ↓追加分↓  #####
#メソッド
def win_or_loss(board) #勝敗判定メソッド
  
end
##### ↑追加分↑  #####

ではこのメソッド内に処理を書いていきます。
あ、第一引数のboardが盤面のデータです。

まずは横3列の判定。
#メソッド
def win_or_loss(board) #勝敗判定メソッド
  ##### ↓追加分↓  #####
  #戻り値 0:試合継続 1:プレーヤー勝利 2:プレーヤー敗北 3:引き分け

  #横3列判定
  3.times do |i|
    case board[i*3] + board[i*3 + 1] + board[i*3 + 2]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end
  ##### ↑追加分↑  #####
end

盤面を管理する配列に入っている値は0,1,-1のいずれかです。
そして同じマークが揃っているとすれば、3つのマスの値を足すと3か-3になっているはずですので、このような処理になります。

揃っていたらreturnで戻り値を設定します。
returnを実行するとそのメソッドを脱出(終了)します。

次は縦です。
#メソッド
def win_or_loss(board) #勝敗判定メソッド
  #戻り値 0:試合継続 1:プレーヤー勝利 2:プレーヤー敗北 3:引き分け

  #横3列判定
  3.times do |i|
    case board[i*3] + board[i*3 + 1] + board[i*3 + 2]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end

  ##### ↓追加分↓  #####
  #縦3列判定
  3.times do |i|
    case board[i] + board[i+3] + board[i+6]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end
  ##### ↑追加分↑  #####
  
  return 0
end

そして斜め。
#メソッド
def win_or_loss(board) #勝敗判定メソッド
  #戻り値 0:試合継続 1:プレーヤー勝利 2:プレーヤー敗北 3:引き分け

  #横3列判定
  3.times do |i|
    case board[i*3] + board[i*3 + 1] + board[i*3 + 2]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end

  #縦3列判定
  3.times do |i|
    case board[i] + board[i+3] + board[i+6]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end

  ##### ↓追加分↓  #####
  #斜め\
  case board[0] + board[4] + board[8]
  when 3 #〇が揃っている
    return 1
  when -3 #×が揃っている
    return 2
  end

  #斜め/
  case board[2] + board[4] + board[6]
  when 3 #〇が揃っている
    return 1
  when -3 #×が揃っている
    return 2
  end
  ##### ↑追加分↑  #####
  
  return 0
end

さて、まだ判定は残っています。
それは引き分けかどうかの判定です。
空のマスがあるかどうかで判断します。
#メソッド
def win_or_loss(board) #勝敗判定メソッド
  #戻り値 0:試合継続 1:プレーヤー勝利 2:プレーヤー敗北 3:引き分け

  #横3列判定
  3.times do |i|
    case board[i*3] + board[i*3 + 1] + board[i*3 + 2]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end

  #縦3列判定
  3.times do |i|
    case board[i] + board[i+3] + board[i+6]
    when 3 #〇が揃っている
      return 1
    when -3 #×が揃っている
      return 2
    end
  end

  #斜め\
  case board[0] + board[4] + board[8]
  when 3 #〇が揃っている
    return 1
  when -3 #×が揃っている
    return 2
  end

  #斜め/
  case board[2] + board[4] + board[6]
  when 3 #〇が揃っている
    return 1
  when -3 #×が揃っている
    return 2
  end

  ##### ↓追加分↓  #####
  #引き分けチェック
  if board.include?(0) #空のマスがあるか
    return 0 #ある→試合継続
  else
    return 3 #ない→引き分け
  end
  ##### ↑追加分↑  #####
end

これでメソッドは完成です。

さて、実際に結果を表示させましょう。
  update do
    comparison_board_data = board_data.dup #配列コピー

    ##### ↓追加分↓  #####
    if decision % 2 == 0 #勝敗判定実行判断
      ####プレーヤーor敵ターン####
    ##### ↑追加分↑  #####

      if turn % 2 == 0
        ####プレーヤーのターン####
  
        #クリックまたはタップしたか
        if pointer.down?
          column = ((pointer.x - board_left_position) / board_size).floor #列を求める
          paragraph = ((pointer.y - board_up_position) / board_size).floor #段を求める
    
          #列が0~2、段も0~2の範囲か
          if (0..2) === column && (0..2) === paragraph
            block = column + paragraph * 3 #列・段からマス番号を求める
            if board_data[block] == 0 #選択したマスが空白か
              board_data[block] = 1
  
              turn += 1 #行動したらターン交代
              decision += 1
              #debug_log "#{block}番のマスをクリック\n #{board_data}\n #{comparison_board_data}"
            end
          end
        end
  
      else
        ####敵のターン####
        wait_time(500) #0.5秒待機
  
        #×配置場所選択
        while(board_data[result = rand(9)] != 0) do
          wait_time(100) #無限ループ対策
        end
  
        board_data[result] = -1 #盤面情報書き換え
        turn += 1 #ターン交代
        decision += 1
      end

    else
      ####勝敗判定####

      ##### ↓追加分↓  #####
      disposition = win_or_loss(board_data)
      if disposition != 0
        debug_log "結果:#{disposition}"
        #仮終了処理
        game_clear
      end
      ##### ↑追加分↑  #####

      decision += 1
    end
  end

今回はここまでです。
お疲れさまでした!

次回→【講座?】CoRを触ってみる18~三目並べを作る6~【自分用メモ?】

コメントする

コメントするには、ログインする必要があります。

コメント一覧

Cdv30200 aoi icon mini aoihikawa(投稿日:2017/05/14 08:56, 履歴)
ゲームも大分
完成に近づいてきましたね

もうひとがんばり、といった
ところでしょうか
    mini 光楼(114)(投稿日:2017/05/14 10:52, 履歴)
コメントありがとうございます!

そうですね、早く完成させたいです。