Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@nogitsune413

Javaで書いたオセロをScalaで書き直した。

More than 5 years have passed since last update.

Scalaを覚えるため、Scalaでオセロゲームを書きました。
いきなりScalaを使うのが難しそうだったため、Javaで下書きしてからScalaで書きました。

以前Javaで下書きしたもの → http://qiita.com/nogitsune413/items/d252a879480480a0697a

なるべく関数プログラミングっぽく書きたかったため、再帰やコレクションを使って、変数の除去に努めました。
他の言語と比べた訳ではないのですが、末尾呼び出し最適化が簡単に書けたので、「こんな簡単に書けるのか」と思いました。
そんな感想です。


import scala.io._

object Main {

  val L       = 10
  val X       =  0
  val Y       =  1
  val EMPTY   =  0
  val BLACK   =  1
  val WHITE   =  2
  val DRAW    =  3
  val WALL    =  9
  val MOVE    =  1
  val PASS    =  2
  val GIVE_UP =  3
  val EXIT    =  4

  val dir     = Array(-1,0,1,1,1,0,-1,-1) zip Array(-1,-1,-1,0,1,1,1,0)
  var board   = Array.ofDim[Int](L,L)
  var x,y     = -1
  var victory = DRAW

  val LINE       = "------------------------------\n"
  val TITLE      = "\n" + LINE + "---      オセロ          ---\n" + LINE + "\n"
  val USAGE      = "  ---  遊び方   --- \n 縦 5,横 3 のマスに置く => 「5 3」と入力。\n パス: pass \n 投了:give up\n ゲームの終了: exit\n"
  val URGES      = "\n駒を置いて下さい  => "  
  val RANGE      = "^[1-8]$"
  val S_BLACK    = "黒"
  val S_WHITE    = "白"
  val S_TURN     = "番"
  val S_DRAW     = "\n   ---    引き分け   ---  \n"
  val PRE_LINE   = "\n   ---  "
  val POST_LINE  = "      ---   \n\n"
  val BLACK_TURN = PRE_LINE + S_BLACK + S_TURN + POST_LINE
  val WHITE_TURN = PRE_LINE + S_WHITE + S_TURN + POST_LINE
  val S_VICTORY  = "の勝ち   ---   \n"
  val S_ERROR    = "駒が置けません。別のマスを選択して下さい。\n"
  val IN_ERROR   = "入力に誤りがあります。再度入力して下さい。\n"
  val THANKS     = "Thank you for playing. Good by the next time."

  object Turn{
    var thisTurn   = BLACK
    def show() = {
      if(thisTurn==BLACK){print(BLACK_TURN)}
      else               {print(WHITE_TURN)}
    }
    def shift() = {
      thisTurn = 3 - thisTurn
    }
    def otherside():Int = {
      3 - thisTurn
    }
  }

  object Board{
    def init() = {
      for(i <- 0 to L - 1 ){
        board(0)(i) = WALL
        board(9)(i) = WALL
        if(i != 0 && i != 9){
          for(i <- 1 to 8){
            board(i)(0) = WALL
            board(i)(9) = WALL
          }
        }
      }
      for(i <- 4 to 5){
        for(j <- 4 to 5){
          if(i==j){
            board(i)(j) = WHITE
          } else {
            board(i)(j) = BLACK
          }
        }
      }
    }
    def show() = {
      print(LINE)
      print("     ")
      for(i <- 1 to L - 2){
        print(i)
        if(i<L-2){print(" ")}
      }
      for(i <- 0 to L-1){
        if(0<i && i<L-1){
          print("\n " + i + " ")
        } else {
          print("\n   ")
        }
        for(j <- 0 to L-1){
          board(i)(j) match {
            case WALL  => print("+")
            case EMPTY => print("_")
            case WHITE => print("o")
            case BLACK => print("*")
          }
          print(" ")
        }
        if(i<L-1){print(" ")}
        else     {print("\n")}
      }
      print(LINE)
    }
  }

