如何使用菱形方块算法为程序生成的地图生成密钥?
How to generate a key for a procedurally generated map using diamond-square algorithm?
我不知道关键字是否适合这个词,但我实现了 Diamond-Square 算法的一个版本,我想知道是否有任何方法 "save" 当前输出并重新创建它使用一个简单的(6 到 10 个字符)键。到目前为止我唯一的方法是将它保存为单个 number/string 包含每个单元格的输出值但是对于 17X17 网格我至少有一个 289 个字符长的序列(假设输出是每个单元格的单个数字细胞)。
由于算法是随机的,我想不出更好的方法。如果这是不可能的,你能告诉我更好的算法来使用。谢谢:)
PS:我正在使用 unity 3D 和 C#
以下 class 来自程序洞穴生成的统一教程,但我将其包含在内,因为它包含您需要的核心元素。它使用种子生成地图,相同的种子将重新生成相同的地图....您可以在生成过程中使用种子,即使它是随机的,然后您始终可以将该种子重新用于 return到那张地图。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class MapGenerator : MonoBehaviour {
public int width;
public int height;
public string seed;
public bool useRandomSeed;
[Range(0,100)]
public int randomFillPercent;
int[,] map;
private void Start()
{
GenerateMap();
}
void GenerateMap()
{
map = new int[width, height];
RandomFillMap();
for (int i = 0; i < 5; i++)
{
SmoothMap();
}
}
void RandomFillMap()
{
if (useRandomSeed)
{
seed = Time.time.ToString();
}
System.Random prng = new System.Random(seed.GetHashCode());
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
{
map[x, y] = 1;
}
else
{
map[x, y] = (prng.Next(0, 100) < randomFillPercent) ? 1 : 0;
}
}
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
GenerateMap();
}
}
void SmoothMap()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int neighborWallTiles = GetSurroundingWallCount(x, y);
if (neighborWallTiles > 4)
{
map[x, y] = 1;
}
else if (neighborWallTiles<4)
{
map[x, y] = 0;
}
}
}
}
int GetSurroundingWallCount(int gridx, int gridy)
{
int wallcount = 0;
for(int neighborx=gridx-1; neighborx<=gridx + 1; neighborx++)
{
for (int neighbory = gridy - 1; neighbory <= gridy + 1; neighbory++)
{
if (neighborx >= 0 && neighborx < width && neighbory >= 0 && neighbory < height)
{
if (neighborx != gridx || neighbory != gridy)
{
wallcount += map[neighborx, neighbory];
}
}
else
{
wallcount++;
}
}
}
return wallcount;
}
void OnDrawGizmos()
{
if (map != null)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Gizmos.color = (map[x, y] == 1) ? Color.black : Color.white;
Vector3 pos = new Vector3(-width / 2 + x + .5f, 0, -height / 2 + y + .5f);
Gizmos.DrawCube(pos, Vector3.one);
}
}
}
}
}
我确实喜欢评论说我使用 Random.InitState 提供统一并且一切正常。再次感谢!
UnityEngine.Random.InitState(seed);
我可以随心所欲地控制种子,它为我提供相同种子的相同地图。
我不知道关键字是否适合这个词,但我实现了 Diamond-Square 算法的一个版本,我想知道是否有任何方法 "save" 当前输出并重新创建它使用一个简单的(6 到 10 个字符)键。到目前为止我唯一的方法是将它保存为单个 number/string 包含每个单元格的输出值但是对于 17X17 网格我至少有一个 289 个字符长的序列(假设输出是每个单元格的单个数字细胞)。
由于算法是随机的,我想不出更好的方法。如果这是不可能的,你能告诉我更好的算法来使用。谢谢:)
PS:我正在使用 unity 3D 和 C#
以下 class 来自程序洞穴生成的统一教程,但我将其包含在内,因为它包含您需要的核心元素。它使用种子生成地图,相同的种子将重新生成相同的地图....您可以在生成过程中使用种子,即使它是随机的,然后您始终可以将该种子重新用于 return到那张地图。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class MapGenerator : MonoBehaviour {
public int width;
public int height;
public string seed;
public bool useRandomSeed;
[Range(0,100)]
public int randomFillPercent;
int[,] map;
private void Start()
{
GenerateMap();
}
void GenerateMap()
{
map = new int[width, height];
RandomFillMap();
for (int i = 0; i < 5; i++)
{
SmoothMap();
}
}
void RandomFillMap()
{
if (useRandomSeed)
{
seed = Time.time.ToString();
}
System.Random prng = new System.Random(seed.GetHashCode());
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
if (x == 0 || x == width - 1 || y == 0 || y == height - 1)
{
map[x, y] = 1;
}
else
{
map[x, y] = (prng.Next(0, 100) < randomFillPercent) ? 1 : 0;
}
}
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
GenerateMap();
}
}
void SmoothMap()
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
int neighborWallTiles = GetSurroundingWallCount(x, y);
if (neighborWallTiles > 4)
{
map[x, y] = 1;
}
else if (neighborWallTiles<4)
{
map[x, y] = 0;
}
}
}
}
int GetSurroundingWallCount(int gridx, int gridy)
{
int wallcount = 0;
for(int neighborx=gridx-1; neighborx<=gridx + 1; neighborx++)
{
for (int neighbory = gridy - 1; neighbory <= gridy + 1; neighbory++)
{
if (neighborx >= 0 && neighborx < width && neighbory >= 0 && neighbory < height)
{
if (neighborx != gridx || neighbory != gridy)
{
wallcount += map[neighborx, neighbory];
}
}
else
{
wallcount++;
}
}
}
return wallcount;
}
void OnDrawGizmos()
{
if (map != null)
{
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
Gizmos.color = (map[x, y] == 1) ? Color.black : Color.white;
Vector3 pos = new Vector3(-width / 2 + x + .5f, 0, -height / 2 + y + .5f);
Gizmos.DrawCube(pos, Vector3.one);
}
}
}
}
}
我确实喜欢评论说我使用 Random.InitState 提供统一并且一切正常。再次感谢!
UnityEngine.Random.InitState(seed);
我可以随心所欲地控制种子,它为我提供相同种子的相同地图。