Vous êtes sur la page 1sur 15

Programacin del Juego For Sale Utilizando Heurstica

David R. Bengoa Tern Departamento de Ingeniera Elctrica y de Computadoras Universidad de Puerto Rico, Recinto Mayagez Mayagez, Puerto Rico 00681-5000 david.bengoa@upr.edu Resumen
El presente documento da a conocer el desarrollo computarizado o programacin de un conocido juego de cartas llamado For Sale [1]. La creacin de este programa fue realizado con el lenguaje de programacin Java, y se utilizaron tcnicas de algoritmos inteligentes basados en diferentes estrategias de juego, es decir, algoritmos heursticos. Adems, el juego no solamente se bas en realizar el desarrollo de estos algoritmos, sino tambin en la construccin de una interfaz grfica. La utilizacin de los algoritmos heursticos permitieron que el juego se pueda realizar entre una o varias personas contra una o ms computadoras, o solamente ver jugar a las computadoras versus otras computadoras. Finalmente se logr obtener un juego que permite variar el nivel de la heurstica, obteniendo como consecuencia una variacin en el nivel de juego de la computadora. Y de acuerdo a las pruebas realizadas, se obtuvieron distintos resultados al variar el nmero de jugadores (humanos y CPU). Otros conceptos que llevaron a la decisin de utilizar heursticas, en vez de otros algoritmos ms complejos. Es el hecho de que (1) es muy comn utilizar heurstica en juegos para simular un jugador, es decir, la utilizacin de una computadora. La heurstica (2) es un conjunto de reglas que los evaluadores pueden utilizar con la finalidad de encontrar defectos en el juego. Los algoritmos heursticos (3) se caracterizan por ser rpidos, econmicos y fciles de crear. Y existen 10 caractersticas importantes sobre la heurstica (4) mencionadas por el Phd. Jacob Nielsen [2], siendo las ms relevantes para el juego: previene errores, flexibilidad y eficiencia en el uso, prevalece la consistencia y estndares, y permite una visibilidad general del estado del sistema. Una vez decidida la utilizacin de heurstica en los algoritmos, se empez con la creacin de la interfaz grfica, basndonos en que inicialmente el juego est concluido para que sea jugado solamente por agentes humanos. Al lograr esta primera etapa, se prosigui agregando los algoritmos heursticos, basndonos en las reglas y estrategias conocidas. Finalmente, se logr de esta manera, poder jugar entre agentes mezclados, sean computadoras y/o personas. La estructura de ste documento es como sigue. Seccin 2 se desarrolla todo lo que es la interfaz grfica. Seccin 3 se despliega al detalle las caractersticas e informacin importante de los algoritmos utilizados. Seccin 4 se da a conocer las pruebas y resultados que se realizaron al juego. Seccin 5 se propone los posibles trabajos a futuro que se pueden realizar. Finalmente en la Seccin 6 se resumen las conclusiones del proyecto.

1. Introduccin
Luego de un anlisis exhaustivo del juego, es decir, al identificar el rendimiento medible, el tipo de escenario, agentes, actuadores y sensores, se lleg a la conclusin de utilizar algoritmos heursticos para simular los agentes automatizados, es decir, los participantes que son manejados por la computadora (CPU). Esta decisin tambin se debe a la aleatoriedad que se presenta en cada juego y a las posibles estrategias que se pueden utilizar para jugar ptimamente, sin la necesidad de incurrir en la utilizacin de algoritmos muchos ms complejos.

2. Desarrollo Grfico del Juego


Como parte del objetivo del proyecto, est la construccin de las interfaces grficas del juego. Luego de un anlisis de las reglas de juego, se encontraron las siguientes caractersticas bsicas del mismo: Nmero de jugadores posibles: 3 6 Nmero de propiedades: 30, numeradas del 1 al 30, en donde cada nmero es el valor de la propiedad. Nmero de cheques: 30, numeradas 0, 2 mil, 3 mil, hasta 15 mil. Encontrndose 2 cheques por cada cantidad. Reparticin de dinero a cada jugador, entre 14 mil y 18 mil, dependiendo de la cantidad de jugadores que participen. Dos fases. Fase inicial: rondas de propiedades. Fase final: rondas de cheques.

