15
12
Jul

Flash, Inteligencia Artificial + 3 en raya

Hoy les presento a un juego que tiene mucha historia.
Esta vez, el juego lo he construido yo, de arriba a abajo. Lo juro

Tiene 2 tipos de juego: Dos Jugadores, para jugar 2 personas desde el mismo PC; y Un Jugador, contra la Inteligencia Artificial que programé. :o

http://blog.bleend.net/downloads/3_raya/3_raya%5BBleend%5D.swf

Nota: La inteligencia Artificial buena, es la de nivel 3 U_U



Algunas referencias para entender el código:

Para trabajar mejor con el tablero, lo representé virtualmente como una matriz 3×3:
[as]var t:Array = new Array();
t = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];[/as]

Cuando una posición del tablero (matriz) esta vacía, (no ha sido ocupada) le asigno un valor de 0.
Cuando una posición del tablero (matriz) ha sido ocupada por una cruz, le doy valor -1.
Cuando una posición del tablero (matriz) ha sido ocupada por una circunferencia, le doy valor 1.

Como podrán ver en el código de la IA, al trabajar con estos valores para la matriz, nos facilita mucho mas las cosas que trabajando con, por ejemplo: undefined , true y false


Les pongo el código de la IA con las funciones que utiliza:
[as]stop();

restart();
//–>Game
function evaluar(t) {
var res:Number = 0;
if (t[0][0] == t[1][1] && t[1][1] == t[2][2]) {
res = t[0][0];
}
if (t[0][2] == t[1][1] && t[1][1] == t[2][0]) {
res = t[0][2];
}
if (t[0][0] == t[0][1] && t[0][1] == t[0][2]) {
res = t[0][0];
}
if (t[1][0] == t[1][1] && t[1][1] == t[1][2]) {
res = t[1][0];
}
if (t[2][0] == t[2][1] && t[2][1] == t[2][2]) {
res = t[2][0];
}
if (t[0][0] == t[1][0] && t[1][0] == t[2][0]) {
res = t[0][0];
}
if (t[0][1] == t[1][1] && t[1][1] == t[2][1]) {
res = t[0][1];
}
if (t[0][2] == t[1][2] && t[1][2] == t[2][2]) {
res = t[0][2];
}
return res;
}

function posicion_libre(t) {
var res:Boolean = false;
var i:Number = 0;
var j:Number = 0;
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
if (t[i][j] == 0) {
res = true;
}
}
}
return res;
}

function disable() {
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
_root["_"+i+"_"+j].enabled = false;
}
}
}

function cruz(i, j) {
_root["_"+i+"_"+j].gotoAndStop("cruz");
t[i][j] = -1;
turno = 1;
turno_mc.gotoAndStop("p1");
trace(i+","+j);
}
function circulo(i, j) {
_root["_"+i+"_"+j].gotoAndStop("circulo");
t[i][j] = 1;
turno = 2;
turno_mc.gotoAndStop("p2");
}

function pulsar(i, j) {
if (!fin) {
if (turno == 1) {
circulo(i,j);
if (evaluar(t) == 0) {
IA();
}
}
}
switch (evaluar(t)) {
case 0 :
if (!posicion_libre(t)) {
//trace("empate");
turno_mc.gotoAndStop("empate");
reiniciar.play();
fin = true;
disable();
}
break;
case -1 :

//trace("ganan cruzes");
turno_mc.gotoAndStop("cruces");
reiniciar.play();
fin = true;
disable();
break;
case 1 :

//trace("ganan criculos");
turno_mc.gotoAndStop("circulos");
reiniciar.play();
fin = true;
disable();
break;
default :

trace("OMG! GRAN ERROR!");
break;
}
}

function restart() {
turno = 1;
fin = false;
turno_mc.gotoAndStop("p1");
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
_root["_"+i+"_"+j].enabled = true;
_root["_"+i+"_"+j].gotoAndStop(1);
t[i][j] = 0;
}
}
}

_0_0.onPress = function() {
pulsar(0,0);
};

_0_1.onPress = function() {
pulsar(0,1);
};
_0_2.onPress = function() {
pulsar(0,2);
};
_1_0.onPress = function() {
pulsar(1,0);
};
_1_1.onPress = function() {
pulsar(1,1);
};
_1_2.onPress = function() {
pulsar(1,2);
};
_2_0.onPress = function() {
pulsar(2,0);
};
_2_1.onPress = function() {
pulsar(2,1);
};
_2_2.onPress = function() {
pulsar(2,2);
};
reiniciar.onPress = function() {
restart();
if (cont) {
reiniciar.play();
}
};

