2013-06-27 4 views
0

지뢰 찾기 프로그램을 작성하고 있는데 인접 격자에 얼마나 많은 지뢰가 있는지 보여줄 코드를 작성하려고합니다.하지만 클래스가 예상된다는 오류가 발생합니다. 이유를 모르겠다. 나는 두 가지 방법 모두 MSgrid 메서드에 있기 때문에 가정하에있었습니다. 여기 오류로 오류가있는 줄 주석 있습니다.지뢰 찾기 인접 격자 지의 개수가 증가합니다

/** 
* Represents a single square in Minesweeper. 
* 
* @author Sophia Ali 
* June 17, 2012 
*/ 
public class MineSquare 
{ 


    // Fields: 
    /** 
    * initialize variables 
    */ 
    private String _shown;  // What a square is showing now 
    private boolean _mined;  // Square is mined or not 
    private boolean _flagged; // Square is flagged or not 
    private boolean _questioned; // Square is question marked or not 
    private int  _minecount; // Square's surrounding mine count 
    private boolean _opened;  // Player has opened this square or not 



    // Constructors & Methods: 

    /** 
    * Default constructor 
    * Sets _mined and _opened to false. 
    */ 
    public MineSquare() 
    { 
     _mined = false; 
     _opened = false; 
     setShown(" "); 
    } 





    /** 
    * Returns flagged status of square. 
    * @return _flagged Flagged status 
    */ 
    public boolean isFlagged() { 
     return _flagged; 
    } 





    /** 
    * Sets or unsets flag on a square. 
    * @param flagged True or false (square is flagged or not) 
    */ 
    public void setFlagged(boolean flagged, boolean opened) { 
     _flagged = flagged; 
     _opened = opened; 

     /* 
     // If Minesquare opened do nothing: 
     if (opened == true) 
     setShown(" ");*/ 
     if (isOpened() == false) 
     { 
     // If flagged, square should show "F": 
     if (isFlagged() == true) 
      setShown("F"); 
     else 
      setShown(" ");    
     } 
     /* else 
     {} not needed but shows it does nothing*/ 
     } 


    /** 
    * Returns _minecount amount. 
    * @return _minecount 
    */ 
    public int getMinecount() { 
     return _minecount; 
    } 




/** 
    * Checks minecount 
    * If minecount between 0 and 8 _minecount not set and error message outputs. 
    */ 
    public void setMinecount(int minecount) { 
     if(minecount >=0 && minecount <= 8) 
      _minecount = minecount; 
     else //invalid minecount 
      System.out.println("Invalid minecount in setMinecount: " +minecount); 
     /* 
     if (minecount > 0 && minecount < 8) 
     { 
     getMinecount(); 
    } 
     else System.out.println("Error :" + minecount); 
     */ 

} 




/** 
    * Returns mined status of square. 
    * @return _mined Mined status 
    */ 
    public boolean isMined() { 
     return _mined; 
    } 




/** 
    * Sets or unsets mine on a square. 
    * @param mined True or false (square is mined or not) 
    */ 
    public void setMined(boolean mined) { 
     _mined = mined; 


     // If mine, square should show "F": 
     if (isMined() == true) 
      setShown("F"); 
     else 
      setShown(" "); 

    } 




/** 
    * Returns opened status of square. 
    * @return _opened Opened status 
    */ 
    public boolean isOpened() { 
     return _opened; 
    } 





    /** 
    * Open a square. 
    * (Once opened, a square can't be unopened.) 
    */ 
    public void setOpened() { 
     _opened = true; 

     if (isMined() == true) 
      setShown("X"); 
     else if (getMinecount() > 0) 
      setShown(_minecount + ""); 
     else // blank space for _minecount = 0 
      setShown(" "); 
    } 




/** 
    * Returns openequestion status of square. 
    * @return _questioned Questioned status 
    */ 
    public boolean isQuestioned() { 
     return _questioned; 
    } 




/** 
    * Sets or unsets question on a square. 
    * @param questioned True or false (square is questioned or not) 
    */ 
    public void setQuestioned(boolean questioned, boolean opened) { 
     _questioned = questioned; 
     _opened = opened; 
     // If Minesquare opened do nothing: 
     /*if (opened == true) 
     setShown(" "); 

     // If Questioned, square should show "F": 
     if (isQuestioned() == true) 
      setShown("F"); 
     else 
      setShown(" "); 
      */ 
     if (isOpened() == false) 
     { 
     // If flagged, square should show "F": 
     if (isQuestioned() == true) 
      setShown("?"); 
     else 
      setShown(" ");    
     } 
     /* else 
     {} not needed but shows it does nothing*/ 
     } 


/** 
    * Returns what is in getShown. 
    * @return _shown 
    */ 
    public String getShown() { 
     return _shown; 
    } 