de ronda. Todo esto se puede visualizar en la Figura 2. La informacin que se puede visualizar debajo de las propiedades, se ha agregado con fines de conocer los valores que cada CPU est obteniendo, esto es para poder ir midiendo el nivel de eficiencia en los algoritmos heursticos, lo mismo ocurre en la Figura 4, en donde tambin se visualizan los valores jugados en cada ronda.

En base a estas caractersticas es que se construyeron las interfaces grficas. En la Figura 1, se puede visualizar la interfaz inicial, en donde el usuario puede seleccionar la cantidad de jugadores que van a participar, adems de tener la facilidad de poder colocarle el nombre del participante, y seleccionar si es que el participante ser una persona o la computadora (CPU).

Figura 2. Interfaz de la primera fase Igualmente, como parte de esta fase en la Figura 3 se observa la informacin que maneja cada jugador, es decir, el dinero que le resta, el dinero mnimo que requiere para poder seguir apostando, las opciones de Bid y Pass, y las propiedades ya ganadas.

Figura 3. Interfaz de cada jugador para la primera fase En la fase final, que se puede visualizar grficamente en la Figura 4, se observan los cheques que se estn jugando, y las propiedades que cada jugador o CPU est lanzando (eligiendo), boca abajo, y as sucesivamente va variando los cheques en cada ronda, hasta que se acaben de vender todas las propiedades.

Figura 1. Interfaz de seleccin de jugadores De acuerdo a las reglas de la fase inicial, los jugadores pueden visualizar la cantidad de dinero que el resto de contrincantes estn apostando, las propiedades que estn en la mesa, y el nmero

Figura 6. Interfaz del resultado del juego

3. Algoritmos
Figura 4. Interfaz de la segunda fase En la Figura 5, se visualiza la interfaz de cada jugador para esta fase final, es decir, cada participante estar visualizando las propiedades que aun mantiene, y los cheques que va obteniendo por cada propiedad. Adems de conocer el total del dinero que le qued de la primera fase ms el dinero ganado por las propiedades. Para el presente proyecto se utilizaron algoritmos heursticos, es decir, algoritmos basados en las reglas y estrategias investigadas [3] y [4]. Entre sus caractersticas ms importantes tenemos: Son parametrizables, por lo tanto permite medir el nivel de dificultad del adversario que es manejado por la computadora (CPU). Se maneja distintos algoritmos para cada fase, ya que la forma de juego en cada fase es distinta. Es importante mencionar que las decisiones son tomadas en base a la informacin que se obtiene en cada ronda. Dicha informacin, es actualizada conforme van jugando los contrincantes, y en base a las cartas que se juegan en la mesa (propiedades o cheques). La informacin manejada por los algoritmos, es informacin que es posible de observar en el juego en fsico (slo jugadores o agentes humanos), esto quiere decir que los algoritmos no estn haciendo trampa al obtener informacin privada de cada contrincante, tan solo que al mantener una memoria esttica de los nmeros en el juego, es que le permite tomar decisiones certeras. Por ejemplo: en la fase 2 cuando los contrincantes colocan sus propiedades en la mesa boca abajo, los algoritmos no requieren saber que propiedades se estn jugando, de lo contrario, slo saca conclusiones en base a las propiedades que tiene cada contrincante, y a los cheques que estn en mesa.

Figura 5. Interfaz de cada jugador para la segunda fase Finalmente en la Figura 6, se visualiza el resultado del juego, ordenado de mayor a menor en base al total de dinero obtenido, siendo el primero el ganador.

