[英]Select X with Max(F(X))
I'm trying to write some AI for a game of checkers. 我正在尝试为跳棋游戏编写一些AI。 I want to select the move with the highest board score.
我想选择棋盘得分最高的棋步。
Need something like this: 需要这样的东西:
var bestMove = from m in validMoves
where BoardScore(opp, board.Clone().ApplyMove(m)) is max
select m
Except I can't figure out the "is max" part. 除了我无法弄清楚“最大”部分。 Would prefer it returns a single item rather than an enumerable too.
希望它返回单个项目而不是可枚举的项目。
Basically, the equivalent of this: 基本上,这等效于:
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;
}
}
Don't you basically already have this figured out? 您基本上不是已经知道了吗? If you write your own extension method you can implement this functionality in typical LINQ fashion:
如果编写自己的扩展方法,则可以以典型的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);
}
This way you could just do: 这样,您可以执行以下操作:
var bestMove = validMoves
.MaxFrom(m => BoardScore(opp, board.Clone().ApplyMove(m)));
var scores = from m in validMoves
select BoardScore(opp, board.Clone().ApplyMove(m));
var bestMove = scores.Max();
EDIT: 编辑:
I should have read more closely. 我应该更仔细地阅读。 You can do:
你可以做:
var descendingMoves = validMoves.OrderByDescending(m=>BoardScore(opp, board.Clone().ApplyMove(m)));
var bestMove = descendingMoves.First();
But this is O(n log n)
. 但这是
O(n log n)
。 I found a blog post with discussion on this issue. 我找到了一篇有关此问题的讨论的博客文章 。 It proposes a
Max
extension function that returns the maximum original value, rather than the transformed one. 它提出了一个
Max
扩展函数,该函数返回最大原始值,而不是转换后的原始值。 Unfortunately, I don't know of a way to do this in LINQ. 不幸的是,我不知道如何在LINQ中做到这一点。
float max = validMoves.Max(m => BoardScore(opp, board.Clone().ApplyMove(m)));
var bestMove = validMoves
.Where(m => BoardScore(opp, board.Clone().ApplyMove(m)) == max)
.First();
You're going to want to look at Enumerable.Max(TSource) Method (IEnumerable(TSource), Func(TSource, Single))
. 您将要查看
Enumerable.Max(TSource) Method (IEnumerable(TSource), Func(TSource, Single))
。 ie: 即:
var bestMove = validMoves.Max((m)=>BoardScore(opp, board.Clone().ApplyMove(m)));
If the scores are expensive to compute, you might compute all scores up-front, pairing them with their corresponding move, but I doubt this will be necessary. 如果分数的计算成本很高,则可以预先计算所有分数,并将它们与相应的动作配对,但是我怀疑这是否必要。 Example:
例:
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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.