康威游戏生活奇怪的结果

时间:2017-06-07 21:09:15

标签: c

为了完成家庭作业,我必须重现Conway的生命游戏项目。

不幸的是,我得到了奇怪的结果,我想因为C语言对我来说是新的,我最近更关注php。

首先我给出项目的规格:

 * The Game of Life
 * http://en.wikipedia.org/wiki/Conway's_Game_of_Life
 *
 * Key requirements :
 * - Limit the size of the world to 10x10 cells
 * - The world (grid) must be a struct composed by cells
 * - A cell must be a struct
 * - Each cell is in one of two possible states : Live or Dead
 * - Any live cell with fewer than two live neighbours dies, as if caused by under-population
 * - Any live cell with two or three live neighbours lives on to the next generation
 * - Any live cell with more than three live neighbours dies, as if by overcrowding
 * - Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction
 * - Between each generation, ask if it's necessary to restart the next generation or to leave the game
 * - Having dedicated function displayWorld() to display a representation of this world
 * - Having dedicated function newGeneration() to generate next step of the world
 * - In the function above, implement conditions based on cell's neighbors to define if each cell is alive or dead
 * - Alive cells are represented by a "+"
 * - Dead cells are represented by a "-"
 * - New borned cells are represented by a "0"
 */

详细说明我得到的奇怪结果:

  • 我有来自loadInitData函数的硬编码值,但有时它会在随机位置的网格中显示0丢失我 * never * 指定...
  • 很快,Conway Game of Life终止很快,任何活细胞都消失了

我确信自己已经习惯了一些坏习惯,而且我已经准备好了解更有经验的开发人员,可以指出我错过或做得不好的事情。

我接近结果(我确定了!)所以感谢您带来的任何帮助。

这是我的家庭作业项目的代码。

#include <stdio.h>
#define NEW '0'
#define LIVE '+'
#define DEAD '-'
#define xSize 10
#define ySize 10

typedef struct {
    char status;
} Cell;

typedef struct {
    int sizeX;
    int sizeY;
    Cell cell[xSize][ySize];
} World;

void displayWorld(World grid) {
    int x, y;
    for (y = 0; y < grid.sizeY; y++) {
        for (x = 0; x < grid.sizeX; x++) {
            if (grid.cell[y][x].status == NEW) {
                printf("0");
            } else if (grid.cell[y][x].status == LIVE) {
                printf("+");
            } else {
                printf("-");
            }
        }
        printf("\n");
    }
    printf("\n");
}

int getNeighborValue(World grid, int row, int col) {
    if (row < 0 || row >= grid.sizeY
            || col < 0 || col >= grid.sizeX
            || grid.cell[row][col].status != LIVE )
    {
        return 0;
    } else {
        return 1;
    }
}

int getNeighborCount(World grid, int row, int col) {
    int neighbor = 0;

    neighbor += getNeighborValue(grid, row - 1, col - 1);
    neighbor += getNeighborValue(grid, row - 1, col);
    neighbor += getNeighborValue(grid, row - 1, col + 1);
    neighbor += getNeighborValue(grid, row, col - 1);
    neighbor += getNeighborValue(grid, row, col + 1);
    neighbor += getNeighborValue(grid, row + 1, col - 1);
    neighbor += getNeighborValue(grid, row + 1, col);
    neighbor += getNeighborValue(grid, row + 1, col + 1);

    return neighbor;
}

World newGeneration(World grid) {
    int neighbor, x, y;

    for (y = 0; y < grid.sizeY; y++) {
        for (x = 0; x < grid.sizeX; x++) {
            neighbor = getNeighborCount(grid, y, x);

            if (grid.cell[y][x].status == NEW || grid.cell[y][x].status == LIVE) {
                if (neighbor > 3) {
                    grid.cell[y][x].status = DEAD;
                } else if (neighbor == 2 || neighbor == 3) {
                    grid.cell[y][x].status = LIVE;
                } else {
                    grid.cell[y][x].status = DEAD;
                }
            } else {
                if (neighbor == 3) {
                    grid.cell[y][x].status = NEW;
                }
            }
        }
    }

    return grid;
}

void clearWorld(World grid) {
    int x, y;
    for (y = 0; y < grid.sizeY; y++) {
        for (x = 0; x < grid.sizeX; x++) {
            Cell cell;
            cell.status = DEAD;
            grid.cell[y][x] = cell;
        }
    }
}