     /** 
      * Increment _minecount by 1. 
      * Calls setMinecount() to make sure that an illegal value (>8) is 
      * not assigned to _minecount. 
      */ 
    public void increMinecount() 
     { 
      int mc = _minecount; 
      mc++; 

      setMinecount(mc); 
     } 

/** 
    * Checks shown 
    * If _shown is one of legal values prints _shown if not prints error. 
    */ 
    public void setShown(String shown) { 
    if (shown.equals ("X") || shown.equals("F") || shown.equals("?") || 
     shown.equals (" ") || shown.equals ("1") || shown.equals ("2") || shown.equals ("3") || 
     shown.equals ("4") || shown.equals ("5") || shown.equals ("6") || shown.equals ("7") || 
     shown.equals ("8")) 
     _shown = shown; 
    else //invalid value of shown 
     System.out.println("Invalid value of shown in setShown: " + shown); 
    } 


    } 

/** 
* MSGrid class that contains a 2-D array of MineSquare objects 
* 
* @author J. Chung 
* @version CS-501B 
*/ 
public class MSGrid 
{ 
    // instance variables - replace the example below with your own 
    // 2-D array of MineSquare objects: 
    private final int ROWS = 20; 
    private final int COLS = 20; 
    private MineSquare [][] grid = new MineSquare[ROWS][COLS]; 
    // Actual size of grid that we use in rows and cols: 
    private int rows = 9; 
    private int cols = 9; 
    // Number of mines that go in grid: 
    private int mines = 10; 


    /** 
    * Constructor for objects of class MSGrid 
    */ 
    public MSGrid() 
    { 
     // initialise the grid of MineSquare objects: 
     // (construct individual MineSquare objects within grid array) 
     for (int r = 1; r <= rows; r++) { 
      for (int c = 1; c <= cols; c++) { 
       grid[r][c] = new MineSquare(); 
      } 
     } 
    } 


    /* 
    * MSGrid methods: 
    * 
    * - Set mines 
    * - Compute and set minecounts 
    */ 

    /** 
    * Set some number of mines at random within the grid. 
    */ 
    public void setMines() //scattering mines 
    { 
     // Choose random row, choose random col, place mine there: 
     for (int i = 1; i <= mines; i++) 
     { 
      int randomrow = randbetween(1, rows); 
      int randomcol = randbetween(1, cols); 

      // If square is already mined, do it again: 
      while (grid[randomrow][randomcol].isMined() == true) 
      { 
       randomrow = randbetween(1, rows); 
       randomcol = randbetween(1, cols); 
      } 

      grid[randomrow][randomcol].setMined(true); 
     } 
    } 




    /* 
    * Compute and set square minecounts. 
    */ 
    public void setMinecounts() 
    { 
     // Approach #1: Visit each square in grid; examine all adjacent 
     //    squares; for each mine found, increment minecount 
     //    by 1. 

     // Approach #2: Visit each mined square in grid; increment minecount 
     //    of all adjacent squares by 1. plus one for all neighbors of mined grid (even if it already +1) - easier way to do it 
      //**do nested for loop to access every square in grid 
    for (int r = 1; r <= rows; r++) { 
      for (int c = 1; c <= cols; c++) { 
       // if current square at r,c has a mine: 
      if (grid[r][c].isMined() == true) 
      {  
       if (grid[r][c].isValidSquare(int rr, int cc) == true) //***ERROR HERE*** 
       { 
        grid[r-1][c-1].increMinecount(); 
        grid[r][c-1].increMinecount(); 
        grid[r+1][c-1].increMinecount(); 
        grid[r+1][c].increMinecount(); 
        grid[r-1][c].increMinecount(); 
        grid[r+1][c+1].increMinecount(); 
        grid[r][c+1].increMinecount(); 
        grid[r-1][c+1].increMinecount(); 
      }  
      } 
     } 
    } 
} 
    // Note: In both approaches, must exclude squares that are not in grid. 
    //  (Must use the isValidSquare() method below.) 





    /* 
    * See if a square at some row, col is within the grid. 
    * 
    * @param rr row of square in question 
    * @param cc col of square in question 
    * @return True if square is in grid, false if square not in grid 
    */ 
    private boolean isValidSquare(int rr, int cc) 
    { 
     if (rr >= 1 && rr <= rows && cc >= 1 && cc <= cols) 
      return true; 
     else 
      return false; 
    } 






    /** 
    * Show the grid, for testing purposes only. 
    */ 
    public void showMSGrid() 
    { 
     for (int r = 1; r <= rows; r++) { 
      for (int c = 1; c <= cols; c++) { 
       // Call a MineSquare method: 
       int mc = grid[r][c].getMinecount(); 

       // Show a mine or a minecount number: 
       if (grid[r][c].isMined() == true) 
        System.out.print(" " + "X"); 
       else 
        System.out.print(" " + mc); 
      } // end of column 

      System.out.println(); // line break 

     } // end of row 
    } 





    /** 
    * randbetween: Return a random integer between low and high values 
    * 
    * @param: low - low value 
    * @param: high - high value 
    * @return: random integer b/w low and high 
    */ 
    private int randbetween(int low, int high) { 
     // Make sure that low and high values are in correct positions: 
     // If low > high, swap low and high. 
     if (low > high) { 
      int temp = low; 
      low = high; 
      high = temp; 
     } 

     int scale = high - low + 1; 
     int shift = low; 
     int randnum = (int)(Math.random() * scale) + shift; 

     return randnum; 
    } 

