2014-12-13 220 views
0

康威的生活遊戲的工作,我覺得我很接近完成它,但我的邏輯有一些缺陷。我已經爲此傾注了好幾個小時,我只是覺得第二雙眼睛能夠比我更快地發現我的錯誤。我的程序編譯得很好,但輸出結果並不遵循特定位置的遊戲準則(第0行,第1行在第二代時有生命,但不應該,但第10行似乎按預期工作)。對於任何不熟悉的人: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life#Rules生命遊戲的邏輯錯誤(C++)

我幾乎可以肯定邏輯錯誤發生在函數advGen中。以下鏈接保存了readGrid使用的細菌內容:http://pastebin.com/6vurFRSB

感謝您花時間閱讀並幫助您選擇這樣做。

//sample setup to start the game of life - startlife.cpp 

#include <iostream> 
#include <fstream> 
#include <iomanip> 
using namespace std; 

const int SIZE = 20; 

//initial function prototypes 
void initGrid(bool life[][SIZE], bool nextGen[][SIZE]); 
void readGrid(bool life[][SIZE], bool nextGen[][SIZE]); 
void printGrid(bool life[][SIZE], bool nextGen[][SIZE]); 
void advGen(bool life[][SIZE], bool nextGen[][SIZE]); 

int main() 
{ 
    bool life[SIZE][SIZE]; 
    bool nextGen[SIZE][SIZE]; 

    readGrid(life, nextGen); 
    /* for (int count = 0; count < 5; count++){ 
     determineNextGen(life); 
    }*/ 

    printGrid(life, nextGen); 
    advGen(life, nextGen); 
    printGrid(life, nextGen); 

    return 0; 
} 


/*------------------------------------------------------- 

      readGrid (and related functions) 

---------------------------------------------------------*/ 

void readGrid(bool life[][SIZE], bool nextGen[][SIZE]) 
{ 
    ifstream infile("bacteria.txt"); //see class site project#5 for data file 

    int numBacteria, row, col; 

    initGrid(life, nextGen); 

    infile >> row >> col; 
    while (infile){ 
     life[row][col] = true; 
     infile >> row >> col; 
    } 
    infile.close(); 
} 


void initGrid(bool life[][SIZE], bool nextGen[][SIZE]) 
{ 
    for (int row = 0; row < SIZE; row++) 
    { 
     for (int col = 0; col < SIZE; col++){ 
      life[row][col] = false; 
     } 
    } 
    for (int row = 0; row < SIZE; row++) 
    { 
     for (int col = 0; col < SIZE; col++){ 
      nextGen[row][col] = false; 
     } 
    } 
} 

void printGrid(bool life[][SIZE], bool nextGen[][SIZE]) 
{ 
    cout << "" << endl; 
    for (int row = 0; row < SIZE; row++) 
    { 
     cout << setw(2) << row; 
     for (int col = 0; col < SIZE; col++) 
     { 
      if (life[row][col]) 
      { 
       cout << "*"; 
      } 
      else 
      { 
       cout << " "; 
      } 
     } 
     cout << endl; 
    } 
} 

