2016-08-21 65 views
1

我有一個連接四個「板」,這是一個6 * 7的二維字符數組,填充了空格,X或O.勝利條件滿足時,垂直,水平或對角線連續排列四個X或四個Os。我已經成功地獲得勝利條件檢查成功垂直和水平位置,其中獲勝的char是一些方法如下返回:Java:如何檢查對角線連接四維贏得二維數組

private char CheckVerticalWinner(char[][] currentBoard) { 
    // check vertical (move down one row, same column) 
    char vWinner = ' '; 
    for (int col=0; col<7; col++) { 
     int vCount = 0; 
     for (int row=0; row<5; row++) { 
      if (currentBoard[row][col]!=' ' && 
       currentBoard[row][col] == currentBoard[row+1][col]) { 
       vCount++; 
       System.out.println("VERT "+vCount); //test 
      } else { 
       vCount = 1; 
      } 

      if (vCount>=4) { 
       vWinner = currentBoard[row][col]; 
      } 
     } 
    } 
    return vWinner; 
} 


private char CheckHorizontalWinner(char[][] currentBoard) { 
    // check horizontal (move across one column, same row) 
    char hWinner = ' '; 
    for (int row=0; row<6; row++) { 
     int hCount = 0; 
     for (int col=0; col<6; col++) { 
      if (currentBoard[row][col]!=' ' && 
       currentBoard[row][col] == currentBoard[row][col+1]) { 
       hCount++; 
       System.out.println("HORIZ "+hCount); //test 
      } else { 
       hCount = 1; 
      } 

      if (hCount>= 4) { 
       hWinner = currentBoard[row][col]; 
      } 
     } 
    } 
    return hWinner; 
} 

我只是停留在如何檢查對角線勝未拋出一個ArrayIndexOutOfBoundsException。我知道我需要通過2D陣列來迭代兩次,一次用於前向對角線,一次用於後向對角線是4個方格長或更多,如下面圖中:

Diagonals to be checked diagram

基本上,如何將我填寫這個方法返回一個成功的char?

private char CheckDiagonalWinner(char[][] currentBoard) { 

    // some iteration here 

    return dWinner; 
} 

任何幫助將不勝感激!

+0

是不是妨礙自己超過董事會的範圍內的一個簡單的事情?對於一個N×M的板子,你只需要考慮'(0,0)'到'(N-4,M-4)'的子矩陣,例如右邊的對角線,左到右下。 –

+0

作爲建議,我建議你製作一種方法,接受網格的起始行和列,然後在特定方向上「掃描」至少4個值。當一行中有4個值時,它可以返回一個布爾值。 –

+1

提示:嘗試提出更有意義的抽象:使用兩個字符的字符是一個非常低層次的抽象爲您的目的。相反,您可以使用枚舉來表示單元中的單元格。換句話說:不要選擇矩陣必須是二維數組的「立即」思想。花一些時間思考,如果組織單元的不同形式可能使其他事情變得更容易。 – GhostCat

回答

4

最簡單的算法可能是:

for every direction 
    for every coordinate 
     check whether the next 3 elements in this direction exist and are the same 

代碼:

final int maxx = 7; 
final int maxy = 6; 

char winner(char[][] board) { 
    int[][] directions = {{1,0}, {1,-1}, {1,1}, {0,1}}; 
    for (int[] d : directions) { 
     int dx = d[0]; 
     int dy = d[1]; 
     for (int x = 0; x < maxx; x++) { 
      for (int y = 0; y < maxy; y++) { 
       int lastx = x + 3*dx; 
       int lasty = y + 3*dy; 
       if (0 <= lastx && lastx < maxx && 0 <= lasty && lasty < maxy) { 
        char w = board[x][y]; 
        if (w != ' ' && w == board[x+dx][y+dy] 
           && w == board[x+2*dx][y+2*dy] 
           && w == board[lastx][lasty]) { 
         return w; 
        } 
       } 
      } 
     } 
    } 
    return ' '; // no winner 
} 
+0

感謝您的直接解決方案。然而,我剛剛嘗試過,它會拋出一堆ArrayIndexOutOfBoundsExceptions。我看到你去了哪裏,只是有點混淆,找出哪些循環修改來解決這個問題... –

+0

不會爲我拋出異常。我們是否同意「棋盤」的尺寸? (按照我的設想,是'board [7] [6]'還是'board [6] [7]')? – meriton

+0

啊,剛剛意識到我的問題中的錯字。它實際上是我的代碼中的[board] [6] [7]'。感謝您指出,併爲解決方案! –

2

首先,您無需在任何給定的時間檢查整個主板,我認爲這是在您的代碼中完成的。要優化代碼並使其更簡單,您可以執行以下操作:

在檢查電路板上的任何方向之前,首先用用戶輸入填充電路板。這意味着每當你得到新的輸入時,你所做的第一件事就是使用該輸入並更新你的矩陣。這樣我們總是有更新的矩陣,我們可以做下一步的工作:

獲取用戶輸入的x和y。這意味着,如果用戶選擇第2行,則將矩陣填充到第2行和第4列。我們如何處理這些座標?我們使用THEM並將它們發送給連續檢查矩陣4的方法。這使我們不能檢查整個矩陣,而只檢查填充矩陣。

在垂直檢驗,你現在只能從這些座標,檢查下來,例如:

boolean winner = false; 

count = 1; 

if (x > 3) 

for (i = 0; i < 3; i++) { 

    if (A[x][y-i] == 'X') 

     count ++; 

    if (count == 4) { 

     winner = true; 

     return; 

    } 

對於水平的檢查,做同樣的,但水平。您需要兩個循環來檢查左側和右側。

對於對角線檢查,現在您只需檢查包含設置座標的對角線。例如,如果用戶輸入第4行和第5列,對於左對角線,我們需要檢查(5,4),(6,3)和(7,2)。

使用座標來檢查贏家是非常簡單的,它允許我們只檢查矩陣的填充部分。

對不起,這是從手機上寫下來的,如果你願意,我可以更新並添加更多的例子。

+0

如果插入的最後一個元素位於4的中間怎麼辦? (如果左邊的兩個元素和右邊的元素是相同的,我們也有一個贏家......) – meriton

+0

您可以簡單地在循環的左右兩邊計算++,如果到達終止字符,只要打破循環。這段代碼需要一點工作,我沒有給出完整的工作示例。但是如果我沒有弄錯,其中n是7×6,OP的代碼複雜度爲O(n^2 + n^2 + 4n)。 – leonz