为了完成家庭作业,我必须重现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"
*/
详细说明我得到的奇怪结果:
我确信自己已经习惯了一些坏习惯,而且我已经准备好了解更有经验的开发人员,可以指出我错过或做得不好的事情。
我接近结果(我确定了!)所以感谢您带来的任何帮助。
这是我的家庭作业项目的代码。
#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;
}
答案 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()
。
您的示例的每个其他函数都使用“函数式方法”返回更改的本地副本作为调用者站点上分配的结果。
这不是很时尚且效率低下但是它正常工作(关于存储)。
考虑到这一点以及有关更新州的评论所建议的内容,您应该能够掌握它。