Respecto a la informacin que se obtiene en cada turno del jugador, tenemos para la fase 1 lo siguiente: Si las propiedades en juego son mayor o menor que un parmetro, o si estn en ambos rangos. La finalidad de esta informacin es para poder segmentar las cartas y dependiendo del rango es que se optar por apostar ms o menos. Si el juego se encuentra en las primeras o ltimas rondas. Esto igualmente ayuda a regular la cantidad que se va a apostar, dado que no es recomendable apostar una gran cantidad en las primeras rondas, ya que la tendencia es que los jugadores apuesten fuertemente al inicio y al final se queden con poco dinero para poder apostar, siendo ah el momento indicado de apostar un poco ms. Si el jugador es quien abre la ronda en el juego. De acuerdo a las propiedades que se encuentran en el juego, y si el jugador es quien abre el juego, es recomendable apostar un poco ms, de tal forma que intimide a que los contrincantes se retiren de la ronda, dejando as las cartas mayores para el CPU. Dentro de los rangos establecidos, se analizan si las cartas se encuentran dispersas o no. Esto igualmente permite saber qu tanto se va a apostar o no, ya que mientras menos disperso sea entonces no es importante apostar grandes cantidades, porque aunque uno se obtenga la carta de menor valor, aun as no existe mucha diferencia con la de mayor valor. Se maneja tambin el porcentaje mximo a apostar en las primeras rondas. Ya que a pesar de filtras la apuesta de acuerdo a la informacin detallada anteriormente, aun as existe la posibilidad de extra limitarse en la apuesta, pero con este parmetro limita a que no se apueste ms de lo establecido Se maneja el porcentaje mximo general para apostar en base al dinero disponible en ese momento, esto aplica para las otras rondas.

Igualmente que en la fase anterior se establecen rangos de valorizacin, pero sta vez es sobre los cheques. La gran diferencia se encuentra en que de acuerdo a muchas pruebas, el mantener dos rangos de cheques, es decir, de 0 a 7 mil, y de 8 mil a 15 mil, no era la forma adecuada de manejarlo, ya que existen dos cheques con el mismo valor y las decisiones no eran tan ptimas. Es por eso que se decidi realizar unos rangos mucho ms especficos. Generando 3 rangos, de 0 a 5 mil, de 6 mil a 10 mil, y de 11 mil a 15 mil, con estos nuevos rangos las decisiones propiedad versus cheque fueron ms acertadas los anteriores. Se controla tambin la dispersin que puede existir entre los cheques en mesa, vale aclarar que en la fase anterior como en sta, para poder decidir si son dispersos o no, tambin se toma en cuenta la cantidad de cartas que se encuentran en mesa, es decir, si son 3 jugadores, que por las reglas nos obligan a lanzar 3 cartas (propiedades o cheques), la diferencias de las mismas con el promedio es distinta a las diferencias que existen si es que se est jugando con 6 jugadores (6 cartas). Esto se establece por conceptos de dispersin matemticos. Esta fase se caracteriza por tener cheques con un valor de cero, para estos casos igualmente se analizan los cheques en mesa para poder tomar una decisin adecuada en caso se encuentren stos mismos. La recomendacin de acuerdo a distintos jugadores con experiencia, es no obtener ningn cheque en cero. En caso hayan cheques con los valores ms altos, se analiza si es el momento adecuado de lanzar las cartas ms altas que tiene el CPU en ese momento. ste anlisis va acorde al conocer tambin si es que ya se jugaron las propiedades ms altas que posiblemente tengan los contrincantes.

La informacin que se obtiene en cada turno del CPU para la fase 2 es:

Los algoritmos que se estn utilizando para ambas fases, as como los parmetros, y otras funciones o mtodos importantes que forman parte del algoritmo en general, se podrn encontrar en el anexo adjunto a este documento

4. Pruebas y Resultados
Una vez culminado el desarrollo del juego se realizaron una serie de pruebas para poder ir midiendo el nivel de eficiencia en las jugadas de los CPUs. Este nivel marca la dificultad con la que los CPUs compiten con sus contrincantes, es decir, mientras mayor sea el nivel, ms difcil ser ganarle al CPU. Como se indic en el punto anterior, el nivel se regula variando el valor a las variables establecidas en los algoritmos. Tabla 1. Pruebas y resultados realizados al juego No. 3 4 4 5 5 6 6 Frec. 20 14 12 15 12 20 14 Jugador 1 1 2 1 2 1 3 CPU 2 3 2 4 3 5 3 Resultados 40% gana CPU 70% gana CPU 50% - 50% 80% gana CPU 50% - 50% 90% gana CPU 50% - 50%

