不确定的行为通过确定主义程序
Undefined behavior with determinist procedure
我目前正在尝试在"生命游戏"想法之后实现"洞穴生成"作为2D数组。这个想法如下:
i的2D向量为0s和1s(分别代表空气和块),该速率用uniform_real_distribution
随机生成的density
(此处为0.45,因此数组的45%为1)。
之后,我们在数组上迭代 x 次。迭代看起来如下:
- 首先,我们将数组复制在新数组中。
- 第二,我们在 old 数组上迭代如下:我们查看我们所处街区附近的块数量,并且根据两件事,我们要这样做:如果当前的瓷砖是空气的,并且在其附近有4个以上的街区(-1,-1)到(1,1),则将其更改为新数组中的一个街区如果当前瓷砖是一个块,其附近的块少于3个块,请将其更改为新数组中的空气
- 复制旧数组中的新数组
问题是,即使我用确定性种子(有时1次)播种我的统一定律时,地图也将在两到三个迭代后完全填充块。我从字面上看了0个想法,为什么在查看我的代码很多小时之后,这就是为什么我在这里。有代码:
cavefactory.h
#ifndef CAVEFACTORY_H_
#define CAVEFACTORY_H_
#include <vector>
namespace cavegenerator {
// define cave_t as a 2d vector of integers
using cave_t = std::vector<std::vector<int>>;
// constants
namespace DEFAULT {
constexpr unsigned short int WIDTH = 64;
constexpr unsigned short int HEIGHT = 64;
constexpr float DENSITY = 0.45;
constexpr unsigned short int BIRTH_LIMIT = 4;
constexpr unsigned short int DEATH_LIMIT = 3;
} // namespace DEFAULT
class CaveFactory {
public:
CaveFactory(unsigned short int width = DEFAULT::WIDTH,
unsigned short int height = DEFAULT::HEIGHT,
float density = DEFAULT::DENSITY);
// makes a cave with the desired number of iterations and parameters
static cave_t MakeCave(unsigned short int width = DEFAULT::WIDTH,
unsigned short int height = DEFAULT::HEIGHT,
float density = DEFAULT::DENSITY,
int iterations = 3,
unsigned short int bl = DEFAULT::BIRTH_LIMIT,
unsigned short int dl = DEFAULT::DEATH_LIMIT);
// implemented in case of generalization of cave(more than two blocks)
bool isSolid(int i, int j);
cave_t getCave();
void Print();
void Iterate( unsigned short int bl = DEFAULT::BIRTH_LIMIT,
unsigned short int dl = DEFAULT::DEATH_LIMIT );
private:
cave_t cave_;
int NumberOfNeighbours(int i, int j);
void Initialize(float density = DEFAULT::DENSITY);
};
} // namespace cavegenerator
#endif // CAVEFACTORY_H_
cavefactory.cc
#include "cavefactory.h"
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
namespace cavegenerator {
CaveFactory::CaveFactory(unsigned short int width, unsigned short int height, float density) {
cave_.resize(width);
for (auto &i : cave_) {
i.resize(height);
}
Initialize(density);
}
bool CaveFactory::isSolid(int i, int j) {
return (cave_[i][j] == 1);
}
int CaveFactory::NumberOfNeighbours(int x, int y) {
int num = 0;
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
if ( i == 0 && j == 0 ) continue; // we don't want to count ourselve
// if out of bounds, add a solid neighbour
if ( x + i >= (int)cave_.size() || x + i < 0 || y + j >= (int)cave_[i].size() || y + j < 0) {
++num;
} else if (isSolid(x+i, y+j)) {
++num;
}
}
}
return num;
}
cave_t CaveFactory::getCave() {
return cave_;
}
void CaveFactory::Print() {
for (auto &i : cave_) {
for (auto &j : i) {
std::cout << ((j==1) ? "x" : " ");
}
std::cout << "n";
}
return;
}
cave_t CaveFactory::MakeCave(unsigned short int width,
unsigned short int height,
float density,
int iterations,
unsigned short int bl,
unsigned short int dl)
{
CaveFactory cave(width, height, density);
for (int i = 0; i < iterations; i++) {
cave.Iterate(bl, dl);
}
return cave.getCave();
}
// Initlialize the cave with the specified density
void CaveFactory::Initialize(float density) {
std::mt19937 rd(4);
std::uniform_real_distribution<float> roll(0, 1);
for (auto &i : cave_) {
for (auto &j : i) {
if (roll(rd) < density) {
j = 1;
} else {
j = 0;
}
}
}
}
// for each cell in the original cave, if the cell is solid:
// if the number of solid neighbours is under the death limit, we kill the block
// if the cell is air, if the number of solid blocks is above the birth limit we place a block
void CaveFactory::Iterate(unsigned short int bl, unsigned short int dl) {
cave_t new_cave = cave_;
for (int i = 0; i < (int)cave_.size(); i++) {
for (int j = 0; j < (int)cave_[0].size(); j++) {
int number_of_neighbours = NumberOfNeighbours(i, j);
if (isSolid(i, j) && number_of_neighbours < dl) {
new_cave[i][j] = 0;
} else if (!isSolid(i,j) && number_of_neighbours > bl) {
new_cave[i][j] = 1;
}
}
}
std::copy(new_cave.begin(), new_cave.end(), cave_.begin());
}
} // namespace cavegenerator
main.cc
#include <iostream>
#include <vector>
#include <random>
#include <ctime>
#include <windows.h>
#include "cavefactory.h"
int main() {
cavegenerator::CaveFactory caveEE;
caveEE.Print();
for(int i = 0; i < 15; i++) {
caveEE.Iterate();
Sleep(600);
system("cls");
caveEE.Print();
}
return 0;
}
我知道windows.h是一个坏习惯,我只是用它来调试。
我希望有人能让我理解,也许这只是我不知道的正常行为?
非常感谢。
NumberOfNeighbours
中的 (int)cave_[i].size()
是不正确的,应为 (int)cave_[x+i].size()
(或 (int)cave_[0].size()
,因为所有行和列都是相等的大小)。当我等于-1时,您有一个范围的向量访问和未定义的行为。
相关文章:
- 不确定要在我的main中放入什么才能使我的代码正常工作
- C++程序不会从 Windows 控制台运行
- 程序不会执行函数 c++
- 为什么我的程序不能显示斐波那契级数?
- 为什么使用数组元素查找最大数字的程序不起作用?
- 程序不向函数返回值
- 不确定如何装饰我的C++库代码以在 C 中使用
- 英特尔 TBB 程序不会终止,可能会误用参考计数器
- C++ 程序不会因为内存而终止
- C++功能泄漏内存,我是C++新手,不确定如何解决
- "错误 C0000:语法错误,令牌"<EOF>"处出现意外$end,并且不确定
- 为什么一个简单的程序不能立即启动
- 代码在 CodeSignal 中工作不正确。不确定这是否是我的代码缺陷
- 为什么以下代码是不确定的?
- 我收到阻止我运行程序的警告,但不确定如何解决
- 不确定的行为通过确定主义程序
- 首先C++程序无法编译 - 不确定将第三方库放在哪里
- C++ 不确定如何让我的程序输出空间的位置
- C++程序-不确定是否,我提供了正确的解决方案
- 不确定为什么我的程序无法显示