menu.onPress = function() {
gotoAndStop("tablero");
};

/*----------I A ------------*/
function IA() {
var fet:Boolean = false;
var a:Number = 0;
var b:Number = 0;

if (d != 1 && d != 2) {//si no es facil ni normal
if (t[1][1] == 0 && !fet) {//coloca el medio
cruz(1,1);
fet = true;
}
if (!fet) {
a = 0;
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
if (t[i][j] == 0) {
a++;
}
}
}
if (a == 8 && (t[0][0] == 0 || t[2][0] == 0 || t[0][2] == 0 || t[2][2] == 0)) {
b = Math.floor(Math.random()*3);
switch (b) {
case 0 :
if (t[0][0] == 0 && !fet) {
cruz(0,0);
fet = true;
}
break;
case 1 :
if (t[0][2] == 0 && !fet) {
cruz(0,2);
fet = true;
}
break;
case 2 :
if (t[2][0] == 0 && !fet) {
cruz(2,0);
fet = true;
}
break;
case 3 :
if (t[2][2] == 0 && !fet) {
cruz(2,2);
fet = true;
}
break;
default :
trace("Error Switch");
break;
}
}
}
//a partir de aquí ataca->>>>>>
if (d != 1) {// si no es fácil (normal)
if (((t[0][0])+(t[1][1])+(t[2][2])) == -2 && !fet) {// diagonal 1 (\)
for (a=0; a<3; a++) {
b = a;//equación (condición de los puntos para que pertenezcan) a la recta de la diagonal 1 (y=x)
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
if (((t[0][2])+(t[1][1])+(t[2][0])) == -2 && !fet) {//diagonal 2 (/)
for (a=0; a<3; a++) {
b = 2-a;
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
b = 0;
while (b<3 && !fet) {
if (((t[0][b])+(t[1][b])+(t[2][b])) == -2 && !fet) {//horitzontals
for (a=0; a<3; a++) {
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
//endif
}//endfor
}
//endifyelse
b++;
}//endwhile
a = 0;
while (a<3 && !fet) {
if (((t[a][0])+(t[a][1])+(t[a][2])) == -2 && !fet) {
for (b=0; b<3; b++) {
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
a++;
}//endwhile
//a partir de aquí se defiende->>>>>>
if (Math.abs((t[0][0])+(t[1][1])+(t[2][2])) == 2 && !fet) {// diagonal 1 (\)
for (a=0; a<3; a++) {
b = a;//equación (condición de los puntos para que pertenezcan) a la recta de la diagonal 1 (y=2-x)
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
if (Math.abs((t[0][2])+(t[1][1])+(t[2][0])) == 2 && !fet) {//diagonal 2 (/)
for (a=0; a<3; a++) {
b = 2-a;
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
b = 0;
while (b<3 && !fet) {
if ((Math.abs((t[0][b])+(t[1][b])+(t[2][b]))) == 2 && !fet) {//horitzontals
for (a=0; a<3; a++) {
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
//endif
}//endfor
}
//endifyelse
b++;
}//endwhile
a = 0;
while (a<3 && !fet) {
if (Math.abs((t[a][0])+(t[a][1])+(t[a][2])) == 2 && !fet) {
for (b=0; b<3; b++) {
if (t[a][b] == 0 && !fet) {
cruz(a,b);
fet = true;
}
}
}
a++;
}//endwhile
}
//acaba el ataque+defensa (no hay posibliidad de ganar o perder)
}
if (!fet) {
a = 0;
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
if (t[i][j] == 0) {
a++;
}
}
}
if (a == 6 && (t[0][1] + t[1][0] + t[1][2] + t[2][1] == 0)) {
b = Math.floor(Math.random()*3);
switch (b) {
case 0 :
if (t[0][1] == 0 && !fet) {
cruz(0,1);
fet = true;
}
break;
case 1 :
if (t[1][0] == 0 && !fet) {
cruz(1,0);
fet = true;
}
break;
case 2 :
if (t[1][2] == 0 && !fet) {
cruz(1,2);
fet = true;
}
break;
case 3 :
if (t[2][1] == 0 && !fet) {
cruz(2,1);
fet = true;
}
break;
default :
trace("Error Switch 2");
break;
}
}
while (a == 6 && (t[0][0] + t[0][2] + t[2][0] + t[2][2] == 1) && !fet) {
b = Math.floor(Math.random()*3);
switch (b) {
case 0 :
if (t[0][0] == 0 && !fet) {
cruz(0,0);
fet = true;
}
break;
case 1 :
if (t[0][2] == 0 && !fet) {
cruz(0,2);
fet = true;
}
break;
case 2 :
if (t[2][0] == 0 && !fet) {
cruz(2,0);
fet = true;
}
break;
case 3 :
if (t[2][2] == 0 && !fet) {
cruz(2,2);
fet = true;
}
break;
default :
trace("Error Switch");
break;
}
}
}
//end dificultad
//no hay 2 iguales: (Genera una posición aleatoria)
if (!fet) {
for (i=0; i<3; i++) {
for (j=0; j<3; j++) {
if (t[i][j] == 0 && !fet) {
cruz(i,j);
fet = true;
}
}
}//endfors
}
}//endIA
[/as]

Como verán es algo lioso ver solamente el código, con lo que aquí les dejo el link para descargarlo:

fla Descargar 3 en raya (Código fuente *.fla)

Espero, les pueda ayudar en algo.

Me costó bastantes horas encontrar los bugs de la IA y perfeccionarla.

La IA no es perfecta, aunque tiene un buen nivel U_U

Entradas Relacionadas:

  1. Como leer el contenido de Combo Box en Flash
  2. Un juego en Flash hecho por mi. Block Puzzle
  3. Dibujar curvas parametrizadas 3D en Flash
  4. Charla BlocketPC sobre Flash Lite
  5. Historias de Starcraft en Flash

15 Awesome Responses.

  • Vale, la IA ha sido owneada… 2 veces… (ni 30 minutos me dejan vivir en la felicidad) :cry:

  • One

    Gané!!
    Ya te lo he dicho por gtalk ;)

  • Muy bueno Bleend (y)

    Jugué aproximadamente 5 veces, en el nivel 3, pero siempre hubo empate, no me dejó ganar ¬¬ Pero yo tampoco la dejé XD

    Prueba hacerlo en Prolog XD

  • RattaMono

    Si anda, como dice takag, prueba hacerlo en algún “Facíl y legible” lenguaje de programación lógica… el año que termines me avisas XD
    Aunque claro, creo que el paradigma se aplica a este problema.

    Es curioso, las formas para ganarle son las mismas que usaban mis amigos y yo para ganar entre nosotros XD

  • Teseo

    Este……………..
    este…………
    YA!
    Creo que se puede hacer muchísimo más corto ese código.
    Modo: Coges una matriz y le pones los 9*12 posibles movimientos con giros y simetrias. en cada turno buscas en la matriz donde este esa secuencia y te da la respuesta de movimiento.
    Lo que es el algoritmo de IA…..3 lineas de código.
    Sin acritud. Buen ejercicio.

  • Buf… Teseo, tu eres el amo; yo paso como puedo…

  • xD n ose como llegue aqui..
    bueno le gane :) ..
    (crusas el centro, luego la esquina contraria que marque la IA.. y luego ganas… XD.. facil)
    hmm y como dice teseo.. el codigo se puede hacer en mucho mucho menos codigo..

    suerte ^^

  • hmm bueno .. segui probando.. y si.. como les digo.. siempre ganas.. NUNCA PIERDES..
    esplico denuevo: marcas el centro.. (luego el marca una esquina), tu amrcas la esquina contraria (luego el te tapa o pone nseguida de la priemra q puso).. luego tu lo tapas… y te quedan algo asi: al centro… y 2 abajo. una en cada esquina.. luego el te tapa… y luego ganas… xD

    suerte y ganenle mucho ^^

  • Gracias Muela, sí, efectivamente, la IA no es dios que digamos…. *sigh

    De todas formas ahí se queda, no voy a arreglarla.
    Si buscan una perfecta, HernanRivas publicó una en cristalab. ;)

  • jose

    que bueno tu juego :wink: :wink:

  • Alex

    La partida perfecta acaba en empate.
    Siempre he estado probando combinaciones nuevas para ganar a mi hermano y contra el funcionan pero me he dado cuenta de que a mi mismo por ejemplo no podria ganarme :mrgreen:

  • Yo

    En que version esta guardado el .fla??

    No me deja abrirlo con el flash 8, me sale que el archivo es corrupto :S

  • Prueba con el CS3.

  • grax muy valioso tu aporte pz xD

Leave a Reply