2013-06-27 44 views
0

我正在寫一個掃雷計劃,我正在努力編寫代碼,它會顯示有多少個地雷在相鄰的網格中,但是我收到一個錯誤,說有一個類是預期的,我我不知道爲什麼。我是在這個假設下,因爲這兩種方法都在MSgrid方法中,所以沒問題。我已將錯誤的行評論爲ERROR HERE。這裏是我的代碼:掃雷增加相鄰礦網的數量

/** 
* 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)

此外,檢查是布爾是真的假通常不使用真/假值。即if (grid[r][c].isValidSquare(rr, cc))

+0

我不認爲rr或cc也是定義的,所以可能是'isValidSquare(r,c)'。 –

2

我相信你想

if(isValidSquare(r, c)) 

,而不是

if (grid[r][c].isValidSquare(int rr, int cc) == true) 
  • isValidSquare爲MSGrid定義,而不是MineSquare,但格[R] [C]是MineSquare
  • 的其他提及的問題
    • 使用int因爲你在這裏是無效的(諷刺)代碼。
    • == true這裏是可選的。

你現在得到,因爲假設if (isValidSquare(int rr, int cc))的NPE,它有8個有效的鄰居。這是錯誤的,因爲如果這個正方形位於網格的邊緣(r == 0 || c == 0 || r == rows-1 || c == cols-1),那麼它可能沒有很多這些鄰居

您需要在增加礦點數之前檢查每個條件。對於e.g

if(r > 0){ 

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

請注意,這只是一個例子,你需要在同一時間在這個檢查c爲好。或者,您可以使用功能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個鄰居爲valids square,這是一個錯誤的假設。您可能需要獨立檢查每個維度,然後僅在它們的有效性爲 –

+0

時按每個維度處理鄰居。所以我需要更多的「grid [r] [c-1] .increMinecount();」行呢? –

0

grid更換grid[r-1][c-1].increMinecount();持有MineSquare對象。但是您的isValidSquare方法在類MSGrid中定義。 grid[r][c]將返回MineSquare對象,因此試圖調用isValidSquare該對象是錯誤的。你會得到一個編譯時錯誤,說明MineSquare類型的方法沒有定義。

將該方法移至MineSquare類,最有可能的應該是罰款。當然,您需要通過這樣做來修復對isVaidSquare的呼叫(grid[r][c].isValidSquare(r,c))。畢竟這是一個方法調用,所以要擺脫int s,並分別將rr和cc更改爲r和c。

編輯

對不起,沒注意什麼呢isValidSquare。正如@KarthikT指出的那樣,if(isValidSquare(r,c))將會很好。如果isValidSquare正在MineSquare的某些成員上工作,可以考慮將該方法移至該類。

+0

函數檢查網格的索引。將它移動到網格元素是沒有意義的 –

+0

是的,你是對的@Karthik T – kau