  def main(args:Array[String]) = {

    Board.init()

    println(TITLE)
    println(USAGE)

    UI
  }

  def UI:Unit = {
      Turn.show()
      Board.show()
      print(URGES)
      val cmd = input()
      cmd match {
        case MOVE    => if(update){
                          if(isFill){
                            victory = judge()
                            show_result()
                          } else {
                            Turn.shift()
                            UI
                          }
                        } else {
                          println(S_ERROR)
                          UI
                        }
        case PASS    => Turn.shift()
                        UI
        case GIVE_UP => victory = Turn.otherside
                        show_result()
        case EXIT    => println(THANKS)
      }
  }

  def show_result() = {
    var result = ""
    victory match {
      case BLACK => result = PRE_LINE + S_BLACK + S_VICTORY
      case WHITE => result = PRE_LINE + S_WHITE + S_VICTORY
      case DRAW  => result = S_DRAW
    }
    println(result)
    Board.show()
  }

  def input():Int = {
    val in = readLine()
    in match {
      case "pass"    => PASS
      case "exit"    => EXIT
      case "give up" => GIVE_UP
      case _         => val ar = in.split("\\s")
                        if(ar.length==2 && ar(0).matches(RANGE) && ar(1).matches(RANGE)){
                          y = ar(0)toInt;
                          x = ar(1)toInt;
                          MOVE
                        } else {
                          println(IN_ERROR)
                          println(USAGE)
                          println(URGES)
                          input()
                        }
    }
  }

  def judge():Int = {
    if(count(BLACK) < count(WHITE)){
      WHITE
    } else if(count(BLACK)>count(WHITE)){
      BLACK
    } else {
      DRAW
    }
  }

  def isFill:Boolean = {
    if(count(BLACK)+count(WHITE)==8*8){
      true
    } else {
      false
    }
  }

  def count(color:Int):Int = {
    count(board,color)
  }

  def count(brd:Array[Array[Int]],color:Int):Int = {
    if(brd.isEmpty){
      0
    } else {
      (brd.first filter (_ == color)).length + count(brd.tail,color)
    }
  }

  def update() = {
    if(chk_square()){
      flip()
      true
    } else {
      false
    }
  }

  def chk_square():Boolean = {
    if(board(y)(x)!=EMPTY){return false}
    for(dr <- dir){
      if(board(y + dr._2)(x + dr._1)==Turn.otherside){
        if(chk_square_a(x + dr._1 * 2,y + dr._2 * 2,dr)){
          return true;
        }
      }
    }
    false
  }

  def chk_square_a(a:Int,b:Int,dr:(Int,Int)):Boolean = {
    board(b)(a) match {
      case n if(n==Turn.thisTurn)  => true
      case n if(n==Turn.otherside) => chk_square_a(a + dr._1,b + dr._2,dr)
      case _                       => false
    }
  } 

  def flip(){
    board(y)(x) = Turn.thisTurn
    for(dr <- dir){
      if(board(y + dr._2)(x + dr._1)==Turn.otherside){
        flip_a(x + dr._1 * 2,y + dr._2 * 2,dr)
      }
    }
  }

  def flip_a(a:Int,b:Int,dr:(Int,Int)):Unit = {
    board(b)(a) match {
      case n if(n==Turn.thisTurn)  => flip_b(a - dr._1,b - dr._2,dr)
      case n if(n==Turn.otherside) => flip_a(a + dr._1,b + dr._2,dr)
      case _                       => ;
    }
  }

  def flip_b(a:Int,b:Int,dr:(Int,Int)):Unit = {
    if (board(b)(a)!=Turn.otherside){
      ;
    } else {
      board(b)(a) = Turn.thisTurn
      flip_b(a - dr._1,b - dr._2,dr)
    }
  }
}

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
nogitsune413
社内SEとして働いています。 学んだ事や調べた技術を投稿しています。
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?