Best card choice in card game in C#

前端 未结 3 1527
遥遥无期
遥遥无期 2021-01-19 16:47

The problem consists in choosing the best option at every moment of the game following these rules:

  • You can only pick the leftmost or the rightmost card.

相关标签:
3条回答
  • 2021-01-19 16:48

    You should look at the Min-Max Algorithm, possibly with Alpha-Beta pruning

    Min-Max is the idea that your opponent will always choose the best choice for themselves, thus you can run each possible scenario to discover the best choice that will result in you beating your opponent. "ie, given I make move x, my opponent will take move y, then I'll take..." etc, all the way to the end of the game. Thus, you can determine who will win.

    Alpha-Beta pruning is similar that it looks at possible scenarios, but it determines if a list of possible scenarios will ever produce a winning outcome. If you know that if you make "move x" then you will always loose no matter what, you don't need to spend more time looking at "move x then move y". You can "prune" off the whole branch of choices from "move x" because you know it will never be helpful.

    0 讨论(0)
  • 2021-01-19 17:06

    This is the code that actually worked in the end. Thanks to everyone for your support.

        static int cardGameValue(List<int> D, int myScore, int opponentScore)
        {
            if (D.Count == 0) return myScore;
            else if (D.Count == 1)
            {
                opponentScore += D[0];
                return myScore;
            }
            else
            {
                if (D[0] <= D[D.Count - 1])
                {
                    opponentScore += D[D.Count - 1];
                    D.RemoveAt(D.Count - 1);
                }
                else
                {
                    opponentScore += D[0];
                    D.RemoveAt(0);
                }
    
                int left = cardGameValue(new List<int>(D.GetRange(1, D.Count - 1)), myScore + D[0], opponentScore);
    
                int right = cardGameValue(new List<int>(D.GetRange(0, D.Count - 1)), myScore + D[D.Count - 1], opponentScore);
    
                if (left >= right)
                {
                    return left;
                }
                else
                {
                    return right;
                }
            }
        }
    
    0 讨论(0)
  • 2021-01-19 17:08

    Build the solution out from the simplest cases using recursion.

    Let D be the array of cards. Let A be the total of your cards and B be the total of your opponent's cards. Set S = A-B to be the value of the game. You win if S>0, lose if S<0 and tie if S==0.

    The easiest is to make two moves at once, your move followed by the opponent's determined move. There are two base cases to consider:

    • If length(D) == 0, return S. The game has ended.

    • If length(D) == 1, return S + D[0]. You choose the remaining card, and the game ends.

    For the recursive case, when length(D) > 1, evaluate the two possibilities

    • Let L be the result of the game if you choose the left card followed by the opponent doing his deterministic move, i.e.

      L = D[0] - max(D[1],D[N-1]) + cardGameValue(newD)

    • Let R be the result of the game if you choose the right card followed by the opponent doing his deterministic move, i.e.

      R = D[N-1] - max(D[0],D[N-2]) + cardGameValue(newD)

    Choose the play corresponding to the larger number, i.e. take D[0] if L>=R, otherwise take D[N-1]. Here N = length(D).

    0 讨论(0)
提交回复
热议问题