void advGen(bool life[][SIZE], bool nextGen[][SIZE]) 
{ 
    int neighbor = 0; 

    for (int row = 0; row < SIZE; row++) 
    { 
     for (int col = 0; col < SIZE; col++) 
     { 
      if (row == 0) 
      { 
       if (col == 0) 
       { 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row + 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
       else if (col == 19) 
       { 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row + 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
       else 
       { 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row + 1][col + 1] == true) 
         ++neighbor; 
        if (life[row + 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
      } 
      if (row == 19) 
      { 
       if (col == 0) 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
       else if (col == 19) 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row - 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
       else 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col - 1] == true) 
         ++neighbor; 
        if (life[row - 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
      } 
      if (col == 0) 
      { 
       if (row == 0) 
       { 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row + 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         //nothing 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         //nothing 
        } 
       } 
       else if (row == 19) 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         //nothing 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         //nothing 
        } 
       } 
       else 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col + 1] == true) 
         ++neighbor; 
        if (life[row + 1][col + 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
      } 
      if (col == 19) 
      { 
       if (row == 0) 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row + 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         //nothing 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         //nothing 
        } 
       } 
       else if (row == 19) 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row - 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         //nothing 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         //nothing 
        } 
       } 
       else 
       { 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row + 1][col - 1] == true) 
         ++neighbor; 
        if (life[row - 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       } 
      } 
      else 
       { 
        if (life[row - 1][col] == true) 
         ++neighbor; 
        if (life[row + 1][col] == true) 
         ++neighbor; 
        if (life[row][col - 1] == true) 
         ++neighbor; 
        if (life[row][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col - 1] == true) 
         ++neighbor; 
        if (life[row + 1][col + 1] == true) 
         ++neighbor; 
        if (life[row - 1][col + 1] == true) 
         ++neighbor; 
        if (life[row + 1][col - 1] == true) 
         ++neighbor; 
        if ((life[row][col] == true) && (neighbor < 2 || neighbor > 3)) 
        { 
         nextGen[row][col] = false; 
        } 
        else if ((life[row][col] == false) && (neighbor == 3)) 
        { 
         nextGen[row][col] = true; 
        } 
       }neighbor = 0; 
     } 
    } 
    for (int row = 0; row < SIZE; row++) 
     { 
     for (int col = 0; col < SIZE; col++) 
      { 
       life[row][col] = nextGen[row][col]; 
      } 
     } 

} 
+1

你有很多重複的代碼在那裏會受益於被移入單獨的功能。它會讓你的代碼更容易閱讀。 – David 2014-12-13 03:26:28

+0

_你擁有的'== true'的每一次使用都是100%冗餘的,而不是視覺噪聲。如果你只是將這些'bool'轉換爲'int'並添加它們,那麼'if(life [...])++ neighbour'的_huge_棧可以簡化爲幾行一起。爲了避免邊界邏輯以更多內存爲代價,你可以用左邊,右邊,上邊和下邊填充板,並且不要寫在它們上面。 – 2014-12-13 03:42:57

回答

1

您的代碼重複計算鄰居的數量。這是因爲,例如,如果row是0並且col是0,則它在頂部執行row == 0事件,並且如果大約100行進一步向下執行,則執行col == 0內部的row == 0事件。

解決此問題的一種方法是使用正確的else子句。即做類似的事情:

if (row == 0) 
{ 
    ... 
} 
else if (row == 19) 
{ 
    ... 
} 
else 
{ 
    ... 
} 

你也需要這樣做的列案例。

更好的解決方案是查看所有這些特殊情況,並嘗試將它們合理化爲代碼重複性較低的內容。

你試圖實現的是防止讀取數組邊界之外。

一個簡單的方法來做到這一點是有一個函數在row, col,檢查rowcol並返回false如果rowcol是出界,以獲得陣列的價值。然後,您可以爲每個位置的8個周圍塊中的每個塊調用該函數,而無需針對行0和19以及列0和19的特殊情況。

我建議嘗試編寫上面的函數,而不是我只是在這裏爲你粘貼它。

編輯:另外請注意 - 你並不總是將值設置到nextGen,所以你殺死的是有生命有2個或3相鄰的小區,你可能需要重新考慮你的if/else語句分配到nextGen

+0

我會投這個票,但我太新了。我非常感謝你的解釋,我想知道是否有更簡單的方法來做到這一點。非常感謝! – 2014-12-13 03:51:38

+0

我試着寫了你所建議的功能,但在我用更多的代碼讓自己感到難堪之前,你是否可以試着解釋函數做了什麼不同的方法? – 2014-12-13 05:32:52

+0

該函數需要將'life'數組作爲參數和'row'和'col'的參數。然後需要檢查'row'和'col'是否在數組內(即> = 0和 2014-12-13 09:25:25