World loadInitData(World grid) {
    int x, y, i, n, v;

    printf("Enter the amount of initial organisms: ");
    scanf("%d", &n);

    printf("Would you like organisms randomly generated or defined by you (0: random; 1: you)? ");
    scanf("%d", &v);

    if (v == 1) {
        for (i = 0; i < n; i++) {
            printf("Enter dimensions (x y) where organism %d will live: ", i + 1);
            scanf("%d %d", &x, &y);
            grid.cell[y][x].status = LIVE;
        }
    } else {
        // for (i = 0; i < n; i++) {
        //  x = rand() % grid.sizeX;
        //  y = rand() % grid.sizeY;
        //  grid.cell[y][x].status = LIVE;
        // }

        grid.cell[3][4].status = LIVE;
        grid.cell[3][5].status = LIVE;
        grid.cell[3][6].status = LIVE;
        grid.cell[6][4].status = LIVE;
        grid.cell[6][5].status = LIVE;
        grid.cell[6][6].status = LIVE;
        grid.cell[7][6].status = LIVE;
        grid.cell[8][5].status = LIVE;
    }

    return grid;
}

int main() {
    World grid;
    grid.sizeX = xSize;
    grid.sizeY = ySize;
    char end;
    int generation = 0;
    clearWorld(grid);
    grid = loadInitData(grid);
    displayWorld(grid);
    printf("Generation %d\n", 0);
    printf("Press q to quit or 1 to continue: ");
    scanf(" %c", &end);

    do {
        grid = newGeneration(grid);
        displayWorld(grid);
        printf("Generation %d\n", ++generation);
        printf("Press q to quit or 1 to continue: ");
        scanf(" %c", &end);
    } while (end != 'q') ;

    return 0;
}

1 个答案:

答案 0 :(得分:1)

我认为,你有一个重大的错误理解:

在C中:struct被传递给函数按值(即通过复制,与总是传递“ by reference ”的数组相对 - 实际上,由它的起始地址)。即使在struct包含数组的情况下也是如此。

我拿了一些你的样本代码来证明这一点:

#include <stdio.h>

enum {
  NEW = '0',
  LIVE = '+',
  DEAD = '-'
};

typedef struct {
  char status;
} Cell;

enum { xSize = 3, ySize = 3 };

typedef struct {
  int sizeX, sizeY;
  Cell cell[ySize][xSize];
} World;

void displayWorld(World world)
{
  for (int y = 0; y < ySize; ++y) {
    for (int x = 0; x < xSize; ++x) printf("+-");
    printf("+\n");
    for (int x = 0; x < xSize; ++x) {
      printf("|%c", world.cell[y][x].status);
    }
    printf("|\n");
  }
  for (int x = 0; x < xSize; ++x) printf("+-");
  printf("+\n");
}

void modifyWorld(World world, int x, int y, char status)
{
  world.cell[y][x].status = status;
  printf("Modified:\n");
  displayWorld(world);
}

int main()
{
  World world = {
    xSize, ySize
  };
  /* init world */
  for (int y = 0; y < ySize; ++y) {
    for (int x = 0; x < xSize; ++x) world.cell[y][x].status = NEW;
  }
  /* display world */
  printf("Before call of modifyWorld():\n");
  displayWorld(world);
  /* modify world */
  modifyWorld(world, xSize / 2, ySize / 2, LIVE);
  /* display world */
  printf("After call of modifyWorld():\n");
  displayWorld(world);
  /* done */
  return 0;
}

输出结果为:

Before call of modifyWorld():
+-+-+-+
|0|0|0|
+-+-+-+
|0|0|0|
+-+-+-+
|0|0|0|
+-+-+-+
Modified:
+-+-+-+
|0|0|0|
+-+-+-+
|0|+|0|
+-+-+-+
|0|0|0|
+-+-+-+
After call of modifyWorld():
+-+-+-+
|0|0|0|
+-+-+-+
|0|0|0|
+-+-+-+
|0|0|0|
+-+-+-+
Drücken Sie eine beliebige Taste . . .

这表明modifyWorld()确实更改了其本地副本,但未更改world中声明的原始main()

要更改此值,1 st 参数必须变为World *world。 因此,其内容必须由->而不是.访问,例如

world->cell[y][x].status = status;

这会影响您的功能clearWorld()

您的示例的每个其他函数都使用“函数式方法”返回更改的本地副本作为调用者站点上分配的结果。

这不是很时尚且效率低下但是它正常工作(关于存储)。

考虑到这一点以及有关更新州的评论所建议的内容,您应该能够掌握它。