2014-11-01 7 views
8

Ho un codice di Game of Life funzionante. Salva ogni popolazione come una bitmap. Ecco ciò che il risultato è simile (tagliato):Errore di confusione nel programma Game of Life

desired output

Per la pulizia del codice, ho scoperto che se ho commentato fuori o altrimenti rimuovere la linea 60:

cout << "Survivor: " << x << ", " << y << "\n"; 

E scombina completamente il programma , e invece di produrre un aliante come dovrebbe, produce questo:

faulty output

Mi sono messo in giro, cercando di scoprire cosa potrebbe causare questo, ma sono stato fino ad ora infruttuoso. Questo è il mio codice corrente:

//Bitmap Library from http://partow.net/programming/bitmap/ 
#include "bitmap_image.hpp" 
#include <iostream> 
#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 

using namespace std; 

#define WIDTH 160 
#define HEIGHT 128 

bool population[WIDTH][HEIGHT]; 
bool survivors[WIDTH][HEIGHT]; 

int check_survivors(); 
int check_neighbors(int x, int y); 
int write_population(char* file); 

int main() { 
    int i, populations; 

    cout << "Enter number of populations: "; 
    cin >> populations; 

    //Glider 
    survivors[28][100] = true; 
    survivors[29][100] = true; 
    survivors[29][101] = true; 
    survivors[30][101] = true; 
    survivors[28][102] = true; 

    //Initial image generation 
    write_population("population0.bmp"); 

    //populations 
    for (i = 0; i < populations; i++) { 
     char filename[17] = "population"; 
     char ii[3]; 
     sprintf(ii, "%d", i+1); 

     strcat(filename, ii); 
     strcat(filename, ".bmp"); 

     check_survivors(); 
     write_population(filename); 
    } 

    return 0; 
} 

int check_survivors() { 
    //set x and y variables 
    int x, y; 

    for (x = 0; x < WIDTH; x++) { 
     for (y = 0; y < HEIGHT; y++) { 
      if (check_neighbors(x, y)) { 
       survivors[x][y] = true; 
       cout << "Survivor: " << x << ", " << y << "\n"; 
      } else { 
       survivors[x][y] = false; 
      } 
     } 
    } 
    return 0; 
} 

int check_neighbors(int x, int y) { 
    int neighbors = 0, survives; 

    //I really need to rewrite this mess 

    //Neighbors above 
    if (population[x-1][y-1] == true && x != 0 && y != 0) { 
     neighbors++; 
    } 
    if (population[x][y-1] == true && y != 0) { 
     neighbors++; 
    } 
    if (population[x+1][y-1] == true && x != WIDTH-1 && y != 0) { 
     neighbors++; 
    } 

    //Neighbors next to 
    if (population[x-1][y] == true && x != 0) { 
     neighbors++; 
    } 
    if (population[x+1][y] == true && x != WIDTH-1) { 
     neighbors++; 
    } 

    //Neighbors below 
    if (population[x-1][y+1] == true && x != 0 && y != HEIGHT-1) { 
     neighbors++; 
    } 
    if (population[x][y+1] == true && y != HEIGHT-1) { 
     neighbors++; 
    } 
    if (population[x+1][y+1] == true && x != WIDTH-1 && y != HEIGHT-1) { 
     neighbors++; 
    } 

    //Determining life or death 
    if (neighbors < 2 || neighbors > 3) { 
     //Neighbors less than 2 or more than 3 is dead cell 
     survives = 0; 
    } else if (neighbors == 3 && population[x][y] == false) { 
     //Exactly 3 neighbors re-animates a cell 
     survives = 1; 
    } else if (population[x][y] == true) { 
     //2 or 3 neighbors is survivor 
     survives = 1; 
    } 

    return survives; 
} 

int write_population(char* file) { 
    //Create Image 
    bitmap_image image(WIDTH, HEIGHT); 

    //Set background to white 
    image_drawer draw(image); 
    image.set_all_channels(255,255,255); 

    //set x and y variables 
    int x, y; 

    //For every array point, check to see if it survives, 
    //and transfer survivors to population 
    for (x = 0; x < WIDTH; x++) { 
     for (y = 0; y < HEIGHT; y++) { 
      if (survivors[x][y] == true) { 
       draw.pen_width(1); 
       draw.pen_color(0,0,0); 
       draw.plot_pixel(x, y); 
      } 
      population[x][y] = survivors[x][y]; 
     } 
    } 

    //Save image 
    image.save_image(file); 

    //return 
    return 1; 
} 
+0

'sprintf (ii,"% d ", i + 1);' può causare un overflow del buffer, nonché le seguenti chiamate 'strcat'. Riscrivi questo codice. –

risposta

6

Cose come questa:

if (population[x-1][y-1] == true && x != 0 && y != 0) 

bisogno di essere riscritto come:

if (x > 0 && y > 0 && population[x-1][y-1] == true) 

altrimenti sarete direttamente nel territorio indefinito comportamento quando sia x o sono 0 (come saranno diverse volte quando si chiama check_neighbors() da check_survivors()), e ci si può aspettare strano, errori inspiegabili come questo. È necessario verificare la presenza di indici di array non validi prima di si tenta di accedere a tali elementi.

Inoltre, qui:

if (neighbors < 2 || neighbors > 3) { 
    //Neighbors less than 2 or more than 3 is dead cell 
    survives = 0; 
} else if (neighbors == 3 && population[x][y] == false) { 
    //Exactly 3 neighbors re-animates a cell 
    survives = 1; 
} else if (population[x][y] == true) { 
    //2 or 3 neighbors is survivor 
    survives = 1; 
} 

Sembra come se survives potrebbe essere lasciato con un valore indeterminato se neighbors == 2 e population[x][y] == false, che sarebbe anche causare un comportamento indefinito se si dovesse accedere a tale valore. Non è immediatamente chiaro dal tuo codice se quella combinazione di circostanze potrebbe mai essere vera, ma se sei ancora in fase di debug, allora al minimo è utile aggiungere un controllo di condizione per verificare se lo è o non lo è mai.

Se il programma mostra un comportamento indefinito come questo, è praticamente impossibile ragionarlo fino a quando tali problemi non saranno risolti.

+0

@Quicksilver assicurati di leggere su cosa [comportamento non definito] (http://stackoverflow.com/a/4105123/211160) significa davvero, se non lo sai già. È un termine tecnico e non necessariamente familiare a chi viene da altre lingue. – HostileFork

+0

Vale anche la pena aggiungere che l'IDE moderno, come VisualStudio, rende molto più semplice evitare questo tipo di errori. –

3

Non si assegna sempre un valore nella variabile survives ad es. se population[x][y] è false e neighbors è 2. Questo lascia survives con un valore di ciò che è in memoria in quel momento. Quando si aggiunge la chiamata cout, probabilmente accade di impostare quel bit di memoria dello stack su 0, mascherando l'errore del programma.

Aggiungere un valore iniziale a survives quando lo si dichiara.