2014-08-29 68 views
1

我正在創建一個類似於應用程序的掃雷程序,並且有一些代碼旨在檢查一個非開採空間周圍有多少個地雷。我創建了一些這方面簡單的方法來忽略越界異常JAVA

int count = 0; 
       if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
       String mineNum = String.valueOf(count); 
       cell[i][j].setText(mineNum); 

然而,當旨在繞過板邊緣煤礦數量這將產生錯誤。任何有用的方法來避免這一點?

嘗試下面的建議後。我仍然遇到了越界錯誤。任何人有任何建議,這裏是回購協議,如果有人想編譯它自己https://github.com/phillolivercomp/MineSweeper.git

+0

什麼數據類型是'model'? – Zyerah 2014-08-29 17:26:00

+7

忽略異常總是一個壞主意。編寫代碼來處理邊緣(字面上在這種情況下)而不是。例如,寫一個簽名爲'List getNeighbors(Cell cell)'的方法,給定一個單元格,返回一個有效的鄰居列表以供檢查。然後只檢查那些鄰居。 – 2014-08-29 17:26:21

+0

那麼模型是一個GUI的模型元素,這只是一個類「MinerGridCo」的實例,它具有這些UNTURNED_MINE元素,這些元素只是特別聲明的整數。 – 2014-08-29 17:27:56

回答

1

使用短前短路,並編寫一個函數isInGrid(int x, int y),檢查位置是否在網格中。

public boolean isInGrid(int x, int y) { 
    //Check if a position is valid in the grid 
    if(i < 0 || j < 0) return false; 
    if(i >= WIDTH || j >= HEIGHT) return false; 
    return true; 
} 

... 

if(isInGrid(i-1, j-1) && model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE) count++; 
if(isInGrid(i+1, j+1) && model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE) count++; 
//Repeat for each location you want to check 

如果第一個條件,isInGrid(i-1, j-1)是不正確的,那麼情況將退出而不運行[condition]聲明。通過這種方式,您可以防止[condition]執行,否則會失敗。

這稱爲「短路」 - 這是一種優化,如果已知該代碼不會運行,則會導致if條件檢查退出。您可以在每個要評估的語句前放置其中一個isInGrid檢查,如果該位置不在網格中,則不會執行get

+0

唯一的問題是我所包含的一些if語句需要調用如果我要檢查的對象位於左上方,它必須檢查右下方和右下方對角線的對象如果對象位於右下方,則這是不同的。 – 2014-08-29 17:32:00

+0

@Phill您可以創建許多這些陳述如你所願。在每條語句之前放置'isInGrid()'條件,如果位置不在網格中,'get'將不會運行。 – Zyerah 2014-08-29 17:32:46

+0

對不起,我明白你的意思。好主意。將實現這一點。就像旁註一樣,上面例子中的代碼在你傳遞給它的那些變量和你正在使用的變量名稱之間有着不同的變量名稱。 – 2014-08-29 17:37:51

0

創建一個線功能:

boolean checkBounds(int i, int j) { //TODO }

然後檢查,這樣做你的模型查找

+0

我想到了這個,但唯一的問題是我必須爲每個個案做一個checkbounds,例如,右下角的情況需要在2D數組內,並且需要小於最大值高度和寬度的計數是有效的,左上角需要超過0 – 2014-08-29 17:29:49

+0

我不確定是什麼問題?檢查範圍不限於只覆蓋一個角落案例 – coffeeaddict 2014-08-29 17:34:18

+0

@PhillOliver是的,你需要檢查每種情況 – ControlAltDel 2014-08-29 17:36:09

2

幫你一個忙,並創建model.countUnturnedMinesAround(i,j)。然後在模型中你有一些選擇。

您可以創建視圖看不到的額外行/列,以便您可以輕鬆處理逐個索引。

或者你可以編寫一個函數private Cell getCell(i,j),當i和j超出界限時它將返回默認的空單元格。

或者您可以有boolean hasUnturnedMine(i,j),當i或j離開電網時返回false。

2

可避免重複與循環:使用isInGrid功能由@ Emrakul的回答表明

for (int iOffset = -1; iOffset <= 1; iOffset++) { 
    for (int jOffset = -1; jOffset <= 1; jOffset++) { 
     if (iOffset != 0 || jOffset != 0) { 
      if (isInGrid(i + iOffset, j + jOffset) && 
       model.get(i + iOffset, j + jOffset) == MinerGridCo.UNTURNED_MINE) { 
        count++; 
      } 
     } 
    } 
} 

(其實我結合範圍檢查和UNTURNED_MINE支票存入一個hasUnturnedMine功能,如@長Arkadiy的提及回答)。

+0

我實現了這一點,當它由於某種原因達到12時,這個值似乎達到了一個超出界限的錯誤,這真的讓我很困惑。 12是我爲電路板指定的最大高度和寬度。 – 2014-08-29 18:26:27

+0

我已經添加了我的github回購標題,因爲我不明白爲什麼代碼仍然拋出這些異常 – 2014-08-29 18:35:45

+0

@PhillOliver我注意到@ Emrakul的回答說'if(i> WIDTH || j> HEIGHT)「..那應該是'if(i> = WIDTH || j> = HEIGHT)'。附:還沒有看過你的回購呢。 – ajb 2014-08-29 18:37:59

0

另一種方法可以是讓一個方法isBorder(int i,int j)讓你知道你是否在邊界上。如果它不是邊界,則可以安全地檢查(i,j)周圍的所有方塊。如果它位於邊界上,則可以計算它是左/右/上/下邊界還是4(不超過2)的某種組合,然後檢查相應的框。

免責聲明:我假設您已經在執行檢查以確保(i,j)是網格上的有效位置。無論您的實施如何,您都應該對此進行檢查

0

有更好的方法可以通過更好地構建代碼來實現此目的。但是,下面是您的具體問題的答案:

您在Java中忽略異常的方式是使用try-catch塊。這允許您嘗試運行一段代碼,捕獲拋出的異常,然後決定如何處理它們(包括忽略它們)。

假設你越界異常出從model.get(即將)調用,你可以忽略它們是這樣的:當一個異常遇到的所有後續代碼try塊

int count = 0; 
try 
{ 
    if(model.get(i-1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i-1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i-1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j-1) == MinerGridCo.UNTURNED_MINE){ count++;} 
    if(model.get(i+1, j+1) == MinerGridCo.UNTURNED_MINE){ count++;} 
} 
catch (IndexOutOfBoundsException ex) 
{ 
    // Do nothing 
} 
String mineNum = String.valueOf(count); 
cell[i][j].setText(mineNum); 

但是,將被跳過。這絕對不是你想要的,因爲你會錯過檢查一些鄰接點。 相反,您需要爲每個對model.get()的調用執行try-catch。這最好通過創建像布爾函數來實現:

// Change method visibility and signature accordingly to match your code 
public static boolean tileHasMine(int x, int y) 
{ 
    try 
    { 
     if (model.get(x, y) == MinerGridCo.UNTURNED_MINE) 
     { 
      return true; 
     } 
    } 
    catch (IndexOutOfBoundsException ex) 
    { 
     // Do Nothing 
    } 
    return false; 
} 

然後你的支票看起來像:

int count = 0; 
if(tileHasMine(i-1, j-1)){ count++;} 
if(tileHasMine(i, j-1)){ count++;} 
if(tileHasMine(i-1, j)){ count++;} 
if(tileHasMine(i+1, j)){ count++;} 
if(tileHasMine(i, j+1)){ count++;} 
if(tileHasMine(i-1, j+1)){ count++;} 
if(tileHasMine(i+1, j-1)){ count++;} 
if(tileHasMine(i+1, j+1)){ count++;} 
String mineNum = String.valueOf(count); 
cell[i][j].setText(mineNum); 

或者,你可以寫一個布爾函數,首先檢查塊出來的甚至在試圖從中讀取模型之前,這可能是一個更好的方法。但我認爲這是你問的問題。