2011-05-14 26 views
2

我有以下代碼。唯一的問題是我們通過一個checkstyle程序來運行它,它出現錯誤Cyclomatic Complexity是11(最大允許值是10)。我想知道如何刪除if語句中的一個,以使其執行相同的操作並讓程序通過測試。如何刪除其中的一個if語句並縮短代碼?

/** 
* Check if there is a winner on the board 
* @return the winner if BLANK there is no winner 
**/ 

public char checkWinner(){ 
    this.winner = BLANK; 
    int totalTiles = GRIDSIZE*GRIDSIZE; 

    //Check if the game has a win 
    for (int i=0; i < GRIDSIZE; i++) { 

    if((grid[i][0] == grid[i][1]) && (grid[i][1] == grid[i][2])){ 
     winner = grid[i][0]; 
     return winner; 
    } 
    if((grid[0][i] == grid[1][i]) && (grid[1][i] == grid[2][i])){ 
     winner = grid[0][i]; 
     return winner; 
    } 

    } 

    if((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])){ 
     winner = grid[0][0]; 
     return winner; 
    } 

    if((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0])){ 
     winner = grid[0][2]; 
     return winner; 
    } 
    //Check if the game is a tie 

    if (movesMade == totalTiles){ 
    winner = TIE; 
    } 
    return winner; 
} 
+0

幾乎是它是檢查3x3的井字遊戲的贏家。 – ron8 2011-05-14 15:16:42

+0

這是一個愚蠢的檢查運行..代碼看起來很可讀.. – Claudiu 2011-05-14 15:24:04

+0

看起來是可讀的,我可以看到,減少if語句的數量,而不損害可讀性的唯一的事情是捕獲他們在一個方法和迭代它,而不是if語句:'boolean checkWinner(GRID_TYPE squrare1,GRID_TYPE aquare2,GRID_TYPE square3)'返回是否有勝利(並設置this.winner)。我不知道我會做到這一點,或只是保持原樣。 – amit 2011-05-14 15:27:36

回答

2

您可以提取用於檢查的行和列的方法和重寫你的代碼是這樣的:

public char checkWinner() 
{  
    for (int i=0; i < GRIDSIZE; i++) { 
     if (checkRow(i)) return winner; 
     if (checkColumn(i)) return winner;  
    } 

    if (checkDiagTopLeft()) return winner; 
    if (checkDiagBottomLeft()) return winner; 
} 

更容易閱讀和更低的複雜性。

附註:很顯然,winner的東西可以使用重新設計,但這不是問題的一部分,如果他們有這種感覺,那麼對讀者(和評論者)來說就是一個練習。

+1

這正是應該完成的事情類型,但修改submethod中的成員字段獲勝者並在外部返回類似於我認爲這是一種代碼味道。 – 2011-05-14 15:39:32

+0

使用幫助器方法是最好的方法。我喜歡你的想法! – ron8 2011-05-14 15:41:41

+1

什麼設置贏家?如果你問我這種醜陋的代碼 – gshauger 2011-05-14 16:02:42

3

我不知道怎麼檢查的作品,但這個怎麼樣:

if(((grid[0][0] == grid[1][1]) && (grid[1][1] == grid[2][2])) || 
    ((grid[0][2] == grid[1][1]) && (grid[1][1] == grid[2][0]))) { 
    winner = grid[1][1]; 
    return winner; 
} 

如果這樣做的工作,當然,諷刺的是,這似乎比你的代碼少一點可讀性。

+0

該死的它不起作用。它還檢查操作員。這真的很煩人。謝謝您的幫助! – ron8 2011-05-14 15:29:02

+0

您的解決方案返回了錯誤的獲勝地點 – gshauger 2011-05-14 15:29:17

+1

這與您認爲獲勝者總是在[1] [1] – 2011-05-14 15:30:55

-1

Cyclometric複雜度是衡量通過您的代碼的路徑數量。您的功能幾乎完全由if聲明組成。

您可以將兩個或兩個以上if語句與or

if(a) 
    do_something(); 
if(b) 
    do_something(); 

應改爲:

if(a || b) 
    do_something(); 
+0

圓環complexicty確實包含或/和等,否則全局圈複雜度將不會是11. – 2011-05-14 15:32:07

1

的解決方案已經在那裏(相結合的if語句),但我會如果方法的代碼適合單個頁面,不要讓Cyclomatic Complexity指定我的編碼。你想要在一個大項目中採取的措施是可讀性和易於理解。請記住,代碼只會被寫入一次,但會讀取很多次。

0

第一步可以從等號中刪除一些冗餘。 allEqual使意圖更加清晰。

把勝利者帶到一個領域很陌生。我在重構中刪除了它。如果你真的需要這個任務,你可以用一個獨立的方法調用checkWinner。返回和分配的問題是,它是意外的呼叫者副作用

public char checkWinner() { 
    // Check if the game has a win 
    for (int i = 0; i < GRIDSIZE; i++) { 
     if (allEqual(grid[i][0], grid[i][1], grid[i][2])) return grid[i][0]; 
     if (allEqual(grid[0][i], grid[1][i], grid[2][i])) return grid[0][i]; 
    } 

    if (allEqual(grid[0][0], grid[1][1], grid[2][2])) return grid[0][0]; 
    if (allEqual(grid[0][2], grid[1][1], grid[2][0])) return grid[0][2]; 

    // Check if the game is a tie 
    int totalTiles = GRIDSIZE * GRIDSIZE; 
    return movesMade == totalTiles ? TIE : BLACK; 
} 

private boolean allEqual(char... c) { 
    for(int i=1;i<c.length;i++) if(c[i-1] != c[i]) return false; 
    return true; 
} 

打開的問題:

  • 炭[] []數組是不是最有效的數據結構來表示板。你可以使用一個BitSet。
  • 您定義了GRIDSIZE常量,但如果實際上將它從3更改爲另一個值,則可能會發生故障。
  • 您可以使用檢查行/列和對角線是對稱的事實。使用這個參數必須轉置。

使用GRIDSIZE常數,你不必明確處理的所有單元格:

public char checkWinner() { 
    // Check if the game has a win 
    for (int i = 0; i < GRIDSIZE; i++) { 
     if (rowEqual(i)) return grid[i][0]; 
     if (columnEqual(i)) return grid[0][i]; 
    } 

    if (diagonalLeftToRightEqual()) return grid[0][0]; 
    if (diagonalRightToLefttEqual()) return grid[0][GRIDSIZE]; 

    // Check if the game is a tie 
    int totalTiles = GRIDSIZE * GRIDSIZE; 
    return movesMade == totalTiles ? TIE : BLACK; 
} 

private boolean rowEqual(int r) { 
    for(int i=1;i<GRIDSIZE;i++) if(grid[r][i-1] != grid[r][i]) return false; 
    return true; 
} 

private boolean diagonalLeftToRightEqual() { 
    for(int i=1;i<GRIDSIZE;i++) if(grid[i-1][i-1] != grid[i][i]) return false; 
    return true; 
}