2016-11-16 57 views
1

我正在爲Java控制檯開發Connect Four遊戲。我在獲勝條件方面存在問題,因爲我不知道如何編程。這裏是我的代碼我公司主營:控制檯中的Java Connect Four - 水平和垂直獲勝條件

public class Main { 

public static char[] playerNumber = new char[]{'1', '2'}; 
public static char[] Badge = new char[]{'X', 'O'}; 

public static void main(String[] args) { 
    Scanner scanner = new Scanner(System.in); 
    int moves = 7 * 6; 
    int whichPlayer = 0; 

    for (int i = 0; i < 10; i++) { 
    System.out.println("     FOUR IN A ROW"); 
    System.out.println("-------------------------------------------------------"); 
    System.out.println("Welcome to the amazing game Four In A Row:"); 
    System.out.println("Enter a number between 0 and 6 for choosing a column."); 
    System.out.println(); 

     Board board = new Board(); 
     board.fillBoard(); 
     board.presentBoard(); 

     do { 
      // 1. get a badge 
      char Player = playerNumber[whichPlayer]; 
      char badge = Badge[whichPlayer]; 

      // 2. make a turn 
      board.makeTurn(badge, Player); 
      board.presentBoard(); 

      // 3. Tjek om der er vinder 
      if (board.checkWinHorizontal() || board.checkWinVertical()) { 
       System.out.println("Player " + Player + " has won!"); 
       break; 
      } 

      // 4. change the player 
      whichPlayer = 1 - whichPlayer; 

      // 5. decrease moves 
      --moves; 

      if (moves == 0) { 
       System.out.println("Game over, nobody has won."); 
       System.out.println("Do you want to play again? 'Y' or 'N':"); 
       String newGame = scanner.nextLine(); 
       if (newGame.equals("Y") || newGame.equals("y")) { 
        break; 
       } 
       if (newGame.equals("N") || newGame.equals("n")) { 
        System.out.println("Thanks for the game!"); 
        return; 
       } 
      } 
      // 6. repeat 
     } while (true); 
    } 
} 

這裏是我爲我的主板類代碼:

public class Board { 

char[][] board = new char[6][7]; 

int column; 

// Fills the empty spaces 
public void fillBoard() { 
    for (int i = 0; i < 6; i++) { 
     for (int j = 0; j < 7; j++) { 
      board[i][j] = ' '; 
     } 
    } 
} 

// Prints the board 
public void presentBoard() { 
    for (int i = 0; i < 6; i++) { 
     System.out.print("   | "); 
     for (int j = 0; j < 7; j++) { 
      System.out.print(board[i][j] + " | "); 
     } 
     System.out.println(); 
     System.out.print("   -----------------------------"); 
     System.out.println(); 
    } 
} 

// Turn 
public void makeTurn(char badge, char Player) { 
    Scanner scanner = new Scanner(System.in); 
    do { 
     // 1. Ask for a column 
     System.out.println("Player " + Player + " turn: "); 
     column = scanner.nextInt(); 

     // 2. Check if it's between 0 and 6 
     if (column > 6) { 
      System.out.println("That is not a valid number. Please enter a number between 0 and 6: "); 
      continue; 
     } 

     // 3. Place a badge 
     for (int i = 6 - 1; i >= 0; i--) { 
      if (board[i][column] == ' ') { 
       board[i][column] = badge; 
       return; 
      } 
     } 

     // If column is full 
     System.out.println("Column " + column + " is full. Try another column:"); 

    } while (true); 
} 

// Check for vertical win 
public boolean checkWinVertical() { 
      return verticalWin(5, column); 
    } 

// Check for horizontal win 
public boolean checkWinHorizontal() { 
    return horizontalWin(5,column); 
} 

// Conditions for vertical win 
private boolean verticalWin(int x, int y) { 
    char charToCheck = board[x][y]; 
    if (board[x-1][y] == charToCheck && 
     board[x-2][y] == charToCheck && 
     board[x-3][y] == charToCheck) { 
     return true; 
    } 

    return false; 
    } 

// Conditions for horizontal win 
private boolean horizontalWin(int x, int y) { 
    char charToCheck = board[x][y]; 
    if (board[x][y+1] == charToCheck && 
      board[x][y+2] == charToCheck && 
      board[x][y+3] == charToCheck) { 
     return true; 
    } 
    return false; 
} 

我已經成功地得到了比賽的水平和垂直認識到勝利在底排我數組,但我不知道如何讓整個數組的遊戲識別。我只專注於水平和垂直,因爲對角線對我來說太複雜了。我不知道這是正確的方法,還是有更好的方法。 謝謝!

+0

什麼意思,你是如何成功地檢查贏的條件,但不是整個陣列?有時候水平或垂直的勝利檢查失敗,即使有水平或垂直的勝利? – NESPowerGlove

回答

1

這是另一種解決方案。這與前面提到的一樣:通過循環遍歷每一行/列,檢查連續4行。也許這個實現會提供一些其他的見解。下面,我展示了一個檢查水平條紋的示例方法。對於垂直,您可以迭代inner for循環中的行。

public boolean checkWin(char badge) { 
    return checkHorizontalStreaks(board, badge) 
      || checkVerticalStreaks(board, badge); 
} 

private boolean checkHorizontalStreaks(char[][] board, char badge) { 
    for (int row = 0; row < board.length; row++) { 
     // loop throught each row 
     int currentStreak = 0; 
     for (int col = 0; col < board[row].length; col++) { 
      // loop through each column in the row 
      if (board[row][col] == badge) { 
       // keep the streak of 'badge' going 
       currentStreak++; 
       if (currentStreak == 4) { 
        // winner 
        return true; 
       } 
      } else { 
       // restart the streak 
       currentStreak = 0; 
      } 
     } 
    } 
    return false; 
} 

然後用

