代码之家  ›  专栏  ›  技术社区  ›  mpen

用Max(F(X))选择X

  •  2
  • mpen  · 技术社区  · 15 年前

    我想为跳棋游戏写些人工智能。我想选择棋盘得分最高的那一步。

    需要这样的东西:

    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;
        }
    }
    
    4 回复  |  直到 15 年前
        1
  •  3
  •   Dan Tao    15 年前

    你不是基本上已经搞清楚了吗?如果编写自己的扩展方法,则可以以典型的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)));
    
        2
  •  2
  •   Matthew Flaschen    15 年前
    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

        3
  •  1
  •   Grozz    15 年前
        float max = validMoves.Max(m => BoardScore(opp, board.Clone().ApplyMove(m)));
        var bestMove = validMoves
              .Where(m => BoardScore(opp, board.Clone().ApplyMove(m)) == max)
              .First();
    
        4
  •  0
  •   Nathan Ernst    15 年前

    你会想看看 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;