我正在尝试为棋盘游戏编写一些AI。我想选择董事会得分最高的那一步。
需要这样的东西:
var bestMove = from m in validMoves
where BoardScore(opp, board.Clone().ApplyMove(m)) is max
select m
除了我无法弄清楚“是最大”部分。希望它返回单个项而不是可枚举项。
基本上,相当于:
Move bestMove = null;
float highestScore = float.MinValue;
foreach (var move in validMoves)
{
float score = BoardScore(opp, board.Clone().ApplyMove(move));
if (score > highestScore)
{
highestScore = score;
bestMove = move;
}
}
答案 0 :(得分:3)
难道你基本上没有这个问题吗?如果您编写自己的扩展方法,则可以采用典型的LINQ方式实现此功能:
public static T MaxFrom<T, TValue>(this IEnumerable<T> source, Func<T, TValue> selector, IComparer<TValue> comparer)
{
T itemWithMax = default(T);
TValue max = default(TValue);
using (var e = source.GetEnumerator())
{
if (e.MoveNext())
{
itemWithMax = e.Current;
max = selector(itemWithMax);
}
while (e.MoveNext())
{
T item = e.Current;
TValue value = selector(item);
if (comparer.Compare(value, max) > 0)
{
itemWithMax = item;
max = value;
}
}
}
return itemWithMax;
}
public static T MaxFrom<T, TValue>(this IEnumerable<T> source, Func<T, TValue> selector)
{
return source.MaxFrom(selector, Comparer<TValue>.Default);
}
这样你就可以做到:
var bestMove = validMoves
.MaxFrom(m => BoardScore(opp, board.Clone().ApplyMove(m)));
答案 1 :(得分:2)
var scores = from m in validMoves
select BoardScore(opp, board.Clone().ApplyMove(m));
var bestMove = scores.Max();
编辑:
我应该仔细阅读。你可以这样做:
var descendingMoves = validMoves.OrderByDescending(m=>BoardScore(opp, board.Clone().ApplyMove(m)));
var bestMove = descendingMoves.First();
但这是O(n log n)
。我找到了一个blog post来讨论这个问题。它提出了一个Max
扩展函数,它返回最大的原始值,而不是转换后的原始值。不幸的是,我不知道在LINQ中这样做的方法。
答案 2 :(得分:1)
float max = validMoves.Max(m => BoardScore(opp, board.Clone().ApplyMove(m)));
var bestMove = validMoves
.Where(m => BoardScore(opp, board.Clone().ApplyMove(m)) == max)
.First();
答案 3 :(得分:0)
你想看看Enumerable.Max(TSource) Method (IEnumerable(TSource), Func(TSource, Single))
。即:
var bestMove = validMoves.Max((m)=>BoardScore(opp, board.Clone().ApplyMove(m)));
如果计算得分很高,你可以预先计算所有分数,将它们与相应的动作配对,但我怀疑这是必要的。例如:
var scores = from m in validMoves
select new {Move=m, Score=BoardScore(opp, board.Clone().ApplyMove(m))};
var bestMove = scores.Max(s=>s.Score).Move;