    /*first setmines 
    then setminecount 
    then showmsgrid 
    */ 
} 
+2

특정 오류 및 스택 추적을 알려주십시오. 많은 코드, 유용하지 않습니다. 완전한 오류 플러스 스택 추적은 매우 유용합니다. – BevynQ

+0

참고로, 일반적으로 클래스가 올바르게 사용된다면 일어나지 않을 것들에 대해 예외 (예 :'InvalidArgumentException')를 던져야합니다. 무엇보다도 스택 추적을 얻을 수 있습니다. 코드 추적 방법에 대한 오류 메시지보다 훨씬 유용합니다. – cHao

답변

0

if (grid[r][c].isValidSquare(int rr, int cc) == true)

이 유효한 코드가 아닙니다 : 여기 내 코드입니다. 시도해보십시오.

if (grid[r][c].isValidSquare(rr, cc) == true)

또한 true/false 값을 사용하지 않고 false가 true 일 때 검사가 수행됩니다. 즉 if (grid[r][c].isValidSquare(rr, cc))입니다.

+0

rr 또는 cc가 정의되어 있다고 생각하지 않으므로 아마도 isValidSquare (r, c)'라고 정의됩니다. –

2

난 당신이

if (grid[r][c].isValidSquare(int rr, int cc) == true) 
  • isValidSquare이 MSGrid에 대해 정의하지 MineSquare하지만, 그리드 [R]를 [C]는 MineSquare
  • 입니다

    if(isValidSquare(r, c)) 
    

    대신

    싶은 생각 기타 언급 된 문제
    • 여기에 표시된대로 int을 사용하면 잘못되었습니다 (아이러니하게도) 코드입니다.
    • == true 여기에 선택 사항입니다.

이제 때문에 가정이 if (isValidSquare(int rr, int cc))의 NPE을 받고, 그것은 8 유효한 이웃이 있습니다. 이 사각형이 격자 (r == 0 || c == 0 || r == rows-1 || c == cols-1) 가장자리에 있으면 그 이웃을 많이 가질 수 없기 때문에 잘못되었습니다.

광산 카운트를 증가시키기 전에 이러한 각 조건을 확인해야합니다. 이것은 단지 예이며, 동시에뿐만 아니라이에 c를 확인해야한다는 예컨대

if(r > 0){ 

    grid[r-1][c+1].increMinecount(); 
    grid[r-1][c].increMinecount(); 
    grid[r-1][c-1].increMinecount(); 
} 

참고. 또는 UpdateMineCount(r,c) 함수를 사용하여 isValidSquare을 먼저 호출 한 다음 increMinecount을 호출 할 수 있습니다.

public void IncrementMineCount(MineSquare ms, int r, int c){ 
     if(isValidSquare(r,c)){ 
      ms.increMineCount(); 
     }  
} 

이제 IncrementMineCount(grid[r-1][c-1],r,c)

+0

도와 주셔서 감사합니다. 나는 하나의 마지막 질문 setminecounts 메서드에서 잘못된 그리드 때 그것은 "java.lang.NullPointerException : null"말하는 오류를 제공합니다하지만 유효한 격자가 아닌 경우 isvalid 메서드는 돌볼 것이라고 생각, 이 문제를 해결할 방법이 있습니까? –

+0

@ SophiaAli 당신은 (r, c)가 유효한 사각형인지를 확인하고 있지만, 8 개의 이웃들 모두가 유효한 제곱이라고 가정합니다. 이는 잘못된 가정입니다. 당신은 각 차원을 독립적으로 점검하고, 유효성이있는 경우에만 이웃을 처리 할 수 ​​있습니다. 각 차원마다 –

+0

은 각 사각형을 의미합니까? 그래서 나는 더 많은 "grid [r] [c-1] .increMinecount();" 윤곽? –

0

귀하의 gridgrid[r-1][c-1].increMinecount(); 교체는 MineSquare 객체를 보유하고 있습니다. 그러나 귀하의 isValidSquare 메소드는 클래스 MSGrid에 정의되어 있습니다. grid[r][c]MineSquare 개체를 반환하므로 해당 개체에서 isValidSquare을 호출하려고하면 잘못되었습니다. MineSquare 타입에 대해 메소드가 정의되어 있지 않다는 컴파일 타임 오류가 발생합니다.

해당 메서드를 MineSquare 클래스로 옮기면 대부분 괜찮을 것입니다. 물론 전화 번호 isVaidSquare을 수정해야합니다 ((grid[r][c].isValidSquare(r,c))).결국 메소드 호출이므로 int을 제거하고 rr과 cc를 각각 r과 c로 변경하십시오.

편집

죄송합니다, isValidSquare가하는 일에주의를 지불하지 않았다. @ KarthikT가 지적한대로 if(isValidSquare(r,c))은 정상적으로 작동합니다. isValidSquareMineSquare의 구성원 중 일부에서 작업 중이면 해당 클래스로 메서드를 이동하는 것을 고려할 수 있습니다.

+0

함수는 격자의 색인을 검사합니다. 그리드 요소로 이동하면 의미가 없습니다. –

+0

예, 올바른 @ Karthik T – kau