2014-04-30 16 views
6

Câu hỏi này khá lớn và khó giải quyết mà không cần xem mã của tôi, và nếu nó quá lớn, thì phạm vi có thể quá lớn và tôi sẽ xóa câu hỏi. Về cơ bản tôi có một trò chơi cờ vua làm việc với tất cả các quy tắc của cờ vua trừKiểm tra(vàdo đó cũng không Checkmate, bế tắc, vv) thực hiện.Thực hiện "Kiểm tra" trong Trò chơi Cờ vua

Tôi đã thực hiện Kiểm tra bằng cách chỉ định Hình vuông của Cờ vua của tôi hai booleans: protectedByWhiteprotectedByBlack. Có hai phần chính của logic với kiểm tra:

  • Nếu một động thái được thực hiện bởi trắng gây vua của mình để được trên một vuông đó là protectedByBlack, và ngược lại với Black, động thái này là "hoàn tác" .
  • Nếu di chuyển được thực hiện bởi Trắng khiến vua của Black ở trên một hình vuông là protectedByWhite và ngược lại với chuyển động tiếp theo của Black, Black phải đặt vua của mình trên một hình vuông không phải là protectedByWhite.

Do đó, logic khá đơn giản. Trong lớp học ChessBoard của tôi, tôi có các hàm testCheckWhitetestCheckBlack được gọi sau mỗi lần di chuyển. Di chuyển được gọi trong lớp Square của tôi (một chức năng nhấp chuột đơn giản).

Vấn đề chính là mã bị lỗi ... và tôi không chắc chắn tại sao/ở đâu. Lỗi chính là:

  • Khi màu đen hoặc trắng ở trong Kiểm tra, nếu chúng di chuyển ở nơi chúng vẫn ở trong Kiểm tra, di chuyển sẽ không được hoàn tác. Tôi biết rằng chức năng hoàn tác đang hoạt động tốt, vì vậy một số cách logic của tôi sai.

Ví dụ: Tôi có nhãn ở bên cảnh báo khi Kiểm tra màu đen/trắng. Khi tôi bước đầu "Kiểm tra" đối thủ, nhãn sẽ thông báo cho tôi về séc. Tuy nhiên, khi tôi cố gắng di chuyển nhà vua đến một quảng trường nơi tôi vẫn sẽ được kiểm tra, nhãn không chính xác nói rằng không có Kiểm tra. Tôi đã làm việc một thời gian để cố gắng xác định nơi tôi đã đi sai, và tôi có thể sử dụng một số hướng.


LIÊN QUAN Mã sản phẩm:

ChessBoard.Java

public static void setProtectedSquares() { 
     // Reset 
     for(Square s : BOARD_SQUARES) { 
      s.protectedByWhite = false; 
      s.protectedByBlack = false; 
     } 

     // Now set protections 
     for(Square s : BOARD_SQUARES) { 
      if(s.hasPiece() && s.getPiece().getTeamColor().equals(TeamColor.WHITE)) { 
       Piece p = s.getPiece(); 
       for(int[] position : p.getLegalMoves(p.getPosition())) { 
        if(hasSquare(position)) { 
         getSquare(position).protectedByWhite = true; 
        } 
       } 
      } 
     } 
     for(Square s : BOARD_SQUARES) { 
      if(s.hasPiece() && s.getPiece().getTeamColor().equals(TeamColor.BLACK)) { 
       Piece p = s.getPiece(); 
       for(int[] position : p.getLegalMoves(p.getPosition())) { 
        if(hasSquare(position)) { 
         getSquare(position).protectedByBlack = true; 
        } 
       } 
      } 
     } 
} 

