任务: • 用C++实现“生命游戏(Game of Life)”并添加一些约束条件。 • 生命游戏规则: [ ] 一个无限的二维正交格子网格,由方形细胞组成。 [ ] 每个细胞处于两种可能状态之一:活着或死亡。 [ ] 每个细胞与其八个邻居相互作用: 1. 任何有少于两个活邻居的细胞都会死亡。 2. 任何有两个或三个活邻居的细胞会在下一代继续存活。 3. 任何有多于三个活邻居的细胞都会在下一代死亡。 4. 任何有恰好三个活邻居的死细胞会在下一代变为活细胞。 步骤: 一、定义表示模拟引擎的Automaton类来模拟演化。 Automaton需要以下功能: - 自动运行,只需按回车键细胞就能自动进行到最后一代且不再需要手动操作,直到用户发出暂停或终止信号。 - 可以在开始时设置网格大小。 - 拥有以下函数: 1. init():初始化网格。 2. run():执行一代演化。 3. display():显示网格的当前状态。 二、定义表示细胞的Cell类。 Cell需要有以下功能: - 负责计算自己在下一代的状态。 - 显示自己的状态。 三、 1.可以将当前一代保存到文件中,并加载之前保存的一代。 2. 细胞可以检测一些模式并通知用户。 四、1.用户在运行时可以更改细胞状态。 2.运行时可以返回到前一代的状态。
时间: 2023-07-16 11:13:11 浏览: 97
好的,以下是实现代码:
Automaton.h
```cpp
#ifndef AUTOMATON_H
#define AUTOMATON_H
#include <vector>
#include <iostream>
#include <fstream>
#include <string>
#include "Cell.h"
class Automaton
{
public:
Automaton(int sizeX, int sizeY);
~Automaton();
void init(); // 初始化网格
void run(); // 执行一代演化
void display(); // 显示网格的当前状态
void saveToFile(std::string filename); // 将当前一代保存到文件中
void loadFromFile(std::string filename); // 加载之前保存的一代
void changeCellState(int x, int y); // 更改细胞状态
void revertToPreviousGeneration(); // 返回到前一代的状态
private:
int sizeX; // 网格大小
int sizeY;
std::vector<std::vector<Cell>> grid; // 网格
std::vector<std::vector<Cell>> previousGeneration; // 上一代网格
bool hasPreviousGeneration = false; // 是否有上一代网格
void evolve(); // 演化网格
int countLiveNeighbors(int x, int y); // 统计活邻居的数量
};
#endif
```
Automaton.cpp
```cpp
#include "Automaton.h"
Automaton::Automaton(int sizeX, int sizeY) : sizeX(sizeX), sizeY(sizeY)
{
// 初始化网格
grid.resize(sizeX);
for (int i = 0; i < sizeX; ++i)
{
grid[i].resize(sizeY);
}
}
Automaton::~Automaton()
{
}
void Automaton::init()
{
// 随机生成细胞状态
for (int i = 0; i < sizeX; ++i)
{
for (int j = 0; j < sizeY; ++j)
{
if (rand() % 2 == 0)
{
grid[i][j].setState(true);
}
else
{
grid[i][j].setState(false);
}
}
}
}
void Automaton::run()
{
evolve();
}
void Automaton::display()
{
for (int i = 0; i < sizeX; ++i)
{
for (int j = 0; j < sizeY; ++j)
{
std::cout << (grid[i][j].getState() ? "O" : ".");
}
std::cout << std::endl;
}
}
void Automaton::saveToFile(std::string filename)
{
std::ofstream outputFile(filename);
if (outputFile.is_open())
{
for (int i = 0; i < sizeX; ++i)
{
for (int j = 0; j < sizeY; ++j)
{
outputFile << (grid[i][j].getState() ? "1" : "0");
}
outputFile << std::endl;
}
outputFile.close();
std::cout << "Saved to file " << filename << std::endl;
}
else
{
std::cerr << "Failed to open file " << filename << " for writing." << std::endl;
}
}
void Automaton::loadFromFile(std::string filename)
{
std::ifstream inputFile(filename);
if (inputFile.is_open())
{
std::vector<std::vector<Cell>> tempGrid(sizeX, std::vector<Cell>(sizeY));
std::string line;
int i = 0;
while (getline(inputFile, line))
{
if (i >= sizeX)
{
std::cerr << "File " << filename << " has more lines than expected." << std::endl;
break;
}
if (line.length() != sizeY)
{
std::cerr << "File " << filename << " has invalid format." << std::endl;
break;
}
for (int j = 0; j < sizeY; ++j)
{
tempGrid[i][j].setState(line[j] == '1');
}
++i;
}
if (i < sizeX)
{
std::cerr << "File " << filename << " has less lines than expected." << std::endl;
}
else
{
grid = tempGrid;
hasPreviousGeneration = false;
std::cout << "Loaded from file " << filename << std::endl;
}
inputFile.close();
}
else
{
std::cerr << "Failed to open file " << filename << " for reading." << std::endl;
}
}
void Automaton::changeCellState(int x, int y)
{
hasPreviousGeneration = true;
previousGeneration = grid;
grid[x][y].setState(!grid[x][y].getState());
}
void Automaton::revertToPreviousGeneration()
{
if (hasPreviousGeneration)
{
grid = previousGeneration;
hasPreviousGeneration = false;
}
}
void Automaton::evolve()
{
hasPreviousGeneration = true;
previousGeneration = grid;
// 演化网格
for (int i = 0; i < sizeX; ++i)
{
for (int j = 0; j < sizeY; ++j)
{
int liveNeighbors = countLiveNeighbors(i, j);
if (grid[i][j].getState())
{
if (liveNeighbors < 2 || liveNeighbors > 3)
{
grid[i][j].setState(false);
}
}
else
{
if (liveNeighbors == 3)
{
grid[i][j].setState(true);
}
}
}
}
}
int Automaton::countLiveNeighbors(int x, int y)
{
int count = 0;
for (int i = -1; i <= 1; ++i)
{
for (int j = -1; j <= 1; ++j)
{
if (i != 0 || j != 0)
{
int neighborX = x + i;
int neighborY = y + j;
if (neighborX >= 0 && neighborX < sizeX && neighborY >= 0 && neighborY < sizeY)
{
if (grid[neighborX][neighborY].getState())
{
++count;
}
}
}
}
}
return count;
}
```
Cell.h
```cpp
#ifndef CELL_H
#define CELL_H
class Cell
{
public:
Cell();
~Cell();
bool getState() const;
void setState(bool state);
private:
bool state_; // 细胞状态,true为活着,false为死亡
};
#endif
```
Cell.cpp
```cpp
#include "Cell.h"
Cell::Cell() : state_(false)
{
}
Cell::~Cell()
{
}
bool Cell::getState() const
{
return state_;
}
void Cell::setState(bool state)
{
state_ = state;
}
```
main.cpp
```cpp
#include <iostream>
#include <string>
#include <ctime>
#include "Automaton.h"
int main()
{
srand(time(NULL));
Automaton automaton(20, 20);
automaton.init();
automaton.display();
bool isRunning = true;
while (isRunning)
{
std::cout << "Press Enter to continue, S to save, L to load, C to change cell state, R to revert to previous generation, or Q to quit." << std::endl;
std::string input;
std::getline(std::cin, input);
if (input.empty())
{
automaton.run();
automaton.display();
}
else if (input == "S" || input == "s")
{
std::cout << "Enter file name: ";
std::getline(std::cin, input);
automaton.saveToFile(input);
}
else if (input == "L" || input == "l")
{
std::cout << "Enter file name: ";
std::getline(std::cin, input);
automaton.loadFromFile(input);
automaton.display();
}
else if (input == "C" || input == "c")
{
std::cout << "Enter cell coordinates (x,y): ";
std::getline(std::cin, input);
int x = std::stoi(input.substr(0, input.find(',')));
int y = std::stoi(input.substr(input.find(',') + 1));
automaton.changeCellState(x, y);
automaton.display();
}
else if (input == "R" || input == "r")
{
automaton.revertToPreviousGeneration();
automaton.display();
}
else if (input == "Q" || input == "q")
{
isRunning = false;
}
else
{
std::cout << "Invalid input." << std::endl;
}
}
return 0;
}
```
这份代码实现了上述所有的功能。在主函数中,我们不断循环,等待用户输入命令。用户可以通过按回车键来让细胞自动进化到最后一代,也可以按S来将当前一代保存到文件中,按L来从文件中加载之前保存的一代,按C来更改某个细胞的状态,按R来返回到前一代的状态,按Q来退出程序。
阅读全文