2014-04-30 5 views
6

यह प्रश्न मेरे कोड को देखे बिना हल करने के लिए काफी बड़ा और मुश्किल है, और यदि यह बहुत अधिक है, तो दायरा शायद बहुत बड़ा है और मैं सवाल हटा दूंगा। मूल रूप से मैं छोड़करचेक(औरइस प्रकार भी शह और मात नहीं, गतिरोध, आदि) कार्यान्वित शतरंज के नियमों के सभी के साथ एक काम शतरंज खेल है।शतरंज गेम में "चेक" लागू करना

मैं अपने शतरंज के स्क्वायर को दो बूलियनों को निर्दिष्ट करके चेक लागू करने के बारे में गया: protectedByWhite और protectedByBlack। वहाँ की जांच के साथ तर्क के दो मुख्य टुकड़े कर रहे हैं: का कारण बनता है एक कदम व्हाइट द्वारा किया जाता है

  • अगर वह अपने राजा एक वर्ग कि है protectedByBlack पर हो सकता है, और काले के साथ इसके विपरीत, इस कदम "पूर्ववत" है ।
  • यदि व्हाइट द्वारा एक कदम बनाया जाता है जो ब्लैक के राजा को protectedByWhite पर एक वर्ग पर होने का कारण बनता है, और इसके विपरीत ब्लैक के साथ, ब्लैक के अगले कदम को अपने राजा को उस वर्ग पर रखना चाहिए जो protectedByWhite नहीं है।

इस प्रकार तर्क काफी सरल है। मेरे ChessBoard कक्षा में, मेरे पास testCheckWhite और testCheckBlack फ़ंक्शन हैं जिन्हें हर कदम के बाद बुलाया जाता है। मूव को मेरे Square वर्ग (एक साधारण माउस क्लिक फ़ंक्शन) में बुलाया जाता है।

मुख्य समस्या यह है कि कोड छोटी है ... और मुझे यकीन नहीं है कि क्यों/कहाँ। मुख्य बग यह है कि:

  • जब काला या सफेद चेक में होते हैं, यदि वे एक कदम बढ़ाते हैं जहां वे अभी भी चेक में होंगे, तो चाल पूर्ववत नहीं होती है। मुझे पता है कि पूर्ववत कार्य ठीक काम कर रहा है, तो कुछ मेरा तर्क गलत कैसे है।

उदाहरण के लिए, मेरे पास उस तरफ लेबल हैं जो काले/सफेद जांच में हैं जब चेतावनी देते हैं। जब मैं शुरुआत में प्रतिद्वंद्वी को "चेक" करता हूं, तो लेबल मुझे चेक के बारे में सूचित करता है। हालांकि, जब मैं राजा को एक वर्ग में ले जाने की कोशिश करता हूं जहां मैं अभी भी जांच में रहूंगा, तो लेबल गलत तरीके से कहता है कि कोई चेक नहीं है। मैं अब कुछ समय के लिए काम कर रहा हूं यह पहचानने की कोशिश कर रहा हूं कि मैं कहां गलत हो गया हूं, और मैं कुछ दिशा का उपयोग कर सकता हूं।


प्रासंगिक कोड:

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(); 
     } 

उत्तर

2

मैं काफी समझ और आपके कोड के एल्गोरिदम। दुर्भाग्यवश, मुझे आपके द्वारा पोस्ट किए गए स्निपेट के साथ कुछ भी गलत नहीं दिख रहा है।

यही कारण है कि आपको हमेशा कोड के दौरान यूनिट टेस्ट का उपयोग करना चाहिए।:)

  1. यूनिट setProtectedSquares()
  2. यूनिट परीक्षण
  3. यूनिट परीक्षण परीक्षण testCheckWhite()
  4. यूनिट परीक्षण testcCheckBlack() तो for(Square s : ChessBoard.BOARD_SQUARES) {...}

refactor इन में मदद मिलेगी आप लंबे समय तक।

हालांकि, यदि आप चीजों को जल्दी से हल करना चाहते हैं (उम्मीद है) चीजें जल्दी से, डीबगर मोड को अपने आईडीई से उपयोग करें।

1

यहां जांच की एक सुझाई गई पंक्ति है। आइए मान लें कि यह परिदृश्य है: सफेद ने काले और काले राजा की जांच की है सफेद द्वारा संरक्षित दूसरे वर्ग में जा सकते हैं।

प्रदान किए गए कोड के आधार पर और तथ्य यह है कि काला (जब चेक के तहत) सफेद द्वारा संरक्षित वर्ग में स्थानांतरित हो सकता है, तो यह होना चाहिए कि ChessBoard.testCheckBlack() विधि गलत हो रही है। अब कार्यान्वयन ChessBoard.testCheckBlack() पद्धति पर आधारित है, हम निष्कर्ष है कि पाठ

"ब्लैक की जांच में है"