public static boolean testCheckWhite() { 

     // Get king position 
     int[] whiteKingPosition = new int[]{}; 
     for(Square s : BOARD_SQUARES) { 
      Piece p = s.getPiece(); 
      if(s.hasPiece() && (p.getPieceType()).equals(PieceType.KING)) { 
       if((p.getTeamColor()).equals(TeamColor.WHITE)) { 
        whiteKingPosition = p.getPosition(); 
       } 
      } 
     } 

     if(hasSquare(whiteKingPosition) && getSquare(whiteKingPosition).protectedByBlack) { 
      GameInfoPanel.inCheckWhite.setText("White is in check"); 
      return true; 
     } else { 
      GameInfoPanel.inCheckWhite.setText("White is not in check"); 
      return false; 
     } 
    } 

    public static boolean testCheckBlack() { 

     // Get king position 
     int[] blackKingPosition = new int[]{}; 
     for(Square s : BOARD_SQUARES) { 
      Piece p = s.getPiece(); 
      if(s.hasPiece() && (p.getPieceType()).equals(PieceType.KING)) { 
       if((p.getTeamColor()).equals(TeamColor.BLACK)) { 
        blackKingPosition = p.getPosition(); 
       } 
      } 
     } 

     if(hasSquare(blackKingPosition) && getSquare(blackKingPosition).protectedByWhite) { 
      GameInfoPanel.inCheckBlack.setText("Black is in check"); 
      return true; 
     } else { 
      GameInfoPanel.inCheckBlack.setText("Black is not in check"); 
      return false; 
     } 
    } 

Square.java

.... // If a square is clicked that IS colored... 
     } else { 
      for(Square s : ChessBoard.BOARD_SQUARES) { 
       if(s.hasPiece() && (s.getPiece()).getFocus()) { 

        // Check to make sure that the target square and current 
        // square are not the same 
        if(!this.equals(s)) { 
         movePiece(s); 

         ChessBoard.setProtectedSquares(); 

         // Test for check 
         // 1) Find out what color the moved piece is 
         if((ChessBoard.getTurn()) == TeamColor.WHITE) { 
          if(ChessBoard.testCheckWhite()) { 
           // Undo move 
           s.movePiece(ChessBoard.getSquare(STORED_POSITION)); 
           GameInfoPanel.gameStatus.setText("Illegal move, white in check"); 
          } else if(ChessBoard.testCheckBlack()) { 
           // Move is okay, black is now in check 
           GameInfoPanel.gameStatus.setText("Okay move, black in check"); 
           // Switch players' turn 
           ChessBoard.switchTurn(); 
          } else { 
           // Move is okay, nothing happened 
           GameInfoPanel.gameStatus.setText("No one in check"); 
           // Switch players' turn 
           ChessBoard.switchTurn(); 
          } 

         } else { 
          if(ChessBoard.testCheckBlack()) { 
           // Undo move 
           s.movePiece(ChessBoard.getSquare(STORED_POSITION)); 
           GameInfoPanel.gameStatus.setText("Illegal move, black in check"); 
          } else if(ChessBoard.testCheckWhite()) { 
           // Move is okay, white is now in check 
           GameInfoPanel.gameStatus.setText("Okay move, white in check"); 
           // Switch players' turn 
           ChessBoard.switchTurn(); 
          } else { 
           // Move is okay, nothing happened 
           GameInfoPanel.gameStatus.setText("No one in check"); 
           // Switch players' turn 
           ChessBoard.switchTurn(); 
          } 
         } 
        } 
       } 
      } 

      // Clear all color and focus 
      ChessBoard.clearFocus(); 

      ChessBoard.setProtectedSquares(); 
     } 

Trả lời

2

tôi khá underst và thuật toán mã của bạn. Rất tiếc, tôi không thấy bất kỳ điều gì sai với đoạn trích bạn đã đăng.

Đó là lý do tại sao bạn nên luôn sử dụng Kiểm tra đơn vị trong khi bạn viết mã.:)

  1. Đơn vị kiểm tra setProtectedSquares()
  2. Đơn vị kiểm tra các testCheckWhite()
  3. Đơn vị kiểm tra các testcCheckBlack()
  4. Đơn vị thi THEN Refactor for(Square s : ChessBoard.BOARD_SQUARES) {...}

Những điều này sẽ giúp bạn trong thời gian dài.