 if (board.checkWin(badge)) { 
      System.out.println("Player " + Player + " has won!"); 
      break; 
     } 

我打賭有一種更有效的方式來確定獲獎者(或許是治療電網爲曲線圖與一些特殊的穿越它更新您的主類邏輯)。不過,我懷疑這可能足以滿足您的需求。我會爲您提供輸出,但它可以處理幾個不同的測試案例。

0

可能你可以檢查最後播放字段周圍的所有相鄰字段,所以在用戶輪到他後。因此,對於檢查向上,你可以這樣做:

public boolean checkUp(int rowPlayed, int columnPlayed){ 
     boolean checked = false; 
     if(rowplayed + 1 <= maxrows){ //Checks if you didn't hit the top 
      if(board[rowPlayed+1][columnPlayed] != null){ 
       if(board[rowPlayed+1][columnPlayed].getPlayer() == currentPlayer){ 
        checked = true; 
       } 
      } 
     } 
     return checked; 
    } 

和實施,例如像這樣:

public void checkWin(int rowPlayed, int columnPlayed){ 
     boolean checkingWin = true; 
     int countWin = 0; 
     while(checkingWin){ 
      if(checkUp(rowPlayed + countWin, columnPlayed)){ 
       countWin++; 
      } 
      else{ 
       checkingWin = false; 
      } 
      if(countWin == 4){ 
       checkinWin = false; 
       //Insert win confirmation here 
      } 
     } 
    } 

這是部分僞代碼,因爲我不知道你到底如何處理你的代碼的東西,也不我知道這是否是最好的方式嗎?但我希望這對你有所幫助。

0

這是一個漫長的答案,我會去的房前屋後了一點,所以你可以看到我是如何得出我的解決方案(也擴大在結束對角檢查)。

我會用最後一塊作爲起點,並從那裏開始工作,因爲檢查所有組合都是詳盡無用的。

鑑於添加的最後一塊的行和列,我需要決定我需要實現的內容。

我已經知道當前的行和列有我正在尋找的顏色,所以我可以忽略它。

對於水平比較,我想檢查我要檢查件左右的同一行中具有相同的顏色,並停止,如果顏色是不同的或者有任何一塊。

所以,想象下面的板(#=空,R =紅段子,Y =黃段子:

6 # # # # # # # # 
5 # # # # # # # # 
4 # # # # # # # # 
3 # # # # # # # # 
2 # # # # # # # # 
1 # # # # # # # # 
0 Y R R R Y Y Y R 
    0 1 2 3 4 5 6 7 

最後此舉是黃色的,0行,列4

所以我想要檢查左和從[0] [4]和看顏色的連續的片的總數爲3,(未4),因爲我知道[0] [4]是黃色和可以打折。

基於此,我可以採取遞歸的方法,我檢查一邊的相鄰,然後遞歸地做同樣的事情作爲l因爲我保持匹配相同顏色的棋子或者不會遇到空插槽。

我會用支票向右側開始的(證明):

private static final int COLS = 7; 
private static final int ROWS = 6; 
public enum Piece {RED, YELLOW}; // null is empty 

private Piece[][] board = new Piece[ROWS][COLS]; // the board 

private int checkRight(Piece piece, int row, int col) { 
    // assume valid row for now 
    col++; // moving col to the right 
    if (col >= COLS || board[row][col] != piece) { 
     // We're outside the limits of the column or the Piece doesn't match 
     return 0; // So return 0, nothing to add 
    } else { 
     // otherwise return 1 + the result of checkRight for the next col 
     return 1 + checkRight(piece, row, col); 
    } 
} 

現在,我可以在同一個執行到左邊。

private int checkLeft(Piece piece, int row, int col) { 
    // assume valid row for now 
    col--; // moving col to the left 
    if (col < 0 || board[row][col] != piece) { 
     // We're outside the limits of the column or the Piece doesn't match 
     return 0; // So return 0, nothing to add 
    } else { 
     // otherwise return 1 + the result of checkLeft for the next col 
     return 1 + checkLeft(piece, row, col); 
    } 
} 

,並檢查水平贏家,我能做到這一點:

public boolean checkWinner(Piece piece, int row, int col) { 
    // if the sum is 3, we have a winner (horizontal only). 
    return checkRight(piece, row, col) + checkLeft(piece, row, col) == 3; 
} 

唉,有很多重複的,不是嗎?

我們可以通過引入新的參數direction凝結的兩種方法之一,如果我們移動山坳正或負過值1和-1分別可以改變:

private int check(Piece piece, int row, int col, int direction) { 
    col += direction; // direction is either 1 (right) or -1 (left) 
    if (col < 0 || col >= COLS || board[row][col] != piece) { 
     return 0; 
    } else { 
     return 1 + check(piece, row, col); 
    } 
} 

更新checkWinner()這個新參數:

private static final int POSITIVE = 1; // right at the moment 
private static final int NEGATIVE = -1; // left at the moment 

public boolean checkWinner(Piece piece, int row, int col) { 
    // if the sum is 3, we have a winner (horizontal only). 
    return check(piece, row, col, POSITIVE) + check(piece, row, col, NEGATIVE) == 3; 
} 

現在我可以實現同一類垂直邏輯,而是留在同一col並更改row。我將詳細跳過這一部分,並轉向包含此項和對角線檢查的解決方案。

這已被使用,其rowcol應該改變,並用於通過check()方法的enum稱爲CheckType存儲值來完成。例如爲HORIZONTAL由1或-1的列中的更改(取決於指定的方向時check()被調用)和行保持爲0

public class Board { 

    public enum Piece { 

     RED, YELLOW 
    }; 

    private enum CheckType { 

     HORIZONTAL(0, 1), VERTICAL(1, 0), DIAGNONAL_UP(1, 1), DIAGNONAL_DOWN(-1, 1); 

     int row; 
     int col; 

     CheckType(int row, int col) { 
      this.row = row; 
      this.col = col; 
     } 
    } 

    private static final int POSITIVE = 1; 
    private static final int NEGATIVE = -1; 

    private static final int ROWS = 6; 
    private static final int COLS = 7; 

    private Piece[][] board = new Piece[ROWS][COLS]; 
    private boolean hasWinner = false; 

    public boolean hasWinner() { 
     return hasWinner; 
    } 

    private void checkWinner(Piece piece, int row, int col) { 
      // check all values of enum CheckType for a winner 
     // so HORIZONTAL, VERTICAL, etc.. 
     int enumIndex = 0; 
     while (!hasWinner && enumIndex < CheckType.values().length) { 
      hasWinner = check(piece, row, col, POSITIVE, CheckType.values()[enumIndex]) 
        + check(piece, row, col, NEGATIVE, CheckType.values()[enumIndex]) == 3; 
      enumIndex++; 
     } 
    } 

    private int check(Piece piece, int row, int col, int direction, CheckType type) { 
     row += type.row * direction; 
     col += type.col * direction; 
     if (row >= ROWS || row < 0 || col >= COLS || col < 0 || board[row][col] != piece) { 
      return 0; 
     } else { 
      return 1 + check(piece, row, col, direction, type); 
     } 
    } 

    // for completeness, adding a Piece  
    public boolean add(Piece piece, int col) { 
     int row = 0; 
     while (row < ROWS && board[row][col] != null) { 
      row++; 
     } 
     if (row < ROWS) { 
      board[row][col] = piece; 
      // check for winner after successful add 
      checkWinner(piece, row, col); 
     } 
     return row < ROWS; 
    } 

} 

希望這有助於。