EclipseでScalaに触ってみる（1）～ボウリングのスコア計算～

職場でScalaが話題に出ていたので、触ってみました。

ただScalaの書き方で書いてみただけで言語特性とか何も生かせてない気がしますが、
ボウリングのスコア計算プログラムを作ってみました。

# 準備
* Eclipse 4.4 Luna（Pleiades）に「Scala IDE」をインストール

下記の「4.1.0 Release」のURLからインストール
http://download.scala-ide.org/sdk/lithium/e44/scala211/stable/site

# 動作確認
* プロジェクト・エクスプローラーなどで右クリックして「新規→その他→Scalaウィザード→Scalaプロジェクト」を選択
* プロジェクト名をつけて保存
* 完了をクリック
* プロジェクトを右クリックして「新規→Scalaオブジェクト」を選択
* 名前に「Hello」と入力し、完了をクリック
* 作成された「Hello.scala」ファイルに下記のように記述する

```scala:Hello.scala
object Hello {
    def main(args:Array[String]) = {
        println("Hello World!!")
    }
}
```

* 「Hello.scala」ファイルを右クリックして「実行→Scalaアプリケーション」を選択
* コンソールに「Hello World!!」が表示されることを確認

# ボウリングスコア計算プログラム
## プロジェクト構成・実行結果
![qiita_20150614_001.png](https://qiita-image-store.s3.amazonaws.com/0/53590/73914768-dd65-dd35-efa7-782688c2010b.png)
## 入力データファイル

```scala:Result.scala
object Result {

  def game1() : List[List[String]] = {
    var f1 = List("G", "8")
    var f2 = List("G", "-")
    var f3 = List("G", "3")
    var f4 = List("6", "3")
    var f5 = List("7", "-")
    var f6 = List("2", "6")
    var f7 = List("9", "/")
    var f8 = List("6", "/")
    var f9 = List("8", "1")
    var f10 = List("6", "-", null)
    List(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
  }

  def game2() : List[List[String]] = {
    var f1 = List("7", "2")
    var f2 = List("8", "/")
    var f3 = List("5", "1")
    var f4 = List("9", "-")
    var f5 = List("X", "-")
    var f6 = List("3", "4")
    var f7 = List("9", "/")
    var f8 = List("X", "-")
    var f9 = List("9", "/")
    var f10 = List("G", "3", null)
    List(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
  }

  def game3() : List[List[String]] = {
    var f1 = List("9", "/")
    var f2 = List("6", "2")
    var f3 = List("9", "/")
    var f4 = List("5", "4")
    var f5 = List("5", "/")
    var f6 = List("9", "/")
    var f7 = List("X", "-")
    var f8 = List("X", "-")
    var f9 = List("X", "-")
    var f10 = List("X", "X", "X")
    List(f1, f2, f3, f4, f5, f6, f7, f8, f9, f10)
  }
}
```

## スコア計算プログラム

```scala:Hello.scala
object Bowling {

  val totalFrame:Int = 10

  def main(args: Array[String]) {
    calc(Result.game1)
    calc(Result.game2)
    calc(Result.game3)
  }

  private def calc(frames: List[List[String]]) {
    var total = 0
    var resultPrint = ""
    var totalPrint = "";

    for(frameNo <- 1 to totalFrame) {
      val index = frameNo - 1
      val frame = frames(index)
      var result3 = " "

      if (frameNo == totalFrame) {
        total += getLastFrameScore(frame)

        if (frame(2) != null) {
          result3 = frame(2)
        }
      } else {
        var next1 = frames(index + 1)
        var next2:List[String] = null
        if (index + 2 < totalFrame) {
          next2 = frames(index + 2)
        }

        total += getFrameScore(frame, next1, next2)
      }

      resultPrint += "|" + frame(0) + frame(1) + result3
      totalPrint += "|" + total.toString.padTo(3, ' ')
    }
    printTable(resultPrint, totalPrint)
  }

  private def getLastFrameScore(frame : List[String]): Int = {
    if (frame(0) == "X") {
      stringToScore(frame(0)) + getPairScore(frame(1), frame(2))
    } else if (frame(1) == "/") {
      spare(frame, frame(2))
    } else {
      getPairScore(frame)
    }
  }

  private def getFrameScore(frame : List[String], next1 : List[String], next2 : List[String]): Int = {
    if (frame(0) == "X") {
      strike(frame, next1, next2)
    } else if (frame(1) == "/") {
      spare(frame, next1(0))
    } else {
      getPairScore(frame)
    }
  }

  private def printTable(resultPrint : String, totalPrint : String) {
    printFrame
    printSeparator
    println(resultPrint + "|")
    printSeparator
    println(totalPrint + "|")
    println()
  }

  private def printFrame() {
    println("|1  |2  |3  |4  |5  |6  |7  |8  |9  |10 |")
  }

  private def printSeparator() {
    println("|---|---|---|---|---|---|---|---|---|---|")
  }

  private def strike(frame: List[String], next1: List[String], next2: List[String]) : Int = {
    var score = getPairScore(frame)

    if (next1(0) == "X" && next2 != null) {
      score + stringToScore(next1(0)) + stringToScore(next2(0))
    } else {
      score + getPairScore(next1)
    }
  }

  private def spare(frame: List[String], next: String) : Int = {
    getPairScore(frame) + stringToScore(next)
  }

  private def getPairScore(score: List[String]) : Int = {
    getPairScore(score(0), score(1))
  }

  private def getPairScore(result1: String, result2: String) : Int = {
    if (result1 == "X" && result2 == "-") {
      stringToScore(result1)
    } else if (result2 == "/") {
      10
    } else {
      stringToScore(result1) + stringToScore(result2)
    }
  }

  private def stringToScore(str: String) : Int = {
    if (str == "X") {
      10
    } else if (str == "G") {
      0
    } else if (str == "-") {
      0
    } else {
      str toInt
    }
  }
}
```