Tuy nhiên, nếu bạn muốn giải quyết (hy vọng) mọi thứ nhanh hơn, hãy sử dụng chế độ gỡ lỗi trình gỡ lỗi từ IDE của bạn.

1

Dưới đây là một dòng đề nghị điều tra. Giả sử đây là kịch bản: trắng đã kiểm tra vua đen và đen có thể di chuyển đến một hình vuông được bảo vệ bởi màu trắng.

Dựa trên mã được cung cấp và thực tế là màu đen (khi được kiểm tra) có thể di chuyển đến hình vuông được bảo vệ bằng màu trắng, nó phải là trường hợp phương pháp ChessBoard.testCheckBlack() trả về sai. Bây giờ dựa trên phương pháp thực hiện ChessBoard.testCheckBlack(), chúng ta có thể kết luận rằng các văn bản

"Đen là trong tầm kiểm soát"

phải đầu ra trên GameInfoPanel.

Nếu điều đó là đúng nhu cầu thì sau để được kiểm tra, từng người một:

hasSquare(blackKingPosition) 
getSquare(blackKingPosition).protectedByWhite // just protectedByWhite 

Nó sẽ là tuyệt vời nếu bạn có thể gửi thông điệp GameInfoPanel cho kịch bản trên.

1

Kiểm tra để xem nếu có vuông đang bị đe dọa là một chức năng hữu ích mà bạn có thể sử dụng không chỉ đối với các cuộc tấn công trực tiếp vua mà còn cho lên đời từ một vị vua không được phép lâu đài "thông qua" kiểm tra. Điều này có nghĩa bạn phải đảm bảo lên đến ba hình vuông được tự do từ đường dây trực tiếp của đối thủ tấn công đến lâu đài nhà vua một cách hợp pháp.

Với điều này là tâm trí, bạn có thể muốn xây dựng một phương pháp như thế này:

public static final boolean isThreatenedSquare(
      Color threatenedColor, 
      Square threatenedSquare, 
      Chessboard board) 

Thuật toán cho trượt mảnh thể sử dụng mảng song song để xác định 8 hướng (đường tấn công hay "tia") mà tỏa ra từ nguồn gốc (quảng trường bị đe dọa).Ví dụ:

int[] rowDirections = {-1, -1, -1, 0, 0, 1, 1, 1}; 
int[] colDirections = {-1, 0, 1, -1, 1, -1, 0, 1}; 
  • chỉ số đầu tiên thiết lập (-1, -1) đại diện cho một diagoanl "tia" di chuyển theo một hướng "về phía tây bắc"
  • chỉ số thứ hai thiết lập (-1, 0) đại diện cho dọc "tia" di chuyển trong "north" direction
  • chỉ số thứ ba đặt (-1, 1) đại diện cho một chéo "tia" di chuyển theo một hướng "đông bắc"
  • chỉ số thứ tư thiết (0, -1) đại diện cho một ngang "tia" di chuyển trong "hướng tây" hướng

... v.v. Bằng cách tỏa ra một hình vuông tại một thời điểm, bạn chỉ cần kiểm tra vuông (đảm bảo bạn nằm trong ranh giới bàn cờ) và xem nếu nó là chiếm đóng. Nếu có, hãy xác định xem đó là một mảnh thân thiện hay đối thủ. Chỉ vì chúng tôi đã đánh một mảnh của đối phương không nhất thiết có nghĩa là hình vuông bị đe dọa của chúng tôi đang bị tấn công.

Các giám mục, ví dụ chỉ có thể tấn công dọc theo các tia chéo để tìm một dọc theo một tia thẳng đứng ngăn tia của chúng tôi phát ra thêm bất kỳ tuy nhiên Bishop không đe dọa hình vuông. Chúng tôi gọn gàng có thể mô tả các khả năng tấn công cho bất kỳ mảnh trượt đối với các mảng hướng song song chúng ta định nghĩa trước đó với. Ví dụ:

boolean bishopThreats[] = {true, false, true, false, false, true, false, true}; 
boolean rookThreats[] = {false, true, false, true, true, false, true, false}; 
boolean queenThreats[] = {true, true, true, true, true, true, true, true}; 
boolean kingThreats[] = {true, true, true, true, true, true, true, true}; 

Các mảng ở trên cho thấy rằng Giám Mục chỉ có thể đe dọa dọc đường chéo, Rooks dọc theo các đường dọc và ngang, Queens và Kings có thể tấn công theo hướng nào.

Cầm Xe hơi khó khăn vì họ tấn công dọc theo đường chéo nhưng chỉ ở phía đông bắc + hướng về phía tây bắc (đối với màu trắng), và phía đông nam + tây nam hướng (ví màu đen).

boolean kill = threatenedColor.equals(Color.black) ? true : false; 
boolean pawnThreats[] = {kill, false, kill, false, false, !kill, false, !kill}; 

Với mọi thứ tại chỗ, tất cả những gì cần thiết là sử dụng một cặp lồng nhau cho vòng lặp. Người bên ngoài để lặp qua tất cả các hướng, là bên trong để tỏa ra một hình vuông tại một thời điểm cho đến khi chúng ta nhấn vào cạnh của bàn cờ hoặc nhấn một mảnh, nào đến trước. Đây là thuật toán cho các phần trượt. Hiệp sĩ là khác biệt so với mảnh trượt nhưng những ý tưởng chung được trình bày ở đây cũng được áp dụng.

boolean threatDetected = false; 
int threatenedRow = threatenedSquare.getRow(); 
int threatenedCol = threatenedSquare.getCol(); 

for(int direction = 0; direction < 8 && !threatDetected; direction++) { 
    // RESET OUR COORDINATES TO PROCESS CURRENT LINE OF ATTACK. 
    // INCREMENT VALUES ARE SAME AS DIRECTION ARRAY VALUES 
    int row = threatenedRow; 
    int col = threatenedCol; 
    int rowIncrement = rowDirections[direction]; 
    int colIncrement = colDirections[direction]; 

    // RADIATE OUTWARDS STARTING FROM ORIGIN UNTIL WE HIT A PIECE OR ARE OUT OF BOUNDS 
    for(int step = 0; step < 8; step++) { 
     row = row + rowIncrement; 
     col = col + colIncrement; 

     // IF WE ARE OUT OF BOUNDS, WE STOP RADIATING OUTWARDS FOR 
     // THIS RAY AND TRY THE NEXT ONE 
     if(row < 0 || row > 7 || col < 0 || col > 7) { 
      break; 
     } 
     else { 
      // LOOK AT CURRENT SQUARE AND SEE IF IT IS OCCUPIED BY A PIECE 
      Square square = board.getSquare(row, col); 
      IPiece piece = square.getPiece(); 
      if(piece != null) { 
       // RADIATING OUTWARDS MUST STOP SINCE WE HIT A PIECE, ONLY 
       // QUESTION IS WHAT DID WE HIT? FRIEND OR FOE? 
       if(!piece.getColor.equals(threatenedColor)) { 
        // WE ARE FACING AN OPPONENT, DOES IT HAVE THE CAPABILITY 
        // TO ATTACK US GIVEN THE DIRECTIONAL LINE OF ATTACK 
        // WE ARE CURRENTLY ANALYZING  
        if(piece instanceof Bishop && bishopThreats[direction]) 
         threatDetected = true; 
        else if(piece instanceof Rook && rookThreats[direction]) 
         threatDetected = true; 
        else if(piece instanceof Queen && queenThreats[direction]) 
         threatDetected = true; 
        else { 
         if(step == 0) { 
          // PAWNS AND KINGS DONT HAVE THE REACH OF OTHER SLIDING 
          // PIECES; THEY CAN ONLY ATTACK SQUARES THAT ARE CLOSEST 
          // TO ORIGIN 
          if(piece instanceof Pawn && pawnThreats[direction]) 
           threatDetected = true; 
          if(piece instanceof King && kingThreats[direction]) 
           threatDetected = true; 
         } 
        } 
       } 
       break; 
      } 
     } 
    } 
} 
Các vấn đề liên quan