我试图用C ++编写着名的生命游戏代码。这是我到目前为止所得到的。当我运行它时,它给出了一个初始的随机细胞群,但下一代似乎不起作用。我的代码出了什么问题?
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
int main(){
//Number of rows and columns
const char live = '*';
const char dead = ' ';
const int rows = 10;
const int cols = 10;
char life[rows][cols];
char life1[rows][cols];
int ans=0;
//create initial generation randomly
srand (time(NULL));
int cell;
for(int r=0; r<rows; r++){
for(int c=0; c<cols; c++){
cell= rand()%10;
if(cell >= 5){
life[r][c] = live;
}
else {
life[r][c] = dead;
}
}
}
for(int r=0; r < rows; r++){
for(int c = 0; c<cols;c++){
cout << life[r][c] << " ";
}
cout << endl;
}
for(int k=0; k <10;k++){
for(int r=0; r < rows; r++){
for(int c=0;c<cols;c++){
if(life[r][c] == live){
if((c-1) >=1 && (life[r][c-1] == live))
ans++;
if(c<cols && (life[r][c+1] == live))
ans++;
if(c<cols && r<rows && (life[r+1][c+1] == live))
ans++;
if(r<rows && (life[r+1][c] == live))
ans++;
if(c<cols && c >=0 && (life[r+1][c-1] == live))
ans++;
if(r>=0 && c >=0 && (life[r-1][c-1] == live))
ans++;
if(r>=0 && (life[r-1][c]==live))
ans++;
if(r>=0 && c<cols && (life[r-1][c+1] == live))
ans++;
if(ans==2 || ans==3)
life[r][c]= live;
if(ans>3)
life[r][c]= dead;
if(ans<2)
life[r][c]=live;
}
else {
if( life[r][c]==dead){
if(c>=0 && (life[r][c-1]==dead))
ans++;
if(c<cols && (life[r][c+1]==dead))
ans++;
if(r<rows && c<cols && (life[r+1][c+1]==dead))
ans++;
if(r<rows && (life[r][c]==life[r+1][c]))
ans++;
if(r<rows && c>0 && (life[r][c]==life[r+1][c-1]))
ans++;
if(r>=0 && c>=0 && (life[r][c]==life[r-1][c-1]))
ans++;
if(r>=0 &&(life[r][c]==life[r-1][c]))
ans++;
if(r>=0 && c<cols && (life[r][c] == life[r-1][c+1]))
ans++;
if(ans==3)
life[r][c]=live;
}
}
}
}
for(int r=0; r<rows; r++){
for(int c=0; c< cols; c++){
life[r][c]=life1[r][c];
}
}
for(int r=0; r<rows;r++){
for(int c =0; c<cols;c++){
cout << life[r][c] << " ";
}
cout<<endl;
}
}
return 0;
}
答案 0 :(得分:2)
让我们从使代码工作所需的最小更改开始。
ans
:在内循环开始时(超过cols
),设置ans = 0;
,否则计算在3
以上,永远不会返回,一切都会停留{ {1}} dead
数组计算的,因此在计算生成时不要更改此数组。而是将结果写入life
。在每个外部(life1
)迭代结束时,结果将被复制回k
。life
案例结束时,少于2个邻居,单元格应按规则死亡。因此,请指定if (life[r][c] == live)
而不是if (ans < 2) life1[r][c] = dead;
。live
完成作业:对于其他情况(life1
),请添加if (life[r][c] == dead)
以确保完整初始化:else
。if(ans==3) life1[r][c] = live; else life1[r][c] = dead
开始):0
省略第一个索引。替换为if ((c - 1) >= 1 && (life[r][c - 1] == live))
if (c >= 1 && (life[r][c - 1] == live))
结尾)。 size-1
超出范围,用if(c < cols && (life[r][c + 1] == live))
替换以保持在界限范围内。if((c + 1) < cols && (life[r][c + 1] == live))
语句中的数组边界,方法与两个示例中描述的方式相同。现在继续进行代码设计:我建议你创建一个函数if
,在其中放置所有逻辑来计算活的邻居单元格。然后替换主要的巨大int count_living_neighbors(char life[10][10], int rowPos, int colPos)
级联:
if
关于for(int k = 0; k < 10; k++)
{
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
int count = count_living_neighbors(life, r, c);
if(life[r][c] == live)
{
if(count == 2 || count == 3)
life1[r][c] = live;
else
life1[r][c] = dead;
}
else
{
if(count == 3)
life1[r][c]=live;
else
life1[r][c]= dead;
}
}
}
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
life[r][c] = life1[r][c];
}
}
for(int r = 0; r < rows; r++)
{
for(int c = 0; c < cols; c++)
{
cout << life[r][c] << " ";
}
cout << endl;
}
}
的说明:实际上最好将count_living_neighbors
以及行和列大小作为参数。但它使得数组算术不太明显。
修改强>
将常量值移动到全局范围,char* life
函数可能如下所示:
count_living_neighbors
答案 1 :(得分:2)
grek40已经给出了实际答案,但我认为给你一些关于编码风格的建议并不会有什么坏处。这个答案基于grek40的代码。
首先,如果您处理某些数据结构,这是一个明确的信号,表明您需要一个类。我也将摆脱数组(你想避免使用C ++中的数组)并使用枚举使单元格的状态更具可读性。
让我们从一个位于头文件中的界面开始。
#include <vector>
using std::vector;
enum CellState{ //replacing your char* with CellState
dead, alive
};
class GameOfLife{
public:
GameOfLife(const unsigned int rows, const unsigned int cols);
virtual ~GameOfLife(){}; //can omit the virtual if no subclasses are guaranteed
void iterate(const unsigned int iterations = 1); //can do several steps at once, one step at a time is the assumed default
void print() const;
private:
vector<vector<CellState> > state;
void initialize(const unsigned int rows, const unsigned int cols); //does the randomization
unsigned int neighbors(const unsigned int row, const unsigned int col) const;
}
该课程使您的主要功能看起来非常容易阅读:
#include "GameOfLife.h"
int main(){
GameOfLife game(10,10);
game.print(); //print initial configuration
game.iterate(); //or iterate(10) or how many steps you want
game.print(); //print configuration at the end
return 0;
}
让我们继续这个类的实现,位于GameOfLife.cpp中。我现在将省略像iostream这样的必要包括。
让我们从简单的开始,打印:
inline char state_to_char(const CellState state){
if(state == dead){
return ' ';
}
return '*';
}
void GameOfLife::print() const{
for(unsigned int r = 0; r < state.size(); r++){
for(unsigned int c = 0; c < state[r].size(); c++){
cout << state_to_char(state[r][c]) << " ";
}
cout << endl;
}
}
现在进行初始化:
void GameOfLife::initialize(const unsigned int rows, const unsigned int cols){
state.resize(rows);
for(unsigned int r = 0, r < rows, r++){
state[r].resize(cols);
}
insert your code of randomly assigning dead or alive with changed names
}
构造函数变为
GameOfLife::GameOfLife(const unsigned int rows, const unsigned int cols){
initialize(rows, cols);
}
(创建初始化以便以后在需要时更容易引入新的构造函数)
unsigned int neighbors就像grek40设计的count_living_neighbors。
对于核心部分,迭代:
//function to resize any vector^2
template<class T>
void resize(vector<vector<T> >& target, const unsigned int dx, const unsigned int dy){
target.resize(dx);
for(unsigned int i=0; i<dx; i++){
target[i].resize(dy);
}
}
GameOfLife::iterate(const unsigned int iterations){
unsigned int rows = state.size();
unsigned int cells = 0;
if(rows != 0){
cells = state[0].size();
}
vector<vector<CellState> > new_state;
resize(new_state, rows, cells);
for(unsigned int iteration = 0; iteration < iterations; iteration++){
for(unsigned int r = 0; r < rows; r++){
for(unsigned int c = 0; c < cells; c++){
unsigned int count = neighbors(r, c);
if(state[r][c] == alive){
if(count == 2 || count == 3){
new_state[r][c] = alive;
}else{
new_state[r][c] = dead;
}else{
if(count == 3){
new_state[r][c] = alive;
}else{
new_state[r][c] = dead;
}
}
}//end for c
}//end for r
state = new_state;
}//end for iteration
}
现在,总而言之,这是比以前更多的代码,但对于它的任何部分,我们确切知道它的作用,可以轻松读取它,如果有错误,我们可以使用a轻松找到错误调试器。