【发布时间】:2017-03-29 03:28:19
【问题描述】:
在我用 Scala 制作的游戏地牢生成器中,我有一个递归函数,可以生成“树状”结构。它接受一个纯随机数生成器(RNG),并输出一个随机树和一个新的随机数生成器。
我的问题是因为它是递归的,并且每次我的函数分支出来时,我不想将同一个 RNG 传递给两个分支,所以我必须在我的外部函数中保留一个内部 var。
摘自我的代码:
def generate(parameters: RandomBSPTreeParameters)(rng: RNG): (BSPTree, RNG) = {
var varRng: RNG = rng
def inner(size: Size, verticalSplit: Boolean): BSPTree = {
def verticalBranch = {
val leeway = size.height - parameters.minLeafEdgeLength.value * 2
val (topHeightOffset, newRng) = RNG.nextPositiveInt(leeway)(varRng)
varRng = newRng
val topHeight = parameters.minLeafEdgeLength.value + topHeightOffset
VerticalBranch(
inner(Size(size.width, topHeight), verticalSplit = false),
inner(Size(size.width, size.height - topHeight), verticalSplit = false)
)
}
def horizontalBranch = {
val leeway = size.width - parameters.minLeafEdgeLength.value * 2
val (topWidthOffset, newRng) = RNG.nextPositiveInt(leeway)(varRng)
varRng = newRng
val leftWidth = parameters.minLeafEdgeLength.value + topWidthOffset
HorizontalBranch(
inner(Size(leftWidth, size.height), verticalSplit = true),
inner(Size(size.width - leftWidth, size.height), verticalSplit = true)
)
}
def randomOrientationBranch = {
val (splitVertically, newRng) = RNG.nextBoolean(varRng)
varRng = newRng
if (splitVertically)
verticalBranch
else
horizontalBranch
}
if(size.surface > parameters.minLeafSurface)
size.shape match {
case Square if size.width > parameters.minLeafEdgeLength.value * 2 => randomOrientationBranch
case SkewedHorizontally if size.width > parameters.minLeafEdgeLength.value * 2 => horizontalBranch
case SkewedVertically if size.height > parameters.minLeafEdgeLength.value * 2 => verticalBranch
}
else Leaf(size)
}
val (firstSplitIsVertical, newRng) = RNG.nextBoolean(varRng)
varRng = newRng
val tree = inner(parameters.size, firstSplitIsVertical)
(tree, varRng)
}
有人可以指导我正确的方向,以消除在此函数中保留 var varRng: RNG 的需要,并使其无状态。
【问题讨论】:
标签: scala functional-programming