GameInfoPanel पर उत्पादन किया जाना चाहिए कर सकते हैं।

अगर वह सही उसके बाद निम्न जांच की जानी, एक-एक करके की जरूरत है:

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

यह महान यदि आप ऊपर परिदृश्य के लिए GameInfoPanel संदेश पोस्ट कर सकता है किया जाएगा।

1

यह देखने के लिए जांच कर रहा है कि क्या कोई वर्ग खतरे में है या नहीं, यह एक उपयोगी कार्य है जिसे आप न केवल सीधे राजा हमलों के लिए उपयोग कर सकते हैं बल्कि राजा के लिए भी जा सकते हैं क्योंकि राजा को "माध्यम से" चेक करने की अनुमति नहीं है। इसका मतलब है कि आपको राजा को कानूनी रूप से महल करने के लिए प्रतिद्वंद्वी की हमले की सीधी रेखा से तीन वर्गों तक मुक्त होना सुनिश्चित करना है।

इसे ध्यान, तो आप इस जैसे एक विधि के निर्माण के लिए चाहते हो सकता है है:

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

टुकड़े समानांतर सरणियों 8 दिशाओं (हमले की तर्ज या "रे") को परिभाषित करने को रोजगार हो सकता है रपट के लिए एल्गोरिथ्म जो उत्पत्ति से बाहर निकलता है (धमकीदार वर्ग)।उदाहरण के लिए:

int[] rowDirections = {-1, -1, -1, 0, 0, 1, 1, 1}; 
int[] colDirections = {-1, 0, 1, -1, 1, -1, 0, 1}; 
  • पहले सूचकांक सेट (-1, -1) एक diagoanl "रे" एक "पश्चिमोत्तर" दिशा
  • दूसरा सूचकांक सेट में आगे बढ़ का प्रतिनिधित्व करता है (-1, 0) एक खड़ी "रे" एक "उत्तर" दिशा में आगे बढ़ प्रतिनिधित्व करता
  • तीसरे सूचकांक सेट (-1, 1) एक विकर्ण "रे" एक "पूर्वोत्तर" दिशा
  • चौथे सूचकांक सेट (0, -1) एक क्षैतिज का प्रतिनिधित्व करता है में आगे बढ़ का प्रतिनिधित्व करता है "रे" एक "पश्चिम" दिशा

... और इतने पर में घूम रहा है। एक समय में एक वर्ग बाहर radiating करके, आप बस वर्ग (सुनिश्चित आप बिसात सीमाओं के भीतर कर रहे हैं) का निरीक्षण करें और देखें कि यह कब्जे में है जाएगा। यदि यह है, तो यह निर्धारित करें कि यह एक दोस्ताना या प्रतिद्वंद्वी टुकड़ा है या नहीं। सिर्फ इसलिए कि हमने प्रतिद्वंद्वी के टुकड़े को मारा है, इसका मतलब यह नहीं है कि हमारे धमकी वाले वर्ग पर हमला किया जा रहा है।

बिशप, उदाहरण के लिए केवल विकर्ण किरणों के साथ हमला कर सकते हैं ताकि एक लंबवत किरण के साथ एक को ढूंढने से हमारी किरण किसी और को विकिरण से रोक दे, हालांकि बिशप वर्ग को धमकी नहीं देता है। हम बड़े करीने से समानांतर दिशात्मक सरणियों हम पहले परिभाषित के संबंध में कोई रपट टुकड़े के लिए हमला क्षमताओं का वर्णन कर सकते हैं। उदाहरण के लिए:

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}; 

बताते हैं कि बिशप केवल विकर्णों के साथ धमकी कर सकते हैं इसके बाद के संस्करण सरणियों, ऊर्ध्वाधर और क्षैतिज पंक्तियों के साथ रूक्स, क्वींस और किंग्स किसी भी दिशा में हमला कर सकते हैं। क्योंकि वे विकर्णों के साथ है, लेकिन केवल उत्तर पूर्व + उत्तर-पश्चिम दिशा-निर्देश (सफेद के लिए), और दक्षिण पूर्वी + दक्षिण पश्चिम दिशाओं (काला के लिए) में हमला

प्यादों को कुछ हद तक मुश्किल है।

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

सब कुछ जगह के साथ, लूप के लिए दो घोंसले का उपयोग करना आवश्यक है। बाहरी एक सभी दिशाओं के माध्यम से, भीतर एक एक समय में एक वर्ग बाहर विकीर्ण करने के लिए जब तक हम बिसात के किनारे हिट या एक टुकड़ा है, जो भी पहले हो मारा पुनरावृत्ति करने के लिए। टुकड़े टुकड़े टुकड़े करने के लिए एल्गोरिदम यहाँ है। नाइट स्लाइडिंग टुकड़ों से अलग हैं लेकिन यहां प्रस्तुत सामान्य विचार भी लागू होते हैं।

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; 
      } 
     } 
    } 
} 
संबंधित मुद्दे