首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 二維數組生成 10 個位置聚集的隨機數:聚類采樣、高斯分布、泊松盤算法對比

     編輯:程式設計綜合問答

需求翻譯

在 `M x N` 二維網格中生成 10 個隨機坐標,**使其空間分布「聚集」而非均勻分散** (即點之間距離較小,形成簇)。

四種算法對比

算法原理聚集程度控制代碼複雜度適用場景
高斯混合模型 (GMM) 采樣預設 K 個簇中心,每點從最近簇的高斯分布采樣協方差矩陣 `σ²` 控制擴散半徑低自然現象模擬、遊戲資源點
泊松盤采樣 (Poisson Disk) 反向標準算法生成「最小距離」均勻分布,**取反邏輯**:強制最小距離極小半徑 `r` → 極小值中需嚴格控制最小間距
聚類優先采樣先隨機選 1-3 個種子點,後續點在現有點半徑 `R` 內均勻生成種子數、半徑 `R`**極低**快速原型、程序化地圖
Perlin/Simplex Noise 閾值生成噪聲圖,高值區域作為候選區,在候選區均勻采樣噪聲頻率、閾值中地形生成、有機形狀簇

推薦:聚類優先采樣 (最簡單、可控、O(n))

#include 
#include 
#include 

struct Point { int x, y; };

std::vector generateClustered(int width, int height, int count, int clusterRadius) {
    std::vector points;
    std::mt19937 rng(std::random_device{}());
    std::uniform_int_distribution distX(0, width - 1);
    std::uniform_int_distribution distY(0, height - 1);
    std::uniform_int_distribution distR(-clusterRadius, clusterRadius);

    // 1. 先產生 1-3 個種子點
    int seeds = std::uniform_int_distribution(1, 3)(rng);
    for (int i = 0; i < seeds; ++i) {
        points.push_back({ distX(rng), distY(rng) });
    }

    // 2. 其餘點在現有點鄰域內生成
    while ((int)points.size() < count) {
        const Point& base = points[std::uniform_int_distribution(0, points.size() - 1)(rng)];
        int nx = base.x + distR(rng);
        int ny = base.y + distR(rng);
        // 邊界裁剪
        nx = std::clamp(nx, 0, width - 1);
        ny = std::clamp(ny, 0, height - 1);
        points.push_back({ nx, ny });
    }
    return points;
}

// 使用示例
auto pts = generateClustered(100, 100, 10, 5); // 100x100 網格, 10點, 聚類半徑5
for (auto& p : pts) std::cout << p.x << "," << p.y << "\n";

進階:高斯混合模型 (更自然的橢圓形簇)

#include  // 需 Eigen 庫

struct Cluster { Eigen::Vector2d mean; Eigen::Matrix2d cov; };

std::vector generateGMM(int width, int height, int count, const std::vector& clusters) {
    std::vector points;
    std::mt19937 rng(std::random_device{}());
    std::uniform_real_distribution<> distCluster(0.0, 1.0);
    std::normal_distribution<> norm(0.0, 1.0);

    // 累積權重選簇
    std::vector weights;
    for (auto& c : clusters) weights.push_back(1.0); // 均等權重
    std::discrete_distribution<> clusterDist(weights.begin(), weights.end());

    for (int i = 0; i < count; ++i) {
        const auto& cl = clusters[clusterDist(rng)];
        // Box-Muller 采樣二維高斯
        double u1 = norm(rng), u2 = norm(rng);
        Eigen::Vector2d z(u1, u2);
        Eigen::Vector2d sample = cl.mean + cl.cov.llt().matrixL() * z; // Cholesky 分解
        int x = std::clamp(int(std::round(sample.x())), 0, width - 1);
        int y = std::clamp(int(std::round(sample.y())), 0, height - 1);
        points.push_back({ x, y });
    }
    return points;
}

// 定義兩個簇:左上、右下
std::vector clusters = {
    { {20, 20}, (Eigen::Matrix2d() << 25, 0, 0, 25).finished() },  // 圓形簇 σ=5
    { {80, 80}, (Eigen::Matrix2d() << 16, 8, 8, 16).finished() }   // 橢圓簇
};
auto pts = generateGMM(100, 100, 10, clusters);

二維數組映射 (如需標記網格)

int grid[100][100] = {0};
for (auto& p : pts) grid[p.y][p.x] = 1; // 注意行列順序
// 現在 grid 中 1 表示有點,可直接用於渲染/邏輯判斷

總結

**「聚類優先采樣」5 行核心代碼即可產生位置聚集的隨機點**,參數 `clusterRadius` 直觀控制緊湊度。需更自然形狀用 **GMM**,需嚴格最小間距用 **泊松盤反向**。二維數組僅作為最終標記容器,生成邏輯與數組結構解耦。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved