2014-09-29 66 views
3

我想在Java中製作一個可以在控制檯上玩的國際象棋遊戲。對於每一次移動,遊戲向玩家詢問棋子(例如對於第二行,第三列中的棋子爲12)和最終位置(例如對於第四行,第三列爲32)。一切工作都很完美,包括測試以確定移動是否非法,以及是否有給定的玩家處於檢查狀態,但我的gameOver布爾值似乎正在改變我的板陣列的價值,然後才問第一步。用Java編寫國際象棋遊戲,而gameOver布爾型不起作用

這裏是相關的代碼。從我的主要方法:

public static void main(String[] args) { 
    int[][] board = { {12, 13, 14, 15, 16, 14, 13, 12}, 
         {11, 11, 11, 11, 11, 11, 11, 11}, 
         {0, 0, 0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0, 0, 0}, 
         {0, 0, 0, 0, 0, 0, 0, 0}, 
         {21, 21, 21, 21, 21, 21, 21, 21}, 
         {22, 23, 24, 25, 26, 24, 23, 22} 
        }; 
    Scanner scan = new Scanner(System.in); 
    boolean oneTurn = true; 
    while(!(gameOver(oneTurn, board))) { 
     printBoard(board); 
     System.out.println(((oneTurn) ? "1's" : "2's") + " turn"); 
     System.out.print("What piece? "); 
     int origin = scan.nextInt(); 

的GAMEOVER布爾,測試,看看是否有任何移動當前播放器可以使是合法的,不會讓玩家在辦理入住手續:

public static boolean gameOver(boolean oneTurn, int[][] board) { 
    for (int a = 0; a<8; a++) { 
     for(int b = 0; b<8; b++) { 
      for (int c = 0; c<8; c++) { 
       for(int d = 0; d<8; d++) { 
        if(board[a][b]/10 == (oneTurn ? 1 : 2) && !(illegal(oneTurn, 10*a+b, 10*c+d, board)) && !(illegalCheck(oneTurn, 10*a+b, 10*c+d, board))) return false; 
       } 
      } 
     } 
    } 
    return true; 
} 

該檢查方法,它試圖找到一個合法的移動其他球員可以做到這一點將消除王:

public static boolean check(boolean oneTurn, int[][] board) { 
    int king = kingNum(oneTurn, board); 
    for (int a = 0; a<8; a++) { 
     for(int b = 0; b<8; b++) { 
      if(board[a][b]/10 == (oneTurn ? 2 : 1) && !(illegal(!oneTurn, 10*a+b, king, board))) return true; 
     } 
    } 
    return false; 
} 

的illegalCheck方法,測試,看是否有此舉將播放器放在檢查。我認爲這是問題所在。我試圖做一個單獨的newBoard,以便原來的板不會改變,但它仍然會產生問題。

public static boolean illegalCheck(boolean oneTurn, int origin, int dest, int[][] board) { 
    int[][] newBoard = board; 
    newBoard[dest/10][dest % 10] = board[origin/10][origin % 10]; 
    newBoard[origin/10][origin % 10] = 0; 
    if(check(oneTurn, newBoard)) return true; 
    else return false; 
} 

當我運行的第一次節目,第一輸出我得到的是這樣的:

| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 
_____________________________________________ 

0 | 1R | | 1B | 1Q | 1K | 1B | 1N | 1R | 
_____________________________________________ 

1 | 1P | 1P | 1P | 1P | 1P | 1P | 1P | 1P | 
_____________________________________________ 

2 | | | | | | | | | 
_____________________________________________ 

3 | | | | | | | | | 
_____________________________________________ 

4 | | | | | | | | | 
_____________________________________________ 

5 | | | | | | | | | 
_____________________________________________ 

6 | 2P | 2P | 2P | 2P | 2P | 2P | 2P | 2P | 
_____________________________________________ 

7 | 2R | 2N | 2B | 2Q | 2K | 2B | 2N | 2R | 
_____________________________________________ 

1's turn 
What piece? 

通過GAMEOVER找到的第一個合法的移動是騎士的移動,所以我想這就是爲什麼騎士沒有出現在第一塊板上。當我在布爾測試之前放置printBoard方法時,電路板完美打印。

我剛剛開始學習編程最近,所以我將不勝感激任何意見,爲什麼會發生這種情況。這可能是我錯過的公然顯而易見的事情。讓我知道是否有其他細節我可以提供。謝謝!

+0

您的gameOver函數根本不可讀。選擇一些有意義的變量名稱有多困難,而不要過於幻想? – 2014-09-29 02:49:55

+0

這並不壞。沒必要。另外,它爲什麼不可讀?爲什麼它「太花哨」?隨意編輯它沒有絨毛。 – theGreenCabbage 2014-09-29 03:08:14

+0

抱歉,缺乏清晰度。我認爲這將是一個快速學習項目,我自己的代碼只能閱讀,但這個小問題讓我感到沮喪,不得不訴諸外部來源。 gameOver中的字母只是數組的索引(行a,列b到行c,列d)。非法檢查可能是一個不好的變量名,但它會測試看看從ab到cd的移動是否會讓玩家檢查。 – Greg 2014-09-29 03:18:50

回答

1

當你寫

int[][] newBoard = board; 
newBoard[dest/10][dest % 10] = board[origin/10][origin % 10]; 
newBoard[origin/10][origin % 10] = 0; 

你創建newBoard作爲新的基準同一個數組對象board,然後着手修改數組。您可以直接複製像這樣:

int[][] newBoard = new int[8][]; 
for (int i = 0; i < newBoard.length; ++i) 
    newBoard[i] = board[i].clone(); 

Java的多維數組是其他數組的引用數組(因爲數組是對象),所以首先我們創建一個新的頂級陣列,然後分配給下屬陣列的複製進去。 (有關於Object.clone()Cloneable的一系列規則,但您在此需要知道的一點是克隆數組會生成一個具有相同值的新數組。對於多維數組,這是一個淺拷貝(副本指的是相同的輔助數組),所以我們不能只調用board.clone()並完成它。)

+0

謝謝,我認爲該解決方案工作!因此,爲了將來的參考,很明顯,整個程序中的每個頂級數組都可以訪問相同的二級數組。但是頂層數組也是一樣的,或者我可以有兩個名爲board的數組引用不同的東西嗎? – Greg 2014-09-29 04:43:50

+1

你可以有兩個名爲'board'的引用指向不同的數組,是的。 (例如,如果一個類有一個名爲'board'的字段,則該類的每個實例可以引用來自該字段的不同數組,例如,與使用不同或遞歸方法的本地數據類似)。數組本身不知道指向哪個引用他們。但只是賦值'board = ...'不會創建一個新的數組,除非'...'包含'new'或者調用一個記錄庫函數來返回一個新數組。 – 2014-09-29 04:48:15

1

如果您認爲這是由於陣列的副本造成的,請在非法檢查中嘗試使用System.arraycopy

+0

我改變了我的初始化爲: \t \t int [] [] newBoard = new int [8] [8]; System.arraycopy(board,0,newBoard,0,board.length); 但它沒有奏效。這是arraycopy的正確使用?謝謝您的幫助! – Greg 2014-09-29 03:20:03

0

我會建議使用調試器並設置一些斷點,以便您可以看到究竟發生了什麼,這樣您就不會猜測。

更多關於調試會話信息與Java:http://docs.oracle.com/javase/7/docs/technotes/tools/windows/jdb.html

+0

感謝您的提示。我完全沒有使用調試器的經驗,但我會試一試。你知道一個布爾值可能如何以不同的方法改變一個變量嗎?我的理解是變量只能在他們自己的方法內改變,但在這種情況下似乎是不正確的。 – Greg 2014-09-29 04:12:39

+0

我還沒有真正看過整個代碼,如果你需要幫助,你可以創建一個測試用例,重現相同的行爲,如果它,編輯你的問題,並只發布測試用例。另外,我沒有看到一個gameOver布爾變量,而是看到一個帶有該標識符的方法。做一個測試用例或使用調試器,這應該是你最好的選擇。 – emerino 2014-09-29 04:22:59