Autor
|
Tema: ¿Cual es el método más eficiente para ver si hay una línea de S signos? (Leído 4,192 veces)
|
Tachikomaia
Desconectado
Mensajes: 1.576
Hackentifiko!
|
Conocen el juego 3 en línea, tic tac toe, tateti, etc. Yo estoy haciendo un S en línea, es decir, que el juego permita elegir cuántos signos debe haber en la línea (y qué tan grande es el tablero). Anduve pensando cual es el método más eficiente de ver si alguien ganó. Se me ocurrieron 2 métodos. El 1ero es bastante bruto, más o menos así: Se apunta al superior izquierdo. Repetir: Si no está vacío: Se miran sus contiguos de diagonal derecha-arriba: Si no hay o no marcan victoria: Se miran sus contiguos de la derecha: Si no hay o no marcan victoria: Se miran sus contiguos de diagonal derecha-abajo: Si no hay o no marcan victoria: Se miran sus contiguos de abajo: Si no hay o no marcan victoria: Si hay un casillero hacia abajo: Se empieza a mirar ese. sino si hay casilleros en la derecha: Se empieza a mirar el superior de esa columna. No es necesario que los ifs se repitan, sólo que al escribirlo así nomás quedaba más claro. El otro método intentaba usar menos repeticiones o variaciones de variables, pero a medida que lo analicé llegó un punto en que me parecía igual. En la misma repetición, se apunta a 2 casilleros (al principio son el mismo), y en cada repetición se varía a cual se apunta (y analiza como puse arriba), el 1ero es cada vez más hacia la derecha y el 2ndo hacia abajo. Cuando no quedan, se apunta al diagonal derecho-abajo y se repite el proceso hasta que el apuntado sea el inferior derecho. Empecé a aplicar el método 1: // Por practicidad al calcular, las filas se cuentan desde 0: Fila = -1; // Las columnas no, desde 1: Columna = 0; do { Fila++; SemiReferenciaAlCas = "Casillero"+Fila+"_"; do { Columna++; // Si el casillero no está vacío: if (eval(SemiReferenciaAlCas+Columna != 2)) { // Esto va variando qué siguientes... // casilleros se analizan: Extra = 0; do { Extra++; //
Ahí iría lo de analizar hacia la diagonal arriba-derecha, y el resto de las cosas. Pero siento que es tan poco eficiente que prefiero que me digan algo mejor, que probablemente haya. Sino, más adelante le pregunto a GPT. Por cierto, tengo pensado que la máquina aprenda a jugar experimentando, por eso los valores de los casilleros están grabados de 2 formas, por ejemplo el superior izquierdo: // 2 es vacío, 1 es cruz, 0 es 0. Casillero1 = 2; Casillero1_1 = 2; Porque al hacer referencia a una situación es más fácil variar sólo una variable (no fila y columna). Lo necesito para hacer árboles, no sé cómo lo hacen uds, hablaremos en otra ocasión de eso. Mientras hacía el tema me di cuenta que alcanza con analizar solamente las líneas que impliquen al casillero recién modificado  así que intentaré eso y podría borrar todo esto, pero igual puede ser interesante, luego pongo lo que logre.
|
|
|
En línea
|
|
|
|
Serapis
|
El modo más sencillo no es investigar todo el 'tablero', si no a partir el último movimiento de un jugador, antes de pasarle el turno a otro jugador revisar si ese último movimiento, tiene 2 contiguas más en alguna de las 4 direcciones (vertical, horizontal, diagonal izquierda y diagonal derecha). Para no incurrir en complicaciones de errores por estar fuera del tablero, es adecuado dimensionar el tablero a una casilla más perimetralmente... (solo en código, obviamente). Partamos pues de un esquema mental inicial con sus oportunas explicaciones... Tablero 0: | 3 | 3 | 3 | 3 | 3 | | 3 | 0 | 0 | 0 | 3 | | 3 | 0 | 0 | 0 | 3 | | 3 | 0 | 0 | 0 | 3 | | 3 | 3 | 3 | 3 | 3 | El tablero que se dibuja es el central (de 3x3), donde figuran las casillas vacías (valor 0). Perimetralmente se observa un valor 3 en todas las casilla. El jugador 1 marca las casillas suyas con un 1, el jugador 2 con un 2. Nota que son valores elegidos arbitrariamente, se puede elegir el conjunto que se desee siempre que se sea consecuente. Veamos ahora una partida empezada, olvidemos los pasos previos, en ellos se hará lo mismo que ahora se comenta, pero como solo habria inicialmente 1 casilla, marcada y luego 2, no ofrece el interés (explicativo y aclaratorio) que cuando ya el tablero está más avanzado... Tablero 1: | 3 | 3 | 3 | 3 | 3 | | 3 | 1 | 2 | 1 | 3 | | 3 | 0 | 1 | 0 | 3 | | 3 | - | 0 | 2 | 3 | | 3 | 3 | 3 | 3 | 3 | Empezaba el jugador 1, luego el 2... ahora es el turno del 2, y va a poner su ficha en la casilla marcada con '-' (solo para verla fácilmente), procede pues analizar el si jugador 2 ha conseguido las 3 en raya, sabiendo que su último movimiento es la casilla 3-A, o también 3-1 (Tercerá fila columna 1). Una función recibe: qué jugador tiene el turno y qué casilla marcó, queda pues mirar si a su alrededor las casillas contiguas son también son suyas hasta sumar 3: buleano = funcion Validar(jugador, fila, columna) puntos tipo byte
puntos =1 Si (Buscar(jugador, fila-1, columna, -1, 0) = FALSE) luego // 1 buscar hacia arriba: // Buscar en vertical Si (Buscar(jugador, fila+1, columna, 1, 0) = FALSE) luego // 2 buscar hacia abajo: // Buscar en vertical puntos =1 //reset puntos a 1. Si (Buscar(jugador, fila, columna-1, 0, -1) = FALSE) luego // 3 buscar hacia izquierda: // Buscar en horizontal Si (Buscar(jugador, fila, columna+1, 0, 1) = FALSE) luego // 4 buscar hacia derecha: // Buscar en horizontal
// Ahora las diagonales... puntos =1 //reset puntos a 1. Si (Buscar(jugador, fila-1, columna-1, -1, -1) = FALSE) luego // 5 buscar hacia diagonal izquierda y arriba: // Buscar en diagonal '\' Si (Buscar(jugador, fila+1, columna+1, 1, 1) = FALSE) luego // 6 buscar hacia diagonal derecha y abajo: // Buscar en diagonal '\' puntos =1 //reset puntos a 1. Si (Buscar(jugador, fila-1, columna+1, -1, 1) = FALSE) luego // 7 buscar hacia diagonal derecha y arriba: // Buscar en diagonal '/' Si (Buscar(jugador, fila+1, columna-1, 1, -1) = FALSE) luego // 8 buscar hacia diagonal izquierda y abajo: // Buscar en diagonal '/' devolver FALSE fin si fin si fin si fin si fin si fin si fin si fin si devolver TRUE fin funcion
Todas las verificaciones se derivan a esta única función para no repetir código, donde solo cambia el avance de fila o columna para revisar... El parámetro puntos se recibe por referencia, es decir conserva su valor tras salir de la función. El tablero tiene perimetralmente una casilla adicional luego es del tamaño 0 a 4 de ancho y lo mismo de alto, siendo útiles a los jugadores solo las casillas 1,2,3. en ese perímetro hay un valor que no corresponde al tablero (valor 0), ni a los jugadores (1 ni 2). Un jugador solo podría ocupar así una casilla del tablero con valor 0... etc... las normas son bien conocidas (en jerga se dice 'well known') por todos los interesados. buleano funcion Buscar(puntos, jugador, Fila, Columna, dF, dC) mientras tablero(Fila, Columna) = jugador puntos +=1 Si (puntos = 3) devolver TRUE
Fila += dF // df puede ser -1, 0, 1 Columna += dC // dC puede ser -1, 0, 1 repetir
devolver FALSE fin funcion
Si se examina el código con el estado actual en el 'tablero 2', se verá que devuelve false, el jugador 2, no tiene 3 en raya. Ahora supongamos que el jugador 2, (ver tablero 3) en vez de marcar la casilla 3,A hubiera marcado la casilla 3,B con intención luego de marcar la 3,A para hacer 3 en raya en la fila C. Entonces el jugador 1, sí marca la casilla 3,A que si se comprueba con la función, devolverá TRUE tras la búsqeuda 7 (se han enumerado en los comentarios las 8 búsquedas), que es la diagonal '/' y que empieza a buscar desde la casilla marcada 3A (3,1) Tablero 3: | 3 | 3 | 3 | 3 | 3 | | 3 | 1 | 2 | 1 | 3 | | 3 | 0 | 1 | 0 | 3 | | 3 | - | 2 | 2 | 3 | | 3 | 3 | 3 | 3 | 3 | La lógica es bastante simple, pero como se ve, no se precisa recorrer todas las líneas, ni todas las columnas, ni todas las diagonales, sino solo alrededor de la casilla recién marcada por el jugador.
|
|
« Última modificación: 30 Enero 2025, 19:09 pm por Serapis »
|
En línea
|
|
|
|
Serapis
|
Antes que nada, los temas se responden en su hilo, no por privado... ... Ya imprimí tu código hace días y lo estoy entendiendo un poco más.
Estas son mis dudas por ahora:
Pones: buleano funcion Buscar(puntos, jugador, Fila, Columna, dF, dC) ¿qué es dF y dC? dF y dC, son los nombres de dos parámetros cuyo significado es: 'diferencia de Filas y diferencia de Columnas. Nota como en las líneas que llaman a dicha función, el valor que se entrega y recibiría ese parámetro puede ser un valor positivo, negativo o cero, en algún caso es el resultado de una suma o una resta, del valor allí actual ±1 Pones: mientras tablero(Fila, Columna) = jugador ¿Has definido una función tablero? No la veo. ¿El tablero lo has definido como un array? Por ejemplo tablero = [3, 3, 3, 3, 3, 0, 0, 0, 0, 0...] En efecto, Tablero es un array... no lo he definido en el pseudocódigo, por que ¿es evidente, no?. Tu idea de poner casilleros que no se usan parece facilitar las cosas, pero no eficiente, por eso no me agrada del todo. Cómo que no es eficiente?. En un array de 3x3 (que es pequeño), ciertamente se traslada a un array de 5x5, que entre 9 y 25 hay diferencia... pero ¿cuantos arrays de éstos vas a usar a la vez, 500?. Pues incluso con 500 arrays es más eficiente, el consumo de memoria es despreciable (salvo que estuvieres operando con un equipo con una memoria de pocos Mb. Apenas tengas 1Gb. ... es insignificante. El caso es todavía más absurdo, si solo vas a usar 1-5 arrays (que muy probablemente se limite a solo 1 o 2) a la vez. Más aún, cuanto mayor sea el tablero, más insignificante es ese añadido, pues siempre añade filas*2 + columnas*2 + 4. Así si tu Tablero es de (por ejemplo) 100x100 (10.000 elementos), el tamaño de la solución sería de 102x102 (100*4 + 4 = añade 404, en total 10.404), que como se ve, ya no es casi el triple del tamaño como sucedía en el tablero de 3x3 (278%), ahora es solo de un 104'04%... Calcula cuanto es para un tablero de 1000x1000... verás que cuanto más grande es el tablero, menos porcentaje supone cercarlo perimetralmente con una casilla más. En cuanto a la eficiencia en uso durante la progrtamación es extremadamente sencillo controlarlo y por tanto es muy eficiente, pues solo se busca la comprobación TRUE/FALSE en validaciones simples, de otro modo tienes que hacer más complejo cada caso, además de múltiples lineas de código y código más farragosos de leer y modificar... En cualquier caso, puedes recrear ambos modelos, y probarlos en bucle miles o decenas de miles de veces (en igualdad absoluta de condiciones), y verificar tiempos de ejecución entre ambos. Cuando hagas una afirmación asegúrate que sea fundada, si no e spreferible callarse hasta comprobarlo, y si es una opinión, no es adecuado opinar públicamente sin haberse asegurado de lo que se dice, piensalo para ti, pero si no lo pones a prueba estarás dejando la posibilidad de aprender. Por mi parte logré esto: - Posibilidad de agrandar/achicar el tablero (hacerlo reinicia la partida). - Posibilidad de elegir qué tan larga debe ser la línea (idem). - Se detecta la victoria cuando se requiere 1 y se pone 1. - La máquina pone en posiciones al azar donde no haya signo, funciona bien al menos con tablero 3x3. - Se detecta la victoria/derrota cuando se requiere 2 y se ponen 2 contiguos en cualquier sentido. Funciona bien en tablero de 3x3. Falta poner casos de empate y otras cosas... Está bien que logres completar objetivos... function HacerTablero () { // Esto se irá especificando en el while: Situacion = []; PosiblesAcciones = []; // Los casilleros se cuentan desde 0: MaxCasillero = CasillerosPorFila*CasillerosPorFila-1; LargoDeCasilleros = 384/CasillerosPorFila; NroDeCasilleroaColocar = -1; // Sus columnas y filas se cuentan desde 0, // sirven para posicionarlos más fácil: Columna = 0; Fila = 0; do { NroDeCasilleroaColocar++; // v es vacío: Situacion.push("v"); PosiblesAcciones.push(NroDeCasilleroaColocar); CasilleroaColocar = "Casillero"+NroDeCasilleroaColocar; // set ("SignoEn"+CasilleroaColocar, "v"); // sCasillero tiene código. attachMovie("sCasillero", CasilleroaColocar, NroDeCasilleroaColocar); setProperty (CasilleroaColocar, _x, LargoDeCasilleros*Columna); setProperty (CasilleroaColocar, _y, LargoDeCasilleros*Fila); setProperty (CasilleroaColocar, _width, LargoDeCasilleros); setProperty (CasilleroaColocar, _height, LargoDeCasilleros); Columna = Columna+1; if (Columna == CasillerosPorFila) { Columna = 0; Fila = Fila+1; } // Para que al presionar el botón se sepa qué modificar: set (CasilleroaColocar+".CasilleroAsociado", NroDeCasilleroaColocar); // trace("Colocado el "+NroDeCasilleroaColocar); } while (NroDeCasilleroaColocar<MaxCasillero); // Para que no muestre el mensaje de victoria: Win = "No"; } function HumanoHaMarcado () { // Inutilizar botón del casillero marcado: setProperty (eval("Casillero"+CasilleroMarcado+".Boton"), _visible, false); // Agregar cruz: // SignosColocados++; eval("Casillero"+CasilleroMarcado).attachMovie("sCruz", "Cruz", 1); Situacion[CasilleroMarcado] = "X" // set ("SignoEnCasillero"+CasilleroMarcado, "X"); // ¿Gana? if (JuntosRequeridos == 2) { ObtenerColumnayFilaDelMarcado(); // Para saber si el cuadradito marcado no tiene... // contiguos hacia algún lado: ObtenerExcepciones(); trace("Aplicando ChequeoDe2Excepto"+FuncNamePart1+FuncNamePart2); eval("ChequeoDe2Excepto"+FuncNamePart1+FuncNamePart2)(); } else if (JuntosRequeridos == 1) { Win = "Sí"; } if (Win == "Sí") { // Sí, inutilizar botones del tablero // (debería ser sólo los activos): InutilizarBotones(); // Mostrar mensaje de victoria: attachMovie("sGanoX", "Mensaje", NroDeCasilleroaColocar+1); setProperty (Mensaje, _x, 192.4); setProperty (Mensaje, _y, 192); gotoAndStop (3); } else { // Quitar su acción de las posibles acciones: // Se busca en qué posición del array está: AccionRevisandose = -1; // Esto es para evitar restas: LastNroDeAcccion = PosiblesAcciones.length-1; // Probablemente sea ok poner true en la condición: do { AccionRevisandose++; if (PosiblesAcciones[AccionRevisandose] == CasilleroMarcado) { // Se sustituye por la que está última: PosiblesAcciones[AccionRevisandose] = PosiblesAcciones[LastNroDeAcccion]; // Se elimina la última: PosiblesAcciones.pop(); break; } } while (AccionRevisandose < LastNroDeAcccion); LastNroDeAcccion--; // Elegir una acción al azar: NroDeAccionElegida = random(PosiblesAcciones.length); AccionElegida = PosiblesAcciones[NroDeAccionElegida]; // Eliminar la que está en el nro elegido: // Se sustituye por la que está última: PosiblesAcciones[NroDeAccionElegida] = PosiblesAcciones[LastNroDeAcccion]; // Se elimina la última: PosiblesAcciones.pop(); eval("Casillero"+AccionElegida).attachMovie("sCero", "Cero", 0); Situacion[AccionElegida] = 0; // Inutilizar el botón de ahí: setProperty (eval("Casillero"+AccionElegida+".Boton"), _visible, false); // Ver si 0 ganó: CasilleroMarcado = AccionElegida; if (JuntosRequeridos == 2) { ObtenerColumnayFilaDelMarcado(); // Para saber si el cuadradito marcado no tiene... // contiguos hacia algún lado: ObtenerExcepciones(); trace("Aplicando ChequeoDe2Excepto"+FuncNamePart1+FuncNamePart2); eval("ChequeoDe2Excepto"+FuncNamePart1+FuncNamePart2)(); if (Win == "Sí") { // Sí, inutilizar botones del tablero // (debería ser sólo los activos): InutilizarBotones(); // Mostrar mensaje de victoria: attachMovie("sGano0", "Mensaje", NroDeCasilleroaColocar+1); setProperty (Mensaje, _x, 192.4); setProperty (Mensaje, _y, 192); gotoAndStop (3); } } } // _level0.ObtenerSituacion(); } function ObtenerColumnayFilaDelMarcado () { FilaDelMarcado = Math.floor(CasilleroMarcado/CasillerosPorFila); trace ("Su Fila según el cálculo es: "+FilaDelMarcado); ColumnaDelMarcado = CasilleroMarcado%CasillerosPorFila; trace ("Su Columna: "+ColumnaDelMarcado); } function ObtenerExcepciones () { if (FilaDelMarcado != 0) { if (FilaDelMarcado != CasillerosPorFila0) { FuncNamePart1 = ""; } else { FuncNamePart1 = "Abajo"; } } else { FuncNamePart1 = "Arriba"; } if (ColumnaDelMarcado != 0) { if (ColumnaDelMarcado != CasillerosPorFila0) { FuncNamePart2 = ""; } else { FuncNamePart2 = "Derecha"; } } else { FuncNamePart2 = "Izquierda"; } } // Chequear todo, no hay excepción especificada: function ChequeoDe2Excepto () { // 012 // 3x5 // 678 Desde = -1; Hasta = 3; Incremento = 1; ChequeoDe2(); if (Win == "No") { Desde = 4; Hasta = 8; Incremento = 1; ChequeoDe2(); } } function ChequeoDe2ExceptoArriba () { // 0x2 // 345 // 678 Desde = 1; Hasta = 5; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[0]) { Win = "Sí"; } } } function ChequeoDe2ExceptoAbajo () { // 012 // 345 // 6x8 Desde = 2; Hasta = 6; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[8]) { Win = "Sí"; } } } function ChequeoDe2ExceptoIzquierda () { // 012 // x45 // 678 Desde = -2; Hasta = 7; Incremento = 3; ChequeoDe2(); if (Win == "No") { Desde = -6; Hasta = 6; Incremento = 6; ChequeoDe2(); } } function ChequeoDe2ExceptoDerecha () { // 012 // 34x // 678 Desde = -2; Hasta = 7; Incremento = 3; ChequeoDe2(); if (Win == "No") { Desde = -4; Hasta = 8; Incremento = 6; ChequeoDe2(); } } function ChequeoDe2ExceptoArribaIzquierda () { // x12 // 345 // 678 Desde = 2; Hasta = 4; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[1]) { Win = "Sí"; } } } function ChequeoDe2ExceptoArribaDerecha () { // 01x // 345 // 678 Desde = 2; Hasta = 5; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[1]) { Win = "Sí"; } } } function ChequeoDe2ExceptoAbajoIzquierda () { // 012 // 345 // x78 Desde = 2; Hasta = 4; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[7]) { Win = "Sí"; } } } function ChequeoDe2ExceptoAbajoDerecha () { // 012 // 345 // 67x Desde = 3; Hasta = 5; Incremento = 1; ChequeoDe2(); if (Win == "No") { if (Situacion[CasilleroMarcado] == Situacion[7]) { Win = "Sí"; } } } // function ChequeoDe2 () { Win = "No"; do { Desde = Desde+Incremento; trace("Chequeando "+Desde); if (Situacion[CasilleroMarcado] == Situacion[Desde]) { Win = "Sí"; break; } } while (Desde < Hasta); } function InutilizarBotones () { BotonesInutilizados = -1; do { BotonesInutilizados++; setProperty ("Casillero"+BotonesInutilizados+".Boton", _visible, false); } while (BotonesInutilizados<MaxCasillero); } CasillerosPorFila = 3; // Contando desde 0: CasillerosPorFila0 = CasillerosPorFila-1; JuntosRequeridos = 2; HacerTablero();
Muestra:  También estoy haciendo una IA que aprende experimentando. Por ahora sólo capta 2 horizontales, no hay rival, y me falta la etapa 2: En general la IA tiene sentido cuando algo es tan complejo y vasto que es inasumible para un humano poder abarcarlo... no vivimos tanto como para dedicarlo 8.000 años a determinados problemas... el juego del 3 en raya, es muy simple... si un niño de unos 12 años juega lo sufiiiiiiieciente no tardará en darse cuenta que hay una estrategia para no perder nunca, así como se dará cuenta que el jugador que sale tiene mayor ventaja. // 2 en línea horizontal, en tablero de 2x2, sólo X: // // Uso arrays porque es más fácil así modificar los nombres... // de variables: // // Los casilleros están numerados así: // 0 1 // 2 3 // Situación inicial (v es casillero vacío): SituacionBase = ["v", "v", "v", "v"]; // Ponerla en la lista de situaciones a experimentar: SaE1 = SituacionBase.slice(); // Situaciones a experimentar (cuántas son): SaE = 1; NroDeSExperimentandose = 1; NombreDeSE = "S"+(SaE1.join("")); // Acción a realizarse (casillero a marcar): Action = 0; // Este programa tiene básicamente 2 etapas: // 1: Buscar situaciones en que se puede ganar mediante 1 acción. // 2: FALTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA function BuscarBuenasSituaciones () { // Plantear situación porque puede modificarse pero... // podría requerirse su estado original luego: Situacion = SituacionBase.slice(); trace("La situación experimentándose es "+Situacion); EvaluarAplicabilidadEt1(); } // ¿La acción es realizable? // Etapa 1 (buscar buenas situaciones) function EvaluarAplicabilidadEt1 () { trace("Ejecutando EvaluarAplicabilidadEt1"); if (Situacion[Action] == "v") { // Sí, realizarla: AplicarAccionEt1(); } else if (Action < 3) { trace("La acción "+Action+" no es realizable."); // Sino si queda alguna acción sin probar... // en la situación, probarla: Action++; EvaluarAplicabilidadEt1(); } else { trace("No hay más acciones realizables."); BuscarOtraSituacionEt1(); } } function AplicarAccionEt1 () { trace("Ejecutando AplicarAccionEt1"); Situacion[Action] = "X"; trace("Se realizó la acción "+Action+"; ahora la situación es "+Situacion); // ¿Ganó? // Para averiguarlo, calcular fila (contando desde 0): ObtenerColumnayFilaDelMarcado(); CuadraditoMinimoDeLaFila = FilaDelMarcado*2; if (Situacion[CuadraditoMinimoDeLaFila] == Situacion[CuadraditoMinimoDeLaFila+1]) { // trace("Situacion[CuadraditoMinimoDeLaFila] == Situacion[CuadraditoMinimoDeLaFila+1]: "+Situacion[CuadraditoMinimoDeLaFila]+" == "+Situacion[CuadraditoMinimoDeLaFila+1]); // Sí, crear datos sobre eso: // En la situación base conviene la acción realizada: set (NombreDeSE+"BestAction", Action); // En esa situación se requiere 1 acción para ganar: set (NombreDeSE+"DistanciaaGanar", 1); trace("Ganó, ahora se sabe que en la situación "+SituacionBase+" se gana usando la acción "+Action); BuscarOtraSituacionEt1(); } else { EvaluarConocimientoSobreSEt1(); // ¿Queda alguna acción sin probar... // en la situación? if (Action < 3) { // Sí, probarla: Action++; // Se ejecutará BuscarBuenasSituaciones. } else { BuscarOtraSituacionEt1(); } } } function ObtenerColumnayFilaDelMarcado () { FilaDelMarcado = Math.floor(Action/2); ColumnaDelMarcado = Action%2; } // ¿Aún hay situaciones a experimentar? function BuscarOtraSituacionEt1 () { trace("Ejecutando BuscarOtraSituacionEt1"); if (SaE > NroDeSExperimentandose) { IniciarExperimentosEnOtraSEt1(); } else { trace( "No hay más situaciones a experimentar; inicia la etapa 2."); IniciarEtapa2(); } } // ¿La situación está anotada en las que deben investigarse? function EvaluarConocimientoSobreSEt1 () { trace("Ejecutando EvaluarConocimientoSobreSEt1"); SituacionHechaTexto = Situacion.join(""); NombreDeSituacion = "S"+SituacionHechaTexto; Resumen = NombreDeSituacion+"BestAction"; if (eval(Resumen) == undefined) { // No, anotar que debe investigarse: SaE++; set ("SaE"+SaE, Situacion.slice()); trace("Esa situación no está anotada; se anota como nro "+SaE); // Esto para saber que está anotada: set (Resumen, "Desconocida"); } } function IniciarExperimentosEnOtraSEt1 () { trace("Ejecutando IniciarExperimentosEnOtraSEt1"); NroDeSExperimentandose++; SituacionBase = eval("SaE"+NroDeSExperimentandose); // trace("SituacionBase: "+SituacionBase); // Reset de la acción a probar: Action = 0; trace("Se inician experimentos en otra situación, la anotada nro "+NroDeSExperimentandose); } function IniciarEtapa2 () { DistanciaaGanarAceptada = 1; trace("Se experimentaron todas las situaciones; se reexperimentarán buscando resultados menos óptimos"); trace("Son "+SaE+" situaciones; se acepta que la distancia a la victoria sea "+DistanciaaGanarAceptada); gotoAndStop (3); }
 Este diagrama no lo terminé pero puede ayudar a entender cómo funciona: Es suficiente con que lo entiendas tú...
|
|
|
En línea
|
|
|
|
|
|