首先,我必须指定我在Unity5.3中工作,而新的MonoDevelop不允许我进行调试。团结只会崩溃:
因此,我有一个“目标”清单,我需要根据三个标准进行排序:
以下是我的代码:
public class Goal {
public int ID;
public int Level;
public bool Active;
}
...
List<Goal> goals;
goals.Sort((a, b) => {
// first chooses the Active ones (if any)
var sort = b.Active.CompareTo(a.Active);
if (sort == 0) {
// then sort by level
sort = (a.Level).CompareTo(b.Level);
// if same level, randomize. Returns -1, 0 or 1
return sort == 0 ? UnityEngine.Random.Range(-1, 2) : sort;
} else {
return sort;
}
});当我运行这段代码时,有时我会得到一个或多个非活动目标之后的活动目标,但我不明白为什么。
发布于 2016-01-29 22:36:42
要正确工作,排序算法不应依赖于变异状态。解释为什么在比较值时使用随机生成器不是一个好主意就在这里。
这个问题可以通过两种方式来解决:
选项1:预先计算随机数
var tmp = goals.Select( g=> new {goal = g, weight = rnd.NextDouble()})
.OrderByDescending(t=>t.goal.Active) // Active first
.ThenBy(t=>t.goal.Level)
.ThenBy(t=>t.weight)
.Select(t=>t.goal)
.ToList();
goals.Clear();
goals.AddRange(tmp);选项2:排序然后洗牌
Random rnd = new Random();
Comparison<Goal> comparison = (a, b) => {
// first chooses the Active ones (if any)
var sort = b.Active.CompareTo(a.Active);
if (sort == 0) {
// then sort by level
return sort = (a.Level).CompareTo(b.Level);
} else
{
return sort;
}
};
int startIndex = 0;
int endIndex = 0;
goals.Sort(comparison);
while (startIndex < goals.Count)
{
for (endIndex = startIndex + 1; endIndex < goals.Count; ++endIndex)
{
if (comparison(goals[startIndex], goals[endIndex]) != 0)
{
//End of tie
break;
}
}
if (endIndex - startIndex > 1)
{
// Shuffle goals of the same level
ShuffleRange(goals, startIndex, endIndex - startIndex, rnd);
}
startIndex = endIndex;
}
static void ShuffleRange<T>(List<T> list, int startIndex, int count, Random rnd)
{
int n = startIndex + count;
while (n > startIndex + 1)
{
int k = rnd.Next(startIndex, n--);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
} 洗牌算法是从这里中借用的
发布于 2016-01-29 22:41:04
试试这个羔羊:
(a, b) => ((b.Active ? 1000 : 0) + b.Level) - ((a.Active ? 1000 : 0) + a.Level)Active比1的级别差更重要1000倍,这对1000个级别是有效的。当Active是相同的,该级别就变得相关。最后,如果它仍然是相同的,它将以一种确定性的,但无关的方式,这是相同的随机。
没有必要使用真正的随机数。在一次运行中,顺序总是相同的,但在不同的运行过程中可能会有所不同。如果确实需要随机排序,可以使用以下命令:
(a, b) =>
((b.Active ? 10000 : 0) + b.Level * 10) -
((a.Active ? 10000 : 0) + a.Level * 10) + UnityEngine.Random.Range(-1, 2)发布于 2016-01-30 02:23:56
我不能重复你的问题,得到“一个或多个积极的目标后,不积极的目标”。听起来您的Goal实例在排序之后发生了变异。我建议在可能的情况下尝试制作只读对象。
我的另一个建议是简化对代码的排序,使其更清晰、更易于推理--尽管在这种情况下,这可能没有直接帮助。
只需这样做:
var sorted =
(
from g in goals
orderby g.Active descending, g.Level, UnityEngine.Random.Range(-1, 2)
select g
.ToList();...or或者是类似于这样的:
var sorted =
goals
.OrderByDescending(g => g.Active)
.ThenBy(g => g.Level)
.ThenBy(g => rnd.Next())
.ToList();LINQ排序在随机源中工作得很好。我对它做了分布分析,它和费舍-耶茨一样有效。
https://stackoverflow.com/questions/35092917
复制相似问题