2017-04-04 16 views
1

私はScalaと関数型プログラミングの新機能です。私はチック・タック・トー・ゲーム(「7つの週の7つの言語(書籍)」の第1日目)を作成しています。機能的な方法で「勝ち」の方法を知りたいのですが。Scalaでarray.exists()を使用する

'checkcolumn'(2番目の部分)のような 'checkrow'部分(最初の部分)を作りたいと思っていますが、私が試しているのは動作していません。

ここに私の(作業)コード:

def checkGame() { 
    for (y <- board.indices) { 
     // checks a row 
     checkRow(y) 
    } 
    for (x <- board(0).indices) { 
     // checks a column 
     if(!board.exists(y => y(x) != 'x')){ 
     println("You have won mate! (column: " + x + ")") 
     } 
    } 
    } 

def checkRow(y: Integer) { 
var isWon = true 
for (x <- board(y).indices) { 

    if (board(y)(x) != 'x') { 
    isWon = false 
    } 
} 
if (isWon) println("You have won mate! (row: " + y + ")") 
} 

注:ボードは、2次元配列です。

私がこれまでに得たもの(動作しない):

if(!board.exists(x => x(y) != 'x')){ 
     println("You have won mate! (row: " + x + ")") 
} 
+1

あなたは 'for' loppsと可変変異を使用している場合、「機能的な方法で」実行していません。 – RichouHunter

答えて

6

などexistsとして高階関数を持っていることの全体のポイントは、あなたのArray使用してインデックスをトラバースすることを避けるためです。ここで

は、私はそれを行うだろうかです:

def wonRow(row: Array[Char]): Boolean = row.forall(c => c == 'x') 

これは、配列のすべての要素が述語を満たしている場合(ここでは、すべての要素が'x'でなければならない)をチェックforallメソッドを使用します。ここで

def wonSomeRow(board: Array[Array[Char]]: Boolean = board.exists(row => wonRow(row)) 

、我々は列の場合

配列(その任意の行)の任意の要素は、(勝利の行であることを、ここに)述語を満たしている場合、一部の行が勝利を作ることを考慮し、これは何とかです最も簡単な方法は、あなたが開始したとして行うことですので、より複雑な:

def wonColumn(board: Array[Array[Char]], col: Int) = board.forall(row => row(i) == 'x') 

def wonSomeColumn(board: Array[Array[Char]]) = (0 until board(0).size).exists(i => wonColumn(board, i)) 

しかし、私は強くあなたには、いくつかのエラーを避けるために、あなたのコードの先頭にいくつかの定数でboard(0).sizeを交換することをお勧めします。実際、これは

  • 1)boardリストサイズもちろんboard(0).size

に有する第一行

  • 2)board内のすべての行を持っていることを前提とし、これら2つの仮定は、Tic-でOKですTac-Toeであるが、関数型プログラミングでは、このようなコンパイル時の仮定をコンパイル時に検証するために型システムに入れるべきである。しかし、これは、この種のもので関数型プログラミングを開始するためのかなりの一歩を踏み出すでしょう(それらが存在することを知っているだけです)。あなただけ(の列に)行うことができますので、私はちょうど、アレイ上の方法transposeがある思い出し

    EDIT

    def wonSomeCol(board: Array[Array[Char]]) = wonSomeRow(board.transpose) 
    
  • 1

    うーん...一つの機能的なアプローチは、使用することができfoldLeft。ここでは、Intの2つのSetから始めます。それぞれwinRowsとwinColumnsにすべての行と列があります。

    次に、勝利条件を満たさないrowscolumnsを除去するために、ゲームボードを折りたたんでいます。

    def findVictoryRowsAndColumns(board: Array[Array[Char]], height: Int, width: Int): (Set[Int], Set[Int]) = { 
        val winRowsInit = (1 to height).toSet 
        val winColumnsInit = (1 to width).toSet 
    
        val (winRows, winColumns) = board.zipWithIndex.foldLeft((winRowsInit, winColumnsInit))({ 
        case ((winRows1, winColumns1), (row, rowIndex)) => row.zipWithIndex.foldLeft(winRows1, winColumns1)({ 
         case ((winRows2, winColumns2), (cell, columnIndex)) => cell match { 
         case 'x' => (winRows2, winColumns2) 
         case _ => (winRows2 - rowIndex, winColumns2 - columnIndex) 
         } 
        }) 
        }) 
    
        (winRows, winColumns) 
    } 
    
    def checkGame(board: Array[Array[Char]], height: Int, width: Int): Unit = { 
        val (winRows, winColumns) = findVictoryRowsAndColumns(board, height, width) 
    
        winRows.foreach(i => println("You have won in Row : " + i)) 
        winColumns.foreach(i => println("You have won in Column : " + i)) 
    } 
    
    関連する問題