5. Trabajo a Futuro
Existen dos puntos importantes que se pueden desprender del presente proyecto. El primero (1) es que, dado los algoritmos creados que funcionan en base a ciertos parmetros establecidos previamente, stos pueden ser investigados con mayor profundidad con la finalidad de encontrar alguna distribucin estadstica y poder aplicarla, en vez de solamente asignar valores que se obtienen como resultado de las pruebas. Adems con estas distribuciones, se pueden definir claramente distintos niveles de dificultad para el juego (Fcil, Normal, Experto). El segundo (2), de acuerdo a los rangos establecidos en los algoritmos (fase inicial y fase final) se estn tomando distintas decisiones, aun as estos rangos son estticos, el objetivo de esta mejora es cambiar estos rangos de tal forma que varen de forma dinmica, reduciendo de esta forma los parmetros establecidos, y logrando una mejor toma de decisiones durante el juego.

Los resultados de las pruebas se pueden observar en la Tabla 1. Las pruebas se realizaron variando el nmero de jugadores, entre jugadores humanos y jugadores CPU. La tendencia general en las pruebas, es que mientras ms CPUs participen en un juego, ms difcil ser a una persona ganarle a cualquier CPU. Esto se ve en el resultado de 6 jugadores, en donde 5 son CPU y 1 es una persona, el 90% de las veces probadas gana cualquiera de los CPU. De lo contrario se ve cuando se prueban con 3 jugadores, y la configuracin es 2 personas y 1 CPU, en donde slo el 40% de las veces probadas gana el CPU. Y otro resultado importante de mencionar, es que en otras pruebas con distintas cantidades de jugadores, pero con configuraciones de 50% personas y 50% CPU, las veces que gana cualquier CPU son las mismas que cuando gana cualquier humano.

6. Conclusin
Se finaliz el proyecto con la programacin total del juego. Se lograron los objetivos planteados, es decir, recrear el juego en su totalidad, siguiendo todas las reglas y utilizando algoritmos heursticos; que gracias a la flexibilidad con que se construy es escalable, dando paso a posibles mejoras a futuro.

Referencias
[1] http://boardgamegeek.com/boardgame/172/forsale [2] http://blog.unthinkmedia.com/2011/02/03/whatare-games-heuristic-evaluations/ [3] http://boardgamegeek.com/thread/89221/forsale-strategy-article [4] http://www.panix.com/~sos/bc/forsale.html

