programa juegos juego cartas c# algorithm recursion playing-cards

c# - programa - juegos de cartas python



La mejor opción de cartas en el juego de cartas en C# (3)

Construya la solución desde los casos más simples utilizando recursión.

Deje D ser el conjunto de cartas. Deje A ser el total de sus cartas y B sea ​​el total de las cartas de su oponente. Establezca S = AB como el valor del juego. Usted gana si S>0 , pierde si S<0 y empate si S==0 .

Lo más fácil es hacer dos movimientos a la vez, tu movimiento seguido del movimiento determinado del oponente. Hay dos casos base a considerar:

  • Si la length(D) == 0 , devuelve S El juego ha terminado.

  • Si la length(D) == 1 , devuelve S + D[0] . Tú eliges la carta restante, y el juego termina.

Para el caso recursivo, cuando la length(D) > 1 evalúa las dos posibilidades

  • Deje L ser el resultado del juego si elige la carta izquierda seguida por el oponente haciendo su movimiento determinista, es decir,

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

  • Deje que R sea ​​el resultado del juego si elige la carta correcta seguida por el oponente haciendo su movimiento determinista, es decir,

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

Elija la jugada correspondiente al número más grande, es decir, tome D[0] si L>=R , de lo contrario tome D[N-1] . Aquí N = length(D) .

El problema consiste en elegir la mejor opción en cada momento del juego siguiendo estas reglas:

  • Solo puedes elegir la carta más a la izquierda o más a la derecha.

  • Tu oponente SIEMPRE elegirá primero, y SIEMPRE elegirá la carta más alta de la carta situada más a la izquierda o más a la derecha. Si es un empate, elegirá el más a la derecha. Tenga en cuenta que esta no es siempre la mejor opción.

A veces es imposible ganar, pero de todos modos debes mostrar el valor más alto que puedas agregar al jugar contra este oponente (o estrategia, digamos).

Ejemplo:

Cards: 1 2 4 2 8 4 3 Opponent: 3 4 2 2 = 11 Me: 1 8 4 = 13

Aquí elegí 1 en lugar de 4 en el segundo turno, para poder elegir el 8 más tarde. Es por eso que elegir la carta más alta no siempre es lo mejor.

He intentado implementar esta solución utilizando la recursión, pero no estoy seguro de que sea la mejor opción. ¿Alguna idea sobre cómo diseñar este algoritmo?

[EDITAR] Gracias a @PengOne por su generosa ayuda. Este es el código que trato de implementar, pero desafortunadamente me está dando errores. ¿Qué debería arreglar? Estoy editando esto a medida que avance.

static int cardGameValue(List<int> D, int myScore, int opponentScore) { if (D.Count == 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.Take(D.Count - 2)), myScore + D[D.Count - 1], opponentScore); if (left >= right) { return left; } else { return right; } } }


Deberías mirar el algoritmo Min-Max , posiblemente con poda Alpha-Beta

Min-Max es la idea de que tu oponente siempre elegirá la mejor opción para sí mismo, por lo tanto puedes ejecutar cada posible escenario para descubrir la mejor opción que resulte en derrotar a tu oponente. "es decir, dado que hago movimiento x, mi oponente tomará movimiento y, luego tomaré ..." etc., todo el camino hasta el final del juego. Por lo tanto, puedes determinar quién ganará.

La poda Alpha-Beta es similar a los posibles escenarios, pero determina si una lista de escenarios posibles producirá un resultado ganador. Si sabes que si haces "mover x", siempre perderás sin importar qué, no necesitas pasar más tiempo mirando "mover x luego moverte y". Puedes "eliminar" toda la rama de opciones de "mover x" porque sabes que nunca será útil.


Este es el código que realmente funcionó al final. Gracias a todos por vuestro apoyo.

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; } } }