Anexo
1. Fase 1 a. Algoritmo
public void PlayCPU(){ //CPU algorithm if (this.blnLastPlayer || player.getMoney() == 0 || player.getMoney() <= currentBidGeneral){ PassCPU(); return; } int intCardsMoreLessThanEqualNo = CardsMoreLessThanMixedNo(); boolean blnCardsScattered = CardsScattered(); boolean blnImFirstPlayer = IsFirstPlayer(); boolean blnImMoreThanHalfRounds = IsMoreThanHalfRounds(); int maxMoneyOtherPlayers = MaxMoneyOtherPlayers(); int avgMoneyOtherPlayers = AvgMoneyOtherPlayers(); int minToBid = currentBidGeneral+1000; int maxToBid = player.getMoney(); if (blnImFirstPlayer && currentBidGeneral == 0){ switch (intCardsMoreLessThanEqualNo){ case -1: //bid less if (blnCardsScattered) BidOpeningRound(openRound_LessThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidOpeningRound(openRound_LessThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 0: //bid regular if (blnCardsScattered) BidOpeningRound(openRound_Equal_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidOpeningRound(openRound_Equal_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 1: //bid more if (blnCardsScattered) BidOpeningRound(openRound_MoreThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidOpeningRound(openRound_MoreThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; } }else{ if (!blnImMoreThanHalfRounds){ //bid not too much switch (intCardsMoreLessThanEqualNo){ case -1: //bid less if (blnCardsScattered)

BidRegularRound(minToBid, regRoundInit_LessThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundInit_LessThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 0: //bid regular if (blnCardsScattered) BidRegularRound(minToBid, regRoundInit_Equal_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundInit_Equal_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 1: //bid more if (blnCardsScattered) BidRegularRound(minToBid, regRoundInit_MoreThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundInit_MoreThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; } }else{ switch (intCardsMoreLessThanEqualNo){ case -1: //bid less if (blnCardsScattered) BidRegularRound(minToBid, regRoundLast_LessThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundLast_LessThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 0: //bid regular if (blnCardsScattered) BidRegularRound(minToBid, regRoundLast_Equal_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundLast_Equal_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); break; case 1: //bid more if (blnCardsScattered) BidRegularRound(minToBid, regRoundLast_MoreThan_ScatMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers); else BidRegularRound(minToBid, regRoundLast_MoreThan_AvgMax, maxToBid, avgMoneyOtherPlayers, maxMoneyOtherPlayers);

break; } } } }

b. Parmetros
private int cardsMoreThan = 15; private double threeCardsOnTableNotScattered_Min = 1; private double threeCardsOnTableNotScattered_Max = 3; private double fourCardsOnTableNotScattered_Min = 1.5; private double fourCardsOnTableNotScattered_Max = 4; private double fiveCardsOnTableNotScattered_Min = 2; private double fiveCardsOnTableNotScattered_Max = 5; private double sixCardsOnTableNotScattered_Min = 2.5; private double sixCardsOnTableNotScattered_Max = 6; private int openRound_LessThan_ScatMax = 2000; private int openRound_LessThan_AvgMax = 1000; private int openRound_MoreThan_ScatMax = 3000; private int openRound_MoreThan_AvgMax = 2000; private int openRound_Equal_ScatMax = 3000; private int openRound_Equal_AvgMax = 2000; private double percentageMaxToBid = 0.90; private double percentageMaxFirstsRoundsToBidThreeFour = 0.30; private double percentageMaxFirstsRoundsToBidFiveSix = 0.50; private double percentageMaxFirstsRoundsToBid = 0.0; private int regRoundInit_LessThan_ScatMax = 2000; private int regRoundInit_LessThan_AvgMax = 1000; private int regRoundInit_MoreThan_ScatMax = 3000; private int regRoundInit_MoreThan_AvgMax = 2000; private int regRoundInit_Equal_ScatMax = 3000; private int regRoundInit_Equal_AvgMax = 2000; private int regRoundLast_LessThan_ScatMax = 3000; private int regRoundLast_LessThan_AvgMax = 2000; private int regRoundLast_MoreThan_ScatMax = 4000; private int regRoundLast_MoreThan_AvgMax = 2000; private int regRoundLast_Equal_ScatMax = 4000; private int regRoundLast_Equal_AvgMax = 2000;

c. Mtodos Importantes
private void BidRegularRound(int minMoneyToBid, int mySuggestMoneyToBid, int maxMoneyAvailable, int avgMoneyOthers, int maxMoneyOthers){ boolean blnImMoreThanHalfRounds = IsMoreThanHalfRounds(); if (mySuggestMoneyToBid < minMoneyToBid){ if (minMoneyToBid < (int)(maxMoneyAvailable*percentageMaxToBid)) mySuggestMoneyToBid = minMoneyToBid; else{ PassCPU(); return; } } //validate not to bid more than available, nor more than x% available

if (mySuggestMoneyToBid >= maxMoneyAvailable || mySuggestMoneyToBid > (int)(maxMoneyAvailable*percentageMaxToBid)) mySuggestMoneyToBid = (int)(maxMoneyAvailable*percentageMaxToBid); //validate to bid only quantity in thousands mySuggestMoneyToBid = (mySuggestMoneyToBid/1000)*1000; if (mySuggestMoneyToBid < minMoneyToBid){ if (minMoneyToBid < (int)(maxMoneyAvailable*percentageMaxToBid)) mySuggestMoneyToBid = minMoneyToBid; else{ PassCPU(); return; } } if (!blnImMoreThanHalfRounds) if (mySuggestMoneyToBid > (int)(maxMoneyAvailable*percentageMaxFirstsRoundsToBid)){ PassCPU(); return; } if (mySuggestMoneyToBid == 0){ PassCPU(); return; } BidCPU(mySuggestMoneyToBid); } private void BidOpeningRound(int mySuggestMoneyToBid, int maxMoneyAvailable, int avgMoneyOthers, int maxMoneyOthers){ //validate not to bid more than available, nor more than x% available if (mySuggestMoneyToBid >= maxMoneyAvailable || mySuggestMoneyToBid > (int)(maxMoneyAvailable*percentageMaxToBid)) mySuggestMoneyToBid = (int)(maxMoneyAvailable*percentageMaxToBid); //validate to bid only quantity in thousands mySuggestMoneyToBid = (mySuggestMoneyToBid/1000)*1000; if (mySuggestMoneyToBid == 0) PassCPU(); else BidCPU(mySuggestMoneyToBid); } private boolean IsMoreThanHalfRounds(){ boolean result = false; double dblCurrentRound = (double)currentRound; switch (allPlayers.size()){ case 3: if (dblCurrentRound >= 4.0) result = true; //max rounds 8 percentageMaxFirstsRoundsToBid = percentageMaxFirstsRoundsToBidThreeFour; break; case 4: if (dblCurrentRound >= 3.5) result = true; //max rounds 7 percentageMaxFirstsRoundsToBid = percentageMaxFirstsRoundsToBidThreeFour; break; case 5: if (dblCurrentRound >= 3.0) result = true; //max rounds 6 percentageMaxFirstsRoundsToBid = percentageMaxFirstsRoundsToBidFiveSix; break; case 6: if (dblCurrentRound >= 2.5) result = true; //max rounds 5 percentageMaxFirstsRoundsToBid = percentageMaxFirstsRoundsToBidFiveSix; break;

} return result; } private boolean IsFirstPlayer(){ if (this.noTurnInRound == 0) return true; else return false; } private boolean CardsScattered(){ boolean blnCardsScattered = true; int averageCards = AverageCardsOnTable(); int minCard = MinValueCardsOnTable(); int maxCard = MaxValueCardsOnTable(); int diffMin = averageCards - minCard; int diffMax = maxCard - averageCards; switch (propertiesOnTable.size()){ case 2: blnCardsScattered = false; break; case 3: if (threeCardsOnTableNotScattered_Min <= diffMin && diffMin <= threeCardsOnTableNotScattered_Max && threeCardsOnTableNotScattered_Min <= diffMax && diffMax <= threeCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 4: if (fourCardsOnTableNotScattered_Min <= diffMin && diffMin <= fourCardsOnTableNotScattered_Max && fourCardsOnTableNotScattered_Min <= diffMax && diffMax <= fourCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 5: if (fiveCardsOnTableNotScattered_Min <= diffMin && diffMin <= fiveCardsOnTableNotScattered_Max && fiveCardsOnTableNotScattered_Min <= diffMax && diffMax <= fiveCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 6: if (sixCardsOnTableNotScattered_Min <= diffMin && diffMin <= sixCardsOnTableNotScattered_Max && sixCardsOnTableNotScattered_Min <= diffMax && diffMax <= sixCardsOnTableNotScattered_Max) blnCardsScattered = false; break; } return blnCardsScattered; } private int CardsMoreLessThanMixedNo(){ int lessThan = 0; int moreThan = 0; for (int i=0; i<propertiesOnTable.size(); i++) if (propertiesOnTable.get(i).getValue() < cardsMoreThan) lessThan++; else

moreThan++; return ((lessThan > 0 && moreThan > 0) ? 0 : ((moreThan > 0) ? 1 : -1 )); }

2. Fase 2 a. Algoritmo
public void PlayCPU(){ //CPU algorithm int intCardsMoreLessThanEqualNo = CardsMoreLessThanMixedNo(); boolean blnCardsScattered = CardsScattered(); boolean blnExistsZero = ExistsAZeroCheck(); boolean blnExistsHighest = ExistsHighestChecks(); boolean blnSoldOutHighestProperties = SoldOutHighestProperties(); ArrayList<Property> tempProps = GetPropertiesSorted(); switch (intCardsMoreLessThanEqualNo){ case -1: //bid less 0-5 if (blnCardsScattered) if (blnExistsZero) SelectCPU(tempProps,Min_IndexScat_ExistsZero); //1 else SelectCPU(tempProps,Min_IndexScat_NoExistsZero); //0 else if (blnExistsZero) SelectCPU(tempProps,Min_IndexNoScat_ExistsZero); //1 else SelectCPU(tempProps,Min_IndexNoScat_NoExistsZero); //0 break; case 0: //bid regular 6-10 if (blnCardsScattered) SelectCPU(tempProps,Math.round(tempProps.size()/2)); //0 else SelectCPU(tempProps,Math.round(tempProps.size()/3)); //0 break; case 1: //bid more 11-15 if (blnCardsScattered) if (blnExistsHighest) if (blnSoldOutHighestProperties) SelectCPU(tempProps,tempProps.size()-1); else SelectCPU(tempProps,tempProps.size()-2); else if (blnSoldOutHighestProperties) SelectCPU(tempProps,Math.round(2*tempProps.size()/3)); else SelectCPU(tempProps,Math.round(2*tempProps.size()/3-1)); else if (blnExistsHighest) if (blnSoldOutHighestProperties) SelectCPU(tempProps,Math.round(2*tempProps.size()/3)); else SelectCPU(tempProps,Math.round(2*tempProps.size()/3-1)); else

if (blnSoldOutHighestProperties) SelectCPU(tempProps,Math.round(tempProps.size()/2+1)); else SelectCPU(tempProps,Math.round(tempProps.size()/2)); break; case 2: if (blnCardsScattered) if (blnExistsHighest){ if (blnSoldOutHighestProperties) SelectCPU(tempProps,Math.round(2*tempProps.size()/3)); else SelectCPU(tempProps,Math.round(2*tempProps.size()/3-1)); }else if (blnExistsZero) SelectCPU(tempProps,Math.round(tempProps.size()/2)); else SelectCPU(tempProps,Math.round(tempProps.size()/2+1)); else if (blnExistsHighest){ if (blnSoldOutHighestProperties) SelectCPU(tempProps,Math.round(2*tempProps.size()/3+1)); else SelectCPU(tempProps,Math.round(2*tempProps.size()/3)); }else if (blnExistsZero) SelectCPU(tempProps,Math.round(tempProps.size()/2)); else SelectCPU(tempProps,Math.round(tempProps.size()/2-1)); break; } }

b. Parmetros
private int checksMoreThan = 8; private int checksFirstLevel = 5; private int checksSecondLevel = 10; private double threeCardsOnTableNotScattered_Min = 1; private double threeCardsOnTableNotScattered_Max = 2.5; private double fourCardsOnTableNotScattered_Min = 1.5; private double fourCardsOnTableNotScattered_Max = 3; private double fiveCardsOnTableNotScattered_Min = 2; private double fiveCardsOnTableNotScattered_Max = 3.5; private double sixCardsOnTableNotScattered_Min = 2.5; private double sixCardsOnTableNotScattered_Max = 4; private int[] highestChecks = {14,15}; private int[] highestProps = {28,29,30}; private int Min_IndexScat_ExistsZero = 1; private int Min_IndexScat_NoExistsZero = 0; private int Min_IndexNoScat_ExistsZero = 1; private int Min_IndexNoScat_NoExistsZero = 0;

c. Mtodos
private void SelectCPU(ArrayList<Property> tempProp, int indexProp){ System.out.println(player.getName() + " - " + indexProp + " - " + tempProp.size()); if (indexProp > tempProp.size()-1 || indexProp < 0) indexProp = tempProp.size()-1; propertySelected = tempProp.get(indexProp); for (int i=0; i<player.getProperties().size(); i++){ if (player.getProperties().get(i).getIdProperty() == propertySelected.getIdProperty()){ player.getProperties().remove(i); break; } } } private boolean SoldOutHighestProperties(){ boolean soldOut = true; for (int i=0; i<allPlayers.size(); i++){ if (i != noTurnInRound) for (int j=0; j<allPlayers.get(i).getPlayer().getProperties().size(); j++){ for (int k=0; k<highestProps.length; k++) if (allPlayers.get(i).getPlayer().getProperties().get(j).getValue() == highestProps[k]){ soldOut = false; break; } if (!soldOut) break; } if (!soldOut) break; } return soldOut; } private boolean ExistsHighestChecks(){ boolean exists = false; for (int i=0; i<checksOnTable.size(); i++){ for (int j=0; j<highestChecks.length; j++) if (checksOnTable.get(i).getValue() == highestChecks[j]){ exists = true; break; } if (exists) break; } return exists; } private boolean ExistsAZeroCheck(){ boolean exists = false; for (int i=0; i<checksOnTable.size(); i++) if (checksOnTable.get(i).getValue() == 0){ exists = true; break; } return exists; }

private int CardsMoreLessThanMixedNo(){ int lessThan = 0; int middle = 0; int moreThan = 0; int result = 0; for (int i=0; i<checksOnTable.size(); i++) if (checksOnTable.get(i).getValue() <= checksFirstLevel) lessThan++; else if (checksOnTable.get(i).getValue() > checksFirstLevel && checksOnTable.get(i).getValue() <= checksSecondLevel) middle++; else moreThan++; if (lessThan > 0 && middle == 0 && moreThan == 0) result = -1; else if (lessThan == 0 && middle > 0 && moreThan == 0) result = 0; else if (lessThan == 0 && middle == 0 && moreThan > 0) result = 1; else result = 2; return result; } private boolean CardsScattered(){ boolean blnCardsScattered = true; int averageCards = AverageChecksOnTable(); int minCard = MinValueChecksOnTable(); int maxCard = MaxValueChecksOnTable(); int diffMin = averageCards - minCard; int diffMax = maxCard - averageCards; switch (allPlayers.size()){ case 3: if (threeCardsOnTableNotScattered_Min <= diffMin && diffMin <= threeCardsOnTableNotScattered_Max && threeCardsOnTableNotScattered_Min <= diffMax && diffMax <= threeCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 4: if (fourCardsOnTableNotScattered_Min <= diffMin && diffMin <= fourCardsOnTableNotScattered_Max && fourCardsOnTableNotScattered_Min <= diffMax && diffMax <= fourCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 5: if (fiveCardsOnTableNotScattered_Min <= diffMin && diffMin <= fiveCardsOnTableNotScattered_Max && fiveCardsOnTableNotScattered_Min <= diffMax && diffMax <= fiveCardsOnTableNotScattered_Max) blnCardsScattered = false; break; case 6: if (sixCardsOnTableNotScattered_Min <= diffMin && diffMin <= sixCardsOnTableNotScattered_Max &&

sixCardsOnTableNotScattered_Min <= diffMax && diffMax <= sixCardsOnTableNotScattered_Max) blnCardsScattered = false; break; } return blnCardsScattered; } private int AverageChecksOnTable(){ int allChecks = 0; int quantity = 0; for (int i=0; i<checksOnTable.size(); i++){ allChecks += checksOnTable.get(i).getValue(); quantity++; } if (quantity == 0) quantity++; return allChecks/quantity; }

Vous aimerez peut-être aussi