elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


  Mostrar Temas
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 52
1  Programación / Programación General / Black Jack ¿cómo llamar a las cartas? en: Hoy a las 06:28
Empiezo videojuego que se supone es sencillo de hacer:
Código
  1. // Generar array de cartas:
  2. Cartas = [];
  3. Nro = 0;
  4. do {
  5. Nro++;
  6. Cartas[Cartas.length] = "Pica"+Nro;
  7. Cartas[Cartas.length] = "Trebol"+Nro;
  8. Cartas[Cartas.length] = "Corazon"+Nro;
  9. Cartas[Cartas.length] = "Diamante"+Nro;
  10. } while (Nro < 13);
  11. // Ordenarlas al azar:
  12. Posicion1aReubicarse = Cartas.length-1;
  13. while (Posicion1aReubicarse>0) {
  14. Posicion2aReubicarse = random(Posicion1aReubicarse+1);
  15. // trace (Cartas[Posicion1aReubicarse]+" se intercambiará con "+Cartas[Posicion2aReubicarse]);
  16. SaveDeElemento1 = Cartas[Posicion1aReubicarse];
  17. Cartas[Posicion1aReubicarse] = Cartas[Posicion2aReubicarse];
  18. Cartas[Posicion2aReubicarse] = SaveDeElemento1;
  19. Posicion1aReubicarse--;
  20. }
  21. trace (Cartas);

Ejemplo de salida:
Corazon8,Diamante9,Trebol11,Trebol6,Diamante11,Corazon2,Corazon1,Pica2,Pica3,Pica5,etc

Cuando un jugador tome cartas, el programa deberá poder calcular cuánto suman.

Ya sé, en vez de ponerles nombres tan largos, les pongo:
P, T, C, D
luego cuando deba sumar les quito el caracter y ya tengo el número.

¿Algún método mejor? ¿consejos sobre cómo hacer el juego?

He pensado en estos pasos a seguir (orden a realizar, no es que en el código vayan a estar así):
- Lograr que las cartas se ordenen al azar. Hecho.
- Mensaje dice cuales son las 2 obtenidas.
- Se suman pero, las 1 valen 11 (salvo que sean 2 1s, en ese caso el 2ndo vale 1) y las que están por encima de 10 valen 10.
- Un rival también obtiene 2 cartas.
- Se suman por separado y se compara quién obtuvo mayor suma.
- Se pregunta al jugador si quiere otra carta. Si dice que sí se le da y se acaba, sino lo de siempre.
- Ajustar la suma, ahora 1 podría valer 1 o 11.
- El jugador puede pedir carta de nuevo, hasta... 4+8+12, digo, mientras tenga menos de 11 cartas. Eso fue calcular que tendría 4 de 1 (1*4=4), 4 de 2, y 4 de 3, las mínimas cartas, 12, pero con esas suma más de 21, no tiene sentido que llegue a tener 12.
- El rival tomará cartas mientras su suma no llegue a 17. Me lo dijo GPT, sólo sería para probar.
- Se analiza quién ganó y se dice en pantalla.
- Para cada posible situación (cartas de la IA y cuántas tiene la persona) generar un archivo txt cuyo nombre marque qué situación es.
- En cada archivo guardar 2 variables, ambas con valor 0: P y T. Plantarse o tomar.
- Cuando la partida acabe, si la IA ganó, aumentar 1 al valor de la acción que usó en las situaciones en que estuvo, sino restarle. No sé exacto cómo sería esto.
- La IA hace lo que el correspondiente archivo marque como más valioso.
- Lo de aumentar o restar se aplica usando también las cartas de la persona, o sea, desde su perspectiva, conociendo sus cartas pero no las de la IA.

También se podría hacer un generador de las situaciones posibles y probar cada acción así, pero las situaciones son como 52*51*50*49 para empezar...
Ah pero no importa si se tiene el 1 de pica o trebol, etc, así que...
10*10*10*10 para empezar. Igual serían demasiados archivos... La información se puede poner en 1 solo, o distinta info en más de 1, habrá que ver...

- Opción de jugar contra 2.
- Nuevo aprendizaje, basado en jugar contra 2.

Supongo que no llegaré a tanto xP
2  Foros Generales / Dudas Generales / ¿Cómo elimino lo extra de una lista que quiero copiar? en: 14 Septiembre 2025, 20:56 pm
https://www.nintendolife.com/games/browse?sort=score&system=nes&genre=action

Quisiera copiar los nombres de los juegos, pero al ir arrastrando el mouse para copiar la lista entera, se copian más cosas.

De lo que se me ocurre lo mejor me parece pegarlo en Excel (de hecho lo quiero ahí) y cada X filas (donde aparezca lo que quiero copiar) poner un número en otra columna, luego ordenar por ese número. El problema es que quizá haya casos en que los juegos estén más abajo o más arriba, o sea que haya distintas filas de diferencia. Busco un método más seguro.
3  Media / Juegos y Consolas / Juegos que requieren pocas decisiones. en: 6 Septiembre 2025, 07:01 am
La respuesta de GPT fue erradísima, pruebo suerte aquí.

Para determinar qué arma conviene usar en Contra, hay 2 métodos:
A- Intentar pasar el juego con el arma S, luego con la M, etc.
B- Anotar los momentos en que se puede cambiar de arma y luego en cada uno decidir qué arma usar. Probar diferentes configuraciones.
En cualquier caso, con la que se llegue más lejos o más cómodo será la mejor.

Los métodos mejoran si en vez de considerarse 1 arma para cada caso, se consideran tops, o sea, cual es la 2nda preferible en caso de no poder tener la que se estableció.

El método B es más exacto pero más tedioso. Dime juegos en que lo dicho pueda aplicarse pero no tengan tantos momentos en que se deba decidir algo como qué arma llevar.


El 1ero que me recomendó fue Metal Slug. Puede que cumpla el requisito, ajá, pero la diferencia es casi inexistente. Sus otros ejemplos tampoco me sirvieron o son de juegos demasiado nuevos, yo por ahora quiero de NES/Famicom.

Ejemplos:

- Super Spike V'Ball:
https://www.youtube.com/watch?v=MZHFFLxDO4Q
Eliges al equipo al inicio, conformado por sólo 2 jugadores que no tienen diferencia entre sí (los del mismo equipo), y quizá se elige algo más pero, que yo recuerde nada del otro mundo, es apretar los botones en los momentos adecuados, pararse lejos del compañero o en el medio de la cancha no recuerdo, intentar bloquear saltando o no, en fin, no son el tipo de variables que me interesan.

- Mario Bros: No el super y más conocido, sino uno más antiguo en que salen bichitos de tubos. Hay que decidir cuando usar el POW. Qué enemigos atacar 1ero podría ser interesante tenerlo en cuenta pero es como que se resuelve inconscientemente, es parte de la duda.

- Tiny Toon: Al comienzo de cada mundo hay que elegir qué personaje secundario usar. Creo que sólo se elige 6 veces y son sólo 3 personajes. El personaje primario creo que es siempre peor, excepto que Dizzy en ciertas circunstancias.

No busco juegos en que la decisión sea qué ruta seguir.

¿Cuales recomendarían?
4  Programación / Programación General / Excel: Automatizar cambio de fórmulas al crear columna. en: 28 Agosto 2025, 22:34 pm
en la celda N12 tengo esto:
=SI(CONTAR.SI($N$2:$N$9;B12)>1; $N$10; "")
más abajo se repite, cambiando B12 por B13, etc
Más abajo la fórmula cambia a:
=SI(Y(CONTAR.SI($N$2:$N$9;A19)>0; CONTAR.SI($N$2:$N$9;B19)>0); $N$10; "")
más abajo se repite, cambiando A19 y B19, por A20 y B20, luego 21, etc
Finalmente, más abajo cambia a:
=SI(CONTAR.SI($N$2:$N$9;B124)>0; $N$10; "")
y más abajo se repite cambiando B124 por B125, etc

Debo crear columnas al lado de esa, y es muy tedioso cambiar las letras.
A y B deben mantenerse, pero si le pongo los $ no van a cambiar los números cuando quiera que lo hagan hacia abajo.
Y N debe cambiar a M, luego a O, etc, pero si no le pongo los $ aumentarían los números de los rangos cuando quiera que la fórmula se aplique más abajo.

¿comprendes? ¿hay alguna forma de automatizar eso mejor? Por ejemplo se me ocurre hacer un programa que genere las fórmulas separadas con tab, luego creo las columnas y pego esas fórmulas

...

La respuesta de GPT es complicada para mí:
Sí, comprendo el problema: necesitas arrastrar fórmulas hacia abajo (que cambien los números de fila) y también copiarlas hacia la derecha a nuevas columnas, donde la letra de la columna de búsqueda (N) cambie a M, O, P, etc., pero sin que se “rompan” las referencias al arrastrar.

Claves para resolverlo sin macros:
- Usa referencias mixtas para filas/columnas según necesites que varíen.
- Usa DESREF/INDICE con COINCIDIR o con COLUMNAS/ FILAS para construir rangos que cambien de columna al copiar a la derecha.
- Evita “letras fijas” en las fórmulas; genera el rango por posición.

Propuesta 1: construir el rango N2:N9 de forma dinámica según la columna
- Supón que pegas en la primera columna (por ejemplo, columna C) y que quieres que:
  - En esa columna use N2:N9.
  - A la derecha, use O2:O9, luego P2:P9, etc. (o M, O, … ajusta el desplazamiento).
- Usa INDICE con DESREF o directamente DESREF sobre N2:N9 y desplaza por el número de columnas copiadas.

Ejemplo base (para la primera fórmula):
- Rango base: $N$2:$N$9
- Desplazamiento horizontal: COLUMNAS($C:C)-1 si pegas primero en C; ajusta a tu columna real.

Fórmula que cambia N→O→P al copiar a la derecha y mantiene filas al copiar hacia abajo:
=SI(CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); B12)>1; INDICE($N:$N;10); "")
Notas:
- DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1) empieza en N2:N9 y se mueve 0 filas y (n-1) columnas a la derecha cuando copias a la derecha.
- B12 no lleva $ para que al arrastrar hacia abajo cambie a B13, B14, etc.
- INDICE($N:$N;10) devuelve N10. Si quieres que también cambie de N a O al copiar a la derecha, usa DESREF para N10 igual que para el rango:
  DESREF($N$10;0;COLUMNAS($C:C)-1)

Entonces la versión completa que también mueve la celda de resultado:
=SI(CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); B12)>1; DESREF($N$10;0;COLUMNAS($C:C)-1); "")

Para la segunda fórmula (con A y B):
=SI(Y(CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); A19)>0; CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); B19)>0); DESREF($N$10;0;COLUMNAS($C:C)-1); "")

Para la tercera fórmula:
=SI(CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); B124)>0; DESREF($N$10;0;COLUMNAS($C:C)-1); "")

Cómo usar:
1) Pega la fórmula en la primera columna donde quieras empezar (ajusta $C:C a tu columna inicial).
2) Arrastra hacia abajo: A/B/Bx cambian de fila; los rangos 2:9 y 10 quedan fijos en filas.
3) Copia hacia la derecha: el DESREF moverá N→O→P… y también N10→O10→P10.

Si en vez de N→O→P necesitas M→N→O (empezar en M), cambia el offset:
- Usa COLUMNAS($B:C)-1 si la primera columna de pegado es C pero quieres que el desplazamiento empiece ya en +1 (es decir, M cuando offset = -1). Más claro es anclar una columna “origen”:
  DESREF($M$2:$M$9;0;COLUMNAS($C:C)-1)
  y
  DESREF($M$10;0;COLUMNAS($C:C)-1)
Así la primera columna usa M; a la derecha será N, luego O, etc.

Alternativa sin DESREF (más “segura” por volatilidad) usando INDICE:
- Rango variable 2:9:
  INDICE($N:$Z; FILA($2:$9); COINCIDIR(COLUMNAS($C:C)+COLUMNA($N:$N)-COLUMNA($N:$N); COLUMNA($N:$Z); 0))
Esto es más enrevesado; en la práctica DESREF es suficiente y más legible.

Consejo final:
- Evita $ en la letra de A y B si quieres que cambien de fila al arrastrar.
- Usa $ en los números 2:9 y 10 para fijar esas filas.
- Controla el cambio de N→O→P con DESREF y COLUMNAS ancladas a la primera columna de pegado.

Si me indicas:
- En qué columna empiezas a pegar,
- Si quieres iniciar en M o en N,
- Y el patrón exacto de columnas,
te devuelvo las tres fórmulas ya ajustadas listas para copiar-pegar.


Para empezar debo pegar esto:
=SI(CONTAR.SI(DESREF($N$2:$N$9;0;COLUMNAS($C:C)-1); B12)>1; DESREF($N$10;0;COLUMNAS($C:C)-1); "")

Nah, está muy raro.

A ver, vamos paso a paso.
En C12 tengo: =SI(CONTAR.SI($C$2:$C$9;B12)>1; $C$10; "")
En C13: =SI(CONTAR.SI($C$2:$C$9;B13)>1; $C$10; "")
O sea, cambia el número al lado de B, está bien.

En D12 tengo: =SI(CONTAR.SI($D$2:$D$9;B12)>1; $D$10; "")
ven que, todo C cambió a D.

Entonces, supongamos que sólo quisiera que cambie la última letra. Que el 10 se mantenga, pèro que cuando arrastro la fórmula a otra columna, C cambie a la columna en cuestión.

¿Cómo se hace? Eso para empezar, el resto lo intentaré entender luego.

Fórmula original:
=SI(CONTAR.SI($C$2:$C$9;B12)>1; $C$10; "")
GPT dijo:
=SI(CONTAR.SI($C$2:$C$9;$B$12)>1; DESREF($C$10; 0; COLUMNA()-COLUMNA($C$10)); "")
puso $ en B porque le dije. No entiendo esto:
DESREF($C$10; 0; COLUMNA()-COLUMNA($C$10))
y no tengo más puntos, pregunto a Deepseek.

En cierto punto le planteé el problema desde 0 y me dijo:
¡Entiendo perfectamente! Es un escenario muy común. Necesitas **fijar la fila (10)** pero **dejar la columna relativa** para que se ajuste al arrastrar. La solución es correcta y simple usando **referencias mixtas**.

### Solución Correcta y Simplificada:

**`=SI(CONTAR.SI($C$2:$C$9; $B$12)>1; C$10; "")`**

---

### 🔐 Explicación de la Referencia Mixta: `C$10`

*   **`C`** (sin `$`): La **columna es relativa**. Se ajustará automáticamente al arrastrar la fórmula a la derecha o izquierda (se convertirá en D, E, F...).
*   **`$10`** (con `$`): La **fila es absoluta**. No cambiará nunca, sin importar si arrastras la fórmula hacia arriba o hacia abajo. El número **10 se mantendrá fijo**.

### 📍 Comportamiento al Arrastrar:

| Si la fórmula está en: | La referencia se convierte en: | Resultado |
| :--- | :--- | :--- |
| **Celda C15** | `C$10` | Valor de **C10** |
| **Celda D15** | `D$10` | Valor de **D10** |
| **Celda E20** | `E$10` | Valor de **E10** |
| **Celda F5** | `F$10` | Valor de **F10** |

### ✅ Por qué esta es la mejor solución:

1.  **Muy Simple:** Solo usas una referencia de celda normal (`C$10`) en lugar de una función compleja.
2.  **Más Fácil de Entender:** Cualquiera que vea la fórmula sabe instantáneamente que apunta a la fila 10.
3.  **Más Eficiente:** Excel calcula referencias directas mucho más rápido que funciones como `DESREF` o `INDIRECTO`.
4.  **Cumple tu Requisito:** La fila 10 nunca cambia, la columna sí se ajusta.

**En resumen:** Reemplaza el `DESREF` complejo por la referencia mixta **`C$10`**.

Tu fórmula final, optimizada y fácil de leer, queda así:
```excel
=SI(CONTAR.SI($C$2:$C$9; $B$12)>1; C$10; "")
```

Puede que ya me hayan dicho eso y yo lo haya olvidado, de momento no puedo probarlo, luego sigo.
5  Programación / Programación General / Excel 2013 indicar celda "contigua" al 2ndo máximo valor, repetible. en: 23 Agosto 2025, 03:50 am
Tengo unas celdas así:

y otras así:


Quiero que en las que puse 1ero aparezca, en una lo de fondo rojo que tenga mejor promedio, y en la otra lo de fondo rojo que tenga el 2ndo mejor promedio, pudiendo ser igual, o sea, el 2ndo máximo que encuentre.

Le dije a GPT el problema:
esto
=INDICE(B131:B138; COINCIDIR(MAX(L131:L138); L131:L138; 0))
y esto
=INDICE(B131:B138; COINCIDIR(K.ESIMO.MAYOR(L131:L138;2); L131:L138; 0))
me están dando el mismo resultado, no debería ¿qué pasa?

Vean que en la 1er imagen los resultados son los mismos, pero el 2ndo debería ser Patada agachado.

Citar
Hay dos escenarios típicos en los que ambas fórmulas pueden devolver lo mismo:

1) El 2.º mayor “con repetidos” es igual al máximo 
   - Si en L131:L138 hay al menos dos celdas con el valor máximo, entonces:
     - MAX(L131:L138) = 19 (por ejemplo)
     - K.ESIMO.MAYOR(L131:L138;2) también = 19
   - En ese caso, ambas COINCIDIR buscan 19 y, por diseño, COINCIDIR(...;0) devuelve la primera aparición del valor en el rango. Resultado: mismas filas, mismo INDICE.

2) Datos no numéricos/formato o espacios influyen en el cálculo 
   - Si hay textos que parecen números, errores, celdas vacías con espacios, etc., pueden afectar a K.ESIMO.MAYOR/ MAX o a COINCIDIR. Pero lo habitual es el caso 1.

Cómo obtener el “segundo mayor distinto” (sin repetir el máximo):
- Fórmula matricial en Excel 2013 (confirmar con Ctrl+Shift+Enter):
  =INDICE(B131:B138; COINCIDIR(MAX(SI(L131:L138<MAX(L131:L138); L131:L138)); L131:L138; 0))

- Alternativa separando el valor y luego buscando:
  1) En una celda auxiliar: =MAX(SI(L131:L138<MAX(L131:L138); L131:L138))  Confirmar con Ctrl+Shift+Enter.
  2) Luego: =INDICE(B131:B138; COINCIDIR(celda_aux; L131:L138; 0))

Si lo que quieres es “segundo con repetidos” pero devolver la segunda ocurrencia del mismo máximo, COINCIDIR por sí sola no devuelve la segunda coincidencia. Puedes usar una clave auxiliar (por ejemplo, agregar un pequeño ajuste por fila) o una fórmula que ubique la n‑ésima aparición. Por ejemplo, para devolver la fila de la 2.ª aparición del máximo:

- Fórmula matricial para la posición de la 2.ª coincidencia:
  =PESTAÑA(FILA(L131:L138)-MIN(FILA(L131:L138))+1; 2; SI(L131:L138=MAX(L131:L138); FILA(L131:L138)-MIN(FILA(L131:L138))+1))
  Luego úsala dentro de INDICE. Si prefieres, te la adapto completa a tu rango y separadores.

Creo que entiendo el problema "por diseño, COINCIDIR(...;0) devuelve la primera aparición del valor en el rango"
pero las soluciones me parecen bastante raras, aunque le pedí una más simple ¿se les ocurre?

Básicamente es:
- Buscar 2ndo máximo valor en un rango.
- Anotar en qué celda está.
- Restar columnas a esa posición.
6  Foros Generales / Dudas Generales / ¿Cómo pedir a Youtube que no me recomiende un canal? en: 19 Agosto 2025, 16:00 pm
Estás viendo un video, quieres que no te aparezcan más de ese canal.

Si te aparecen en la lista de recomendados, puedes hacer clic en los 3 puntitos y poner la opción ahí.

¿Y si no te aparecen? ¿si sólo viste 1? No sé... Cuando te aparezcan de nuevo los bloqueas, tendrás que hacer una lista de los que quieres bloquear o memorizarlos, pero parece medio tedioso...

Otro método es que cuando vas a ver un video de un canal sospechosamente malo, lo abras en una nueva pestaña, así tienes en la otra el video en la lista y la opción de bloquearlo, pero esto tampoco está bueno, porque en mi caso se pone lento, y si pasa mucho tiempo la pestaña anterior se recarga, los recomendados cambian y ya no puedo bloquearlo. Además no todos los videos son sospechosamente malos, yo que sé, uno me dice "A sus 90 años, X revela lo que le pasó en..." y luego es el youtuber contando la biografía de esa persona, no habla la persona que crei que iba a hablar (parece) y tiene más relleno que Naruto, yo que iba a saber.

¿No se puede entrar al jodido canal y poner ahí no recomendarmelo? Que yo sepa no...

¿Habrá algún código que se le pueda enviar a YT? ¿algún javascript? ¿o sí hay una forma fácil de bloquear que no conozco?
7  Programación / Programación General / Posible aporte: Código para jugar bien Signos en línea, aún no probado. en: 18 Agosto 2025, 04:17 am
Se refiere al 3 en raya pero con la configuración que se ponga: En vez de 3 puede ser otro número y en vez de un tablero de 3*3 puede ser otro número independiente del anterior. Lo pensé para tableros cuadrados, pero quizá funcione para rectangulares. De momento está configurado para revisar sólo rayas horizontales, pero basta quitar un par de rayas // para que revise todas las posibilidades, es sólo que para pruebas me pareció mejor así.
Aún no lo probé, acabo de terminarlo, llevo bastante tiempo con esto... Disfrútenlo, analícenlo si quieren a ver qué tal:
Código
  1. // Signos en línea en tableros cuadrados:
  2. // Este programa tiene básicamente 3 etapas,
  3. // que se pueden resumir así:
  4. // Nota: La situación inicial, en que hay 0 signos colocados,
  5. // estará guardada en la lista nro 0.      
  6. // 1:
  7. // Probar acciones en cada situación de la lista nro 0,
  8. // guardando en una nueva lista las nuevas situaciones (que no...
  9. // sean victoria ni empate). Repetir con cada nueva lista hasta...
  10. // la que tenga situaciones en que sólo 1 acción es posible
  11. // (por ejemplo en el 3 en línea es la 8).
  12. // 2:
  13. // Probar acciones en cada situación de la última lista,
  14. // guardando datos sobre las consecuencias (victoria o empate)
  15. // de realizar la única acción posible.
  16. // 3:
  17. // En las situaciones no resueltas, empezando por las...
  18. // penúltimas listas, probar las acciones.
  19. // Guardar cuántas acciones causan victoria de uno, de otro y...
  20. // de empate. Averiguar la mejor acción en cada situación,
  21. // basado en el mejor resultado seguro que causa (asumiendo...
  22. // que el rival juega bien), y en 2nda instancia el más probable
  23. // (asumiendo que el rival juegue al azar).
  24. // Repetir hasta resolver la lista 0.
  25. JuntosRequeridos = 2;
  26. CasillerosPorFila = 2;
  27. // Contando desde 0:
  28. MaxColumna = CasillerosPorFila-1;
  29. Casilleros = CasillerosPorFila*CasillerosPorFila;
  30. // Están numerados así:
  31. // 0 1
  32. // 2 3
  33. MaxCasillero = Casilleros-1;
  34. // En las listas L_SaE se irán poniendo las situaciones a...
  35. // experimentar que tengan _ signos colocados.
  36. // En la lista 0 se agregará una situación:
  37. L0SaE1 = [];
  38. // A continuación se especifica cual, agregando v
  39. // (que significa vacío) en lo que serían los casilleros,
  40. // los elementos del array:
  41. ValoraAgregar = -1;
  42. do {
  43. ValoraAgregar++;
  44. L0SaE1.push("v");
  45. } while (ValoraAgregar < MaxCasillero);
  46. delete ValoraAgregar;
  47. // Los datos de las situaciones no están en las listas,
  48. // se crean aparte. Con esta variable se evita repetidamente...
  49. // convertir en texto y concatenar:
  50. S_ = "S"+(L0SaE1.join(""));
  51. // Datos de la situación:
  52. // Usada para fácilmente saber de qué signo es turno:
  53. set (S_+"Turno", "X");
  54. // En otros casos usada para evitar probar acciones...
  55. // innecesarias y con LastAPosible para saber si sólo queda 1:
  56. set (S_+"FirstAPosible", 0);
  57. set (S_+"LastAPosible", MaxCasillero);
  58. NroDeListaRevisandose = -1;
  59. // Última lista que se revisará en la etapa 1:
  60. // LastListaDeEt1 = Casilleros;
  61. // /////////////////////////////////////////////
  62. // /////////////////  Etapa 1  /////////////////
  63. // /////////////////////////////////////////////
  64. // Consiste en llegar a nuevas situaciones y guardarlas,
  65. // si no son victoria. Termina antes de que pueda haber empates.
  66. //
  67. // Usada a continuación y durante la etapa 1 (Et1)...
  68. // cuando no hay más situaciones en la lista revisándose:
  69. function BuscarOtraListaEt1 () {
  70. trace("Ejecutando BuscarOtraListaEt1");
  71. NroDeListaRevisandose++;
  72. PrepararUsoDeLista();
  73. PrepararSaE();
  74. // Si las situaciones de la lista tienen más de 1 opción:
  75. if (NroDeListaRevisandose < MaxCasillero) {
  76. // Para evitar concatenar cosas al guardar datos de situaciones nuevas:
  77. NextL_SaE = "L"+(NroDeListaRevisandose+1)+"SaE";
  78. trace("NextL_SaE: "+NextL_SaE);
  79. // Usado en EvaluarConocimientoSobreSEt1 para...
  80. // nombrar las situaciones nuevas que se logren:
  81. SituacionesNuevas = 0;
  82. } else {
  83. trace( "La lista actual tiene situaciones de sólo 1 opción; inicia la etapa 2.");
  84. // Iniciar Etapa 2:
  85. gotoAndStop(3);
  86. }
  87. }
  88. BuscarOtraListaEt1();
  89. // Usada cuando se cambia de lista, en BuscarOtraListaEt1,
  90. // al comenzar Et2 y en Et3:
  91. function PrepararUsoDeLista () {
  92. trace("Ejecutando PrepararUsoDeLista");
  93. // Para evitar concatenar repetidamente:
  94. L_SaE = "L"+NroDeListaRevisandose+"SaE";
  95. trace("L_SaE: "+L_SaE);
  96. NroDeSExperimentandose = 1;
  97. // También para evitar concatenar repetidamente:
  98. // L_SaE_ = L_SaE+NroDeSExperimentandose;
  99. L_SaE_ = L_SaE+"1";
  100. trace("L_SaE_: "+L_SaE_);
  101. trace("Comienzan experimentos en una nueva lista, la "+NroDeListaRevisandose);
  102. }
  103. // Usada cuando se elige una SaE, en BuscarOtraListaEt1,
  104. // BuscarOtraSituacionEt1, BuscarOtraSituacionEt2 y PrepararSaEEt3:
  105. function PrepararSaE () {
  106. trace("Ejecutando PrepararSaE");
  107. trace("Se inician experimentos en otra situación de la lista, la nro "+NroDeSExperimentandose);
  108. SituacionBase = eval(L_SaE_).slice();
  109. S_ = "S"+(SituacionBase.join(""));
  110. Turno = eval(S_+"Turno");
  111. FirstActionPosible = eval(S_+"FirstAPosible");
  112. LastActionPosible = eval(S_+"LastAPosible");
  113. Action = FirstActionPosible;
  114. }
  115. // Usada en frame 2 (o etapa 1) repetidamente:
  116. function ResetearSituacionEt1 () {
  117. // Plantear situación porque puede modificarse pero...
  118. // podría requerirse su estado original luego:
  119. Situacion = SituacionBase.slice();
  120. trace("La situación experimentándose es "+Situacion);
  121. EvaluarAplicabilidadEt1();
  122. }
  123. // Usada luego de que cambia la SaE y/o la acción, en Et1:
  124. function EvaluarAplicabilidadEt1 () {
  125. trace("Ejecutando EvaluarAplicabilidadEt1");
  126. if (Situacion[Action] == "v") {
  127. trace("La acción "+Action+" es realizable.");
  128. AplicarAccionEt1();
  129. } else {
  130. trace("La acción "+Action+" no es realizable.");
  131. SinResetBuscarOtraAccionEt1();
  132. }
  133. }
  134. // Usada luego de EvaluarAplicabilidadEt1,
  135. // si una acción es realizable:
  136. function AplicarAccionEt1 () {
  137. trace("Ejecutando AplicarAccionEt1");
  138. Situacion[Action] = Turno;
  139. trace("Se realizó la acción "+Action+"; ahora la situación es "+Situacion);
  140. // ¿Ganó?
  141. // Si no se detecta victoria vertical,
  142. // revisa de otros modos (ver las funciones Chequear):
  143. ChequearVertical();
  144. if (Win == "No") {
  145. EvaluarConocimientoSobreSEt1();
  146. }
  147. // ¿Queda alguna acción sin probar en la situación?
  148. BuscarOtraAccionEt1();
  149. }
  150. // Usada en EvaluarAplicabilidadEt1 cuando una acción no es...
  151. // realizable:
  152. function SinResetBuscarOtraAccionEt1 () {
  153. trace("Ejecutando SinResetBuscarOtraAccionEt1");
  154. if (Action < LastActionPosible) {
  155. // Si queda alguna acción sin probar...
  156. // en la situación, probarla:
  157. Action++;
  158. EvaluarAplicabilidadEt1();
  159. } else {
  160. trace("No hay más acciones realizables.");
  161. BuscarOtraSituacionEt1();
  162. }
  163. }
  164. // Usada luego de AplicarAccionEt1:
  165. function BuscarOtraAccionEt1 () {
  166. trace("Ejecutando BuscarOtraAccionEt1");
  167. if (Action < LastActionPosible) {
  168. // Si queda alguna acción sin probar...
  169. // en la situación, probarla:
  170. Action++;
  171. // Se ejecutará ResetearSituacionEt1.
  172. } else {
  173. trace("No hay más acciones realizables.");
  174. BuscarOtraSituacionEt1();
  175. }
  176. }
  177. // Usada en AplicarAccionEt1 cuando no hay victoria (ni empate,
  178. // aunque por ahora no ocurren):
  179. function EvaluarConocimientoSobreSEt1 () {
  180. trace("Ejecutando EvaluarConocimientoSobreSEt1");
  181. // Estas 3 variables son para evitar reconcatenar:
  182. SituacionJoined = Situacion.join("");
  183. NewS_ = "S"+SituacionJoined;
  184. NewS_BestAction = NewS_+"BestAction";
  185. // ¿Se ha llegado antes a la situación?
  186. if (eval(NewS_BestAction) == undefined) {
  187. // No, anotar que debe investigarse:
  188. SituacionesNuevas++;
  189. // Copiar array (porque no se puede normalmente):
  190. trace("Situación a copiar a "+NextL_SaE+SituacionesNuevas+" es "+Situacion);
  191. set (NextL_SaE+SituacionesNuevas, Situacion.slice());
  192. trace("Esa situación no está anotada; se anota como nro "+SituacionesNuevas);
  193. set(NewS_BestAction, "Desconocida");
  194. if (Turno == "X") {
  195. set (NewS_+"Turno", "0");
  196. } else {
  197. set (NewS_+"Turno", "X");
  198. }
  199. // Averiguar cual es su 1er acción posible:
  200. AccionRevisandose = -1;
  201. do {
  202. AccionRevisandose++;
  203. if (Situacion[AccionRevisandose] == "v") {
  204. set (NewS_+"FirstAPosible", AccionRevisandose);
  205. break;
  206. }
  207. } while (true);
  208. // Averiguar cual es su última acción posible:
  209. AccionRevisandose = Casilleros;
  210. do {
  211. AccionRevisandose--;
  212. if (Situacion[AccionRevisandose] == "v") {
  213. set (NewS_+"LastAPosible", AccionRevisandose);
  214. break;
  215. }
  216. } while (true);
  217. }
  218. }
  219. // Usada en BuscarOtraAccionEt1 cuando no hay más acciones posibles,
  220. // y en SinResetBuscarOtraAccionEt1:
  221. function BuscarOtraSituacionEt1 () {
  222. trace("Ejecutando BuscarOtraSituacionEt1");
  223. NroDeSExperimentandose++;
  224. if (eval(L_SaE+NroDeSExperimentandose) != undefined) {
  225. // Hay otra situación en la lista,
  226. // prepararse a usarla:
  227. L_SaE_ = L_SaE+NroDeSExperimentandose;
  228. PrepararSaE();
  229. } else {
  230. trace("No hay más situaciones a experimentar en la lista actual, se mirará otra.");
  231. BuscarOtraListaEt1();
  232. }
  233. }
  234. // /////////////////////////////////////////////
  235. // /////////////////  Etapa 2  /////////////////
  236. // /////////////////////////////////////////////
  237. // Consiste en guardar el resultado de las situaciones en que...
  238. // sólo 1 acción es posible. Puede ser victoria o empate.
  239. //
  240. // Usada en frame 3 (o etapa 2) repetidamente:
  241. function ResetearSituacionEt2 () {
  242. // Plantear situación porque puede modificarse pero...
  243. // podría requerirse su estado original luego:
  244. Situacion = SituacionBase.slice();
  245. trace("La situación experimentándose es "+Situacion);
  246. AplicarAccionEt2();
  247. }
  248. // Usada luego de ResetearSituacionEt2, parece innecesario que sea función:
  249. function AplicarAccionEt2 () {
  250. trace("Ejecutando AplicarAccionEt2");
  251. Situacion[Action] = Turno;
  252. trace("Se realizó la acción "+Action+"; ahora la situación es "+Situacion);
  253. // ¿Ganó?
  254. // Si no se detecta victoria vertical,
  255. // revisa de otros modos (ver las funciones Chequear):
  256. ChequearVertical();
  257. set(S_+"BestAction", Action);
  258. if (Win == "Sí") {
  259. trace("Victoria conseguida, guardando datos.");
  260. if (Turno == "X") {
  261. // Estas son las chances de que gane...
  262. // X, 0 o que haya empate:
  263. set(S_+"VictoriasDeX", 1);
  264. set(S_+"VictoriasDe0", 0);
  265. set(S_+"ResultadoEsperado", "X");
  266. } else {
  267. set(S_+"VictoriasDeX", 0);
  268. set(S_+"VictoriasDe0", 1);
  269. set(S_+"ResultadoEsperado", "0");
  270. }
  271. set(S_+"DistanciaaGanar", 1);
  272. set(S_+"Empates", 0);
  273. } else {
  274. trace("Empate conseguido, guardando datos.");
  275. set(S_+"VictoriasDeX", 0);
  276. set(S_+"VictoriasDe0", 0);
  277. set(S_+"Empates", 1);
  278. set(S_+"ResultadoEsperado", "E");
  279. }
  280. // ¿Queda alguna situación en la lista experimentándose?
  281. BuscarOtraSituacionEt2();
  282. }
  283. // Usada luego de AplicarAccionEt2, parece innecesario que sea función:
  284. function BuscarOtraSituacionEt2 () {
  285. trace("Ejecutando BuscarOtraSituacionEt2");
  286. NroDeSExperimentandose++;
  287. if (eval(L_SaE+NroDeSExperimentandose) != undefined) {
  288. // Hay otra situación en la lista,
  289. // prepararse a usarla:
  290. L_SaE_ = L_SaE+NroDeSExperimentandose;
  291. PrepararSaE();
  292. } else {
  293. trace("No hay más situaciones a experimentar en la lista actual, inicia la etapa 3.");
  294. BuscarOtraListaEt3();
  295. gotoAndStop(4);
  296. }
  297. }
  298. // /////////////////////////////////////////////
  299. // /////////////////  Etapa 3  /////////////////
  300. // /////////////////////////////////////////////
  301. // Consiste en guardar los resultados de las acciones en...
  302. // situaciones en que más de 1 acción es posible.
  303. // Particularmente se guarda la mejor acción.
  304. // El resultado de las acciones puede ser victoria,
  305. // una situación con posibles resultados,
  306. // y en la penúltima lista una situación con un único posible...
  307. // resultado.
  308. //
  309. // Usada antes y durante esta etapa...
  310. // cuando no hay más situaciones en la lista revisándose:
  311. function BuscarOtraListaEt3 () {
  312. trace("Ejecutando BuscarOtraListaEt3");
  313. NroDeListaRevisandose--;
  314. if (NroDeListaRevisandose > -1) {
  315. // Si se halla una lista:
  316. PrepararUsoDeLista();
  317. PrepararSaEEt3();
  318. } else {
  319. trace("No hay más listas a revisar; programa terminado.");
  320. // En este frame nada hay, es sólo para mostrar el mensaje:
  321. gotoAndStop(5);
  322. }
  323. }
  324. // Casi como PrepararSaE. Usada cuando se elige una SaE,
  325. // en BuscarOtraListaEt3 y BuscarOtraSituacionEt3:
  326. function PrepararSaEEt3 () {
  327. trace("Ejecutando PrepararSaEEt3");
  328. PrepararSaE();
  329. // Para evitar evals y concatenaciones repetidamente:
  330. BestAction = "";
  331. VictoriasDeX = 0;
  332. VictoriasDe0 = 0;
  333. Empates = 0;
  334. // Establecer que hasta ahora los resultados hallados...
  335. // son peores que lo posible, para que se sustituyan por...
  336. // cualquier acción:
  337. if (Turno == "X") {
  338. // La E antes de Obtenido es Esperado:
  339. BestResultadoEObtenido = "0";
  340. } else {
  341. BestResultadoEObtenido = "X";
  342. }
  343. // Si 2 acciones causan victoria segura,
  344. // esto sirve para elegir la mejor de ellas:
  345. BestDistanciaaGanar = Casilleros;
  346. // Si 2 acciones causan empate seguro,
  347. // esto sirve para elegir la mejor de ellas:
  348. BestChanceDeGanarEnE = -1;
  349. BestChanceDeEmpatarEnE = -1;
  350. // Si 2 acciones causan derrota segura,
  351. // esto sirve para elegir la mejor de ellas:
  352. LowestChanceDePerderEnD = -1;
  353. BestChanceDeGanarEnD = -1;
  354. }
  355. // Usada en frame 4 (o etapa 3) repetidamente:
  356. function ResetearSituacionEt3 () {
  357. // Plantear situación porque puede modificarse pero...
  358. // podría requerirse su estado original luego:
  359. Situacion = SituacionBase.slice();
  360. trace("La situación experimentándose es "+Situacion);
  361. EvaluarAplicabilidadEt3();
  362. }
  363. // Usada luego de que cambia la SaE y/o la acción, en Et3:
  364. function EvaluarAplicabilidadEt3 () {
  365. trace("Ejecutando EvaluarAplicabilidadEt3");
  366. if (Situacion[Action] == "v") {
  367. trace("La acción "+Action+" es realizable.");
  368. AplicarAccionEt3();
  369. } else {
  370. trace("La acción "+Action+" no es realizable.");
  371. SinResetBuscarOtraAccionEt3();
  372. }
  373. }
  374. // Usada luego de EvaluarAplicabilidadEt3,
  375. // si una acción es realizable:
  376. function AplicarAccionEt3 () {
  377. // Los datos se guardarán bien en GuardarDatosEt3.
  378. // Por ahora varios se están guardando en variables más simples de nombrar.
  379. // Además algunos no se pueden guardar aún (VictoriasDeX, NewVictoriasDe0...).
  380. // Y DistanciaaGanar se está guardando como -1 de lo que debe, para no tener que estar sumando.
  381. trace("Ejecutando AplicarAccionEt3");
  382. Situacion[Action] = Turno;
  383. trace("Se realizó la acción "+Action+"; ahora la situación es "+Situacion);
  384. // ¿Ganó?
  385. // Si no se detecta victoria vertical,
  386. // revisa de otros modos (ver las funciones Chequear):
  387. ChequearVertical();
  388. if (Win == "No") {
  389. // Agregar los posibles resultados de la...
  390. // situación obtenida:
  391. // Estas 5 variables son para evitar reconcatenar:
  392. SituacionJoined = Situacion.join("");
  393. NewS_ = "S"+SituacionJoined;
  394. NewVictoriasDeX = eval(NewS_+"VictoriasDeX");
  395. NewVictoriasDe0 = eval(NewS_+"VictoriasDe0");
  396. NewEmpates = eval(NewS_+"Empates");
  397. VictoriasDeX = VictoriasDeX+NewVictoriasDeX;
  398. VictoriasDe0 = VictoriasDe0+NewVictoriasDe0;
  399. Empates = Empates+NewEmpates;
  400. // Si en la SaE ya se halló una acción que...
  401. // causa victoria segura:
  402. if (BestResultadoEObtenido == Turn) {
  403. // Si la acción recién usada también causa eso:
  404. if (eval(NewS_+"ResultadoEsperado") == Turn) {
  405. // Si dicha acción la causa faster:
  406. if (eval(NewS_+"DistanciaaGanar") < BestDistanciaaGanar) {
  407. // Sustituir datos:
  408. BestDistanciaaGanar = eval(NewS_+"DistanciaaGanar");
  409. BestAction = Action;
  410. }
  411. // SINO SI LA CAUSA IGUAL DE RÁPIDO HABRÍA QUE AVERIGUAR CHANCES, pero se gana igual...
  412. // sino dicha acción es peor, no prestarle más atención.
  413. }
  414. // idem.
  415. // sino si el mejor resultado esperado hallado...
  416. // en esta SaE es empate:
  417. } else if (BestResultadoEObtenido == "E") {
  418. // Si la acción recién usada causa que...
  419. // el resultado esperado sea victoria:
  420. if (eval(NewS_+"ResultadoEsperado") == Turn) {
  421. // Sustituir datos:
  422. BestResultadoEObtenido = Turn;
  423. BestDistanciaaGanar = eval(NewS_+"DistanciaaGanar");
  424. BestAction = Action;
  425. // sino si es empate:
  426. } else if (eval(NewS_+"ResultadoEsperado") == "E") {
  427. // Averiguar chance de victoria:
  428. Posibilidades = NewVictoriasDeX+NewVictoriasDe0+NewEmpates;
  429. ChanceDeGanar = eval("NewVictoriasDe"+Turno)*100/Posibilidades;
  430. // Si es mejor que la hallada antes:
  431. if (ChanceDeGanar > BestChanceDeGanarEnE) {
  432. // Sustituir datos:
  433. BestChanceDeGanarEnE = ChanceDeGanar;
  434. BestChanceDeEmpatarEnE = NewEmpates*100/Posibilidades;
  435. BestAction = Action;
  436. // sino si la chance es igual:
  437. } else if (ChanceDeGanar == BestChanceDeGanarEnE) {
  438. // Averiguar chance de empate:
  439. ChanceDeEmpatar = NewEmpates*100/Posibilidades;
  440. // Si es mejor que la hallada antes:
  441. if (ChanceDeEmpatar > BestChanceDeEmpatarEnE) {
  442. // Sustituir datos:
  443. BestChanceDeGanarEnE = ChanceDeGanar;
  444. BestChanceDeEmpatarEnE = ChanceDeEmpatar;
  445. BestAction = Action;
  446. }
  447. }
  448. // SINO SI LAS CHANCES SON LAS MISMAS HABRÍA QUE DECIDIR SI SE PREFIERE LA QUE LO CAUSA MÁS RÁPIDO O NO.
  449. // sino dicha acción no es mejor, no prestarle más atención.
  450. // idem.
  451. }
  452. // El resultado esperado es derrota:
  453. } else {
  454. // Si la acción recién usada causa que...
  455. // el resultado esperado sea victoria:
  456. if (eval(NewS_+"ResultadoEsperado") == Turn) {
  457. // Sustituir datos:
  458. BestResultadoEObtenido = Turn;
  459. BestDistanciaaGanar = eval(NewS_+"DistanciaaGanar");
  460. BestAction = Action;
  461. // sino si es empate:
  462. } else if (eval(NewS_+"ResultadoEsperado") == "E") {
  463. // Averiguar chances y sustituir datos:
  464. Posibilidades = NewVictoriasDeX+NewVictoriasDe0+NewEmpates;
  465. BestChanceDeGanarEnE = eval("NewVictoriasDe"+Turno)*100/Posibilidades;
  466. BestChanceDeEmpatarEnE = NewEmpatesDeX*100/Posibilidades;
  467. BestResultadoEObtenido = "E";
  468. BestAction = Action;
  469. // sino es derrota:
  470. } else {
  471. // Averiguar chance de perder:
  472. Posibilidades = NewVictoriasDeX+NewVictoriasDe0+NewEmpates;
  473. ChanceDePerder = (Posibilidades-eval("NewVictoriasDe"+Turno)*100/Posibilidades;
  474. // Si es más baja (mejor) que la hallada antes:
  475. if (ChanceDePerder < LowestChanceDePerderEnD) {
  476. // Sustituir datos:
  477. LowestChanceDePerderEnD = ChanceDePerder;
  478. BestChanceDeGanarEnD = eval("NewVictoriasDe"+Turno)*100/Posibilidades;
  479. BestAction = Action;
  480. // sino si la chance es igual:
  481. } else if (ChanceDePerder == LowestChanceDePerderEnD) {
  482. // Averiguar chance de victoria:
  483. ChanceDeGanar = eval("NewVictoriasDe"+Turno)*100/Posibilidades;
  484. // Si es mejor que la hallada antes:
  485. if (ChanceDeGanar > BestChanceDeGanarEnD) {
  486. // Sustituir datos:
  487. LowestChanceDePerderEnD = ChanceDePerder;
  488. BestChanceDeGanarEnD = ChanceDeGanar;
  489. BestAction = Action;
  490. }
  491. }
  492. }
  493. }
  494. // sino la acción causa una victoria inmediata:
  495. } else {
  496. // Incrementar victorias:
  497. // Esta es para evitar reconcatenar:
  498. VariableaIncrementar = "VictoriasDe"+Turno;
  499. set (VariableaIncrementar, eval(VariableaIncrementar)+1);
  500. if (BestDistanciaaGanar > 0) {
  501. // Sustituir datos:
  502. BestResultadoEObtenido = Turn;
  503. BestDistanciaaGanar = 0;
  504. BestAction = Action;
  505. }
  506. }
  507. // ¿Queda alguna acción sin probar en la situación?
  508. BuscarOtraAccionEt3();
  509. }
  510. // Usada en EvaluarAplicabilidadEt3 cuando una acción no es...
  511. // realizable:
  512. function SinResetBuscarOtraAccionEt3 () {
  513. trace("Ejecutando SinResetBuscarOtraAccionEt3");
  514. if (Action < LastActionPosible) {
  515. // Si queda alguna acción sin probar...
  516. // en la situación, probarla:
  517. Action++;
  518. EvaluarAplicabilidadEt3();
  519. } else {
  520. trace("No hay más acciones realizables.");
  521. BuscarOtraSituacionEt3();
  522. }
  523. }
  524. // Usada luego de AplicarAccionEt3:
  525. function BuscarOtraAccionEt3 () {
  526. trace("Ejecutando BuscarOtraAccionEt3");
  527. if (Action < LastActionPosible) {
  528. // Si queda alguna acción sin probar...
  529. // en la situación, probarla:
  530. Action++;
  531. // Se ejecutará ResetearSituacionEt3.
  532. } else {
  533. trace("No hay más acciones realizables.");
  534. BuscarOtraSituacionEt3();
  535. }
  536. }
  537. // Usada cuando no hay más acciones posibles:
  538. function GuardarDatosEt3 () {
  539. trace("Ejecutando GuardarDatosEt3");
  540. set(S_+"VictoriasDeX", VictoriasDeX);
  541. set(S_+"VictoriasDe0", VictoriasDe0);
  542. set(S_+"Empates", Empates);
  543. set(S_+"BestAction", BestAction);
  544. set(S_+"DistanciaaGanar", BestDistanciaaGanar+1);
  545. set(S_+"ResultadoEsperado", BestResultadoEObtenido);
  546. }
  547. // Usada en BuscarOtraAccionEt3 cuando no hay más acciones posibles,
  548. // y en SinResetBuscarOtraAccionEt3:
  549. function BuscarOtraSituacionEt3 () {
  550. trace("Ejecutando BuscarOtraSituacionEt3");
  551. NroDeSExperimentandose++;
  552. if (eval(L_SaE+NroDeSExperimentandose) != undefined) {
  553. // Hay otra situación en la lista,
  554. // prepararse a usarla:
  555. L_SaE_ = L_SaE+NroDeSExperimentandose;
  556. PrepararSaEEt3();
  557. } else {
  558. trace("No hay más situaciones a experimentar en la lista actual, se mirará otra.");
  559. BuscarOtraListaEt3();
  560. }
  561. }
  562. // /////////////////////////////////////////////
  563. // /////////////////  Chequeos  ////////////////
  564. // /////////////////////////////////////////////
  565. // Usada en ChequeoHorizontal y requerida en otros casos:
  566. function ObtenerColumnayFilaDelMarcado () {
  567. FilaDelMarcado = Math.floor(Action/CasillerosPorFila);
  568. ColumnaDelMarcado = Action%CasillerosPorFila;
  569. }
  570. function ChequearVertical () {
  571. // trace ("Ejecutando ChequearVertical");
  572. //
  573. // SOLO FUNCIONA SI CasillerosPorFila >= JuntosRequeridos.
  574. //
  575. // Se revisará la vertical. Desde el casillero más arriba...
  576. // que pueda estar incluído en la línea,
  577. // hasta el casillero marcado. Si se halla alguno que no...
  578. // tenga la marca requerida, se repite el proceso mirando...
  579. // desde uno más abajo del fallado, y mirando ahora hasta...
  580. // más abajo, según corresponda:
  581. Desde = Action-CasillerosPorFila*(JuntosRequeridos-1);
  582. // Mientras el casillero no exista:
  583. while (Desde<0) {
  584. // trace ("Desde es "+Desde+", se aumentará");
  585. // Indicar que se empiece a mirar desde más abajo:
  586. Desde = Desde+CasillerosPorFila;
  587. }
  588. do {
  589. Hasta = Desde+CasillerosPorFila*(JuntosRequeridos-1);
  590. if (Hasta>MaxCasillero) {
  591. // Para ganar se necesitaría más casilleros hacia...
  592. // abajo de los que hay, terminar análisis:
  593. // trace ("No hay suficientes cuadraditos abajo");
  594. break;
  595. }
  596. Puntero = Desde;
  597. // trace ("Comenzando chequeo desde "+Desde+" hasta "+Hasta);
  598. // Puede cambiar:
  599. Win = "Sí";
  600. do {
  601. // trace ("Chequando el casillero "+Puntero);
  602. if (Situacion[Action] != Situacion[Puntero]) {
  603. Win = "No";
  604. Desde = Puntero+CasillerosPorFila;
  605. break;
  606. }
  607. Puntero = Puntero+CasillerosPorFila;
  608. } while (Puntero<=Hasta);
  609. } while (Desde<=Action && Win == "No");
  610. if (Win == "No") {
  611. // ChequearHorizontal();
  612. }
  613. }
  614. function ChequearHorizontal () {
  615. // trace ("Ejecutando ChequearHorizontal");
  616. // Es similar al chequeo vertical, pero aquí no sirve...
  617. // sumar o restar a un puntero que marque el casillero...
  618. // porque puede existir ese casillero pero no estar en...
  619. // un costado. En vez de eso, se obtiene su columna y...
  620. // fila, se modifica la columna si es posible,
  621. // y se calcula cual es el casillero a mirar:
  622. ObtenerColumnayFilaDelMarcado();
  623. DesdeColumna = ColumnaDelMarcado-JuntosRequeridos+1;
  624. // Para que no mire cuadraditos inexistentes en la izq:
  625. if (DesdeColumna<0) {
  626. DesdeColumna = 0;
  627. }
  628. do {
  629. HastaColumna = DesdeColumna+JuntosRequeridos-1;
  630. if (HastaColumna>MaxColumna) {
  631. // Para ganar se necesitaría más casilleros hacia...
  632. // la derecha de los que hay, terminar análisis:
  633. // trace ("No hay suficientes cuadraditos a la derecha");
  634. break;
  635. }
  636. Puntero = DesdeColumna;
  637. // trace ("Comenzando chequeo desde "+DesdeColumna+" hasta "+HastaColumna);
  638. // Puede cambiar:
  639. Win = "Sí";
  640. do {
  641. CasilleroaMirar = FilaDelMarcado*CasillerosPorFila+Puntero;
  642. // trace ("Chequando el casillero "+CasilleroaMirar);
  643. if (Situacion[Action] != Situacion[CasilleroaMirar]) {
  644. Win = "No";
  645. DesdeColumna = Puntero+1;
  646. break;
  647. }
  648. Puntero++;
  649. } while (Puntero<=HastaColumna);
  650. } while (DesdeColumna<=ColumnaDelMarcado && Win == "No");
  651. if (Win == "No") {
  652. ChequearDesdeUpIzq();
  653. }
  654. }
  655. // La diagonal así \
  656. function ChequearDesdeUpIzq () {
  657. // trace ("Ejecutando ChequearDesdeUpIzq");
  658. DesdeColumna = ColumnaDelMarcado-JuntosRequeridos+1;
  659. // trace("DesdeColumna: "+DesdeColumna);
  660. DesdeFila = FilaDelMarcado-JuntosRequeridos+1;
  661. // trace("DesdeFila: "+DesdeFila);
  662. // Para que no mire cuadraditos inexistentes:
  663. if (DesdeColumna<DesdeFila) {
  664. Sumar = DesdeColumna;
  665. } else {
  666. Sumar = DesdeFila;
  667. }
  668. // trace("Sumar: "+Sumar);
  669. if (Sumar<0) {
  670. // trace("Sumando.");
  671. DesdeColumna = DesdeColumna-Sumar;
  672. // trace("DesdeColumna: "+DesdeColumna);
  673. DesdeFila = DesdeFila-Sumar;
  674. // trace("DesdeFila: "+DesdeFila);
  675. }
  676. do {
  677. HastaColumna = DesdeColumna+JuntosRequeridos-1;
  678. if (HastaColumna>MaxColumna) {
  679. // Para ganar se necesitaría más casilleros hacia...
  680. // la derecha de los que hay, terminar análisis:
  681. // trace ("No hay suficientes cuadraditos a la derecha");
  682. break;
  683. }
  684. HastaFila = DesdeFila+JuntosRequeridos-1;
  685. // Sirve usar MaxColumna en vez de crear MaxFila...
  686. // porque como el tablero es cuadrado serían iguales:
  687. if (HastaFila>MaxColumna) {
  688. // Para ganar se necesitaría más casilleros hacia...
  689. // abajo de los que hay, terminar análisis:
  690. // trace ("No hay suficientes cuadraditos abajo");
  691. break;
  692. }
  693. PunteroDeColumna = DesdeColumna;
  694. PunteroDeFila = DesdeFila;
  695. // trace ("Comenzando chequeo desde columna "+DesdeColumna+" y fila "+DesdeFila);
  696. // trace ("hasta columna "+HastaColumna+" y fila "+HastaFila);
  697. // Puede cambiar:
  698. Win = "Sí";
  699. do {
  700. CasilleroaMirar = PunteroDeFila*CasillerosPorFila+PunteroDeColumna;
  701. // trace ("Chequando el casillero "+CasilleroaMirar);
  702. if (Situacion[Action] != Situacion[CasilleroaMirar]) {
  703. Win = "No";
  704. DesdeColumna = PunteroDeColumna+1;
  705. DesdeFila = PunteroDeFila+1;
  706. break;
  707. }
  708. PunteroDeColumna++;
  709. PunteroDeFila++;
  710. } while (PunteroDeColumna<=HastaColumna);
  711. } while (DesdeColumna<=ColumnaDelMarcado && Win == "No");
  712. if (Win == "No") {
  713. ChequearDesdeDownIzq();
  714. }
  715. }
  716. // La diagonal así /
  717. function ChequearDesdeDownIzq () {
  718. // trace ("Ejecutando ChequearDesdeDownIzq");
  719. DesdeColumna = ColumnaDelMarcado-JuntosRequeridos+1;
  720. // trace("DesdeColumna: "+DesdeColumna);
  721. DesdeFila = FilaDelMarcado+JuntosRequeridos-1;
  722. // trace("DesdeFila: "+DesdeFila);
  723. // Para que no mire cuadraditos inexistentes:
  724. ColumnasInexistentes = 0;
  725. if (DesdeColumna<0) {
  726. ColumnasInexistentes = DesdeColumna*-1;
  727. }
  728. FilasInexistentes = 0;
  729. // Está bien usar MaxColumna porque MaxFila sería igual:
  730. if (DesdeFila>MaxColumna) {
  731. FilasInexistentes = DesdeFila-MaxColumna;
  732. }
  733. if (ColumnasInexistentes>=FilasInexistentes) {
  734. Ajuste = ColumnasInexistentes;
  735. } else {
  736. Ajuste = FilasInexistentes;
  737. }
  738. // trace("Ajuste: "+Ajuste);
  739. if (Ajuste>0) {
  740. // trace("Ajustando.");
  741. DesdeColumna = DesdeColumna+Ajuste;
  742. // trace("DesdeColumna: "+DesdeColumna);
  743. DesdeFila = DesdeFila-Ajuste;
  744. // trace("DesdeFila: "+DesdeFila);
  745. }
  746. do {
  747. HastaColumna = DesdeColumna+JuntosRequeridos-1;
  748. if (HastaColumna>MaxColumna) {
  749. // Para ganar se necesitaría más casilleros hacia...
  750. // la derecha de los que hay, terminar análisis:
  751. // trace ("No hay suficientes cuadraditos a la derecha");
  752. break;
  753. }
  754. HastaFila = DesdeFila-JuntosRequeridos+1;
  755. if (HastaFila<0) {
  756. // Para ganar se necesitaría más casilleros hacia...
  757. // arriba de los que hay, terminar análisis:
  758. // trace ("No hay suficientes cuadraditos arriba");
  759. break;
  760. }
  761. PunteroDeColumna = DesdeColumna;
  762. PunteroDeFila = DesdeFila;
  763. // trace ("Comenzando chequeo desde columna "+DesdeColumna+" y fila "+DesdeFila);
  764. // trace ("hasta columna "+HastaColumna+" y fila "+HastaFila);
  765. // Puede cambiar:
  766. Win = "Sí";
  767. do {
  768. CasilleroaMirar = PunteroDeFila*CasillerosPorFila+PunteroDeColumna;
  769. // trace ("Chequando el casillero "+CasilleroaMirar);
  770. if (Situacion[Action] != Situacion[CasilleroaMirar]) {
  771. Win = "No";
  772. DesdeColumna = PunteroDeColumna+1;
  773. DesdeFila = PunteroDeFila-1;
  774. break;
  775. }
  776. PunteroDeColumna++;
  777. PunteroDeFila--;
  778. } while (PunteroDeColumna<=HastaColumna);
  779. } while (DesdeColumna<=ColumnaDelMarcado && Win == "No");
  780. // trace("Win: "+Win);
  781. }
8  Foros Generales / Sugerencias y dudas sobre el Foro / El foro cambia haya (con ll) por haya. en: 16 Agosto 2025, 15:35 pm
El 1ero se usa como sinónimo de "encuentra".

El 2ndo es como un pasado de haber.

https://www.rae.es/duda-linguistica/es-haya-o-haya

Hasta el nombre del link se cambia  :o

9  Programación / Programación General / Excel 2013 en un rango de celdas indicar en cual está el mínimo valor. en: 16 Agosto 2025, 15:28 pm
GPT me dijo:
=DIRECCION(FILA(D8)-1+COINCIDIR(MIN(D8:D22);D8:D22;0); COLUMNA(D8))
y funciona pero sólo entiendo lo que está en negrita, quisiera una alternativa o a ver si me lo pueden hacer entender.

(MIN(D8:D22):
haya el mínimo en ese rango de celdas.
(ll, el foro me cambia la palabra)

COINCIDIR(MIN(D8:D22);D8:D22;0):
Asumo que se lee como:
Buscar índice de (Valor; en el rango; coincidencia total)

¿ DIRECCION(qué fila; qué columna) ?

FILA(D8)-1:
No tengo mucha idea. Creo que le suma 7 al resultado de COINCIDIR, pero ahí dice -1, además pone una D no sé para qué.
Edit: Ya entendí esto, de D8 toma el 8, le resta 1, queda 7, y luego la fórmula dice +, así que ese 7 se suma...

Citar
Piensa en COINCIDIR como “posición dentro del rango”, no como “número de fila de la hoja”.

- Tu rango es D8:D22.
- COINCIDIR(MIN(D8:D22); D8:D22; 0) devuelve 1 si el mínimo está en D8, 2 si está en D9, 3 si está en D10, etc. Es una posición relativa al inicio del rango.

Para convertir esa posición en la fila real de la hoja, hay que “desplazarla” hasta la fila de inicio del rango.

- La fila real de D8 es 8.
- Si COINCIDIR devuelve 1 (está en la primera celda del rango), la fila real debe ser 8.
- Si devuelve 2 (segunda celda), la fila real debe ser 9.
- Si devuelve 3, la fila real debe ser 10, y así sucesivamente.

Fórmula del desplazamiento:
- FILA(D8) devuelve 8 (la fila donde empieza el rango).
- Si sumas la posición y restas 1: FILA(D8) + COINCIDIR(...) - 1
  - Caso posición 1: 8 + 1 - 1 = 8 → D8
  - Caso posición 2: 8 + 2 - 1 = 9 → D9
  - Caso posición 3: 8 + 3 - 1 = 10 → D10

Por eso verás escrito como:
- FILA(D8) - 1 + COINCIDIR(...)  (equivale a lo mismo que FILA(D8) + COINCIDIR(...) - 1)

Aplicado a tu fórmula completa (con punto y coma si tu Excel los usa):
- Dirección del mínimo:
  =DIRECCION(FILA(D8)+COINCIDIR(MIN(D8:D22);D8:D22;0)-1; COLUMNA(D8))

- Solo la fila del mínimo:
  =FILA(D8)+COINCIDIR(MIN(D8:D22);D8:D22;0)-1

Esto convierte la posición relativa (1, 2, 3, ...) en el número de fila real (8, 9, 10, ...).

COLUMNA(D8):
Idem. Si toma la columna del parámetro D8, sería más fácil simplemente poner D.

O sea, de D8 a D22 tengo unos datos, y en otra celda quiero que me diga en cual de esas celdas está el mínimo valor. No creo que sea tan complicado ¿GPT se lió?

Edit: Ya entendí más, pero hay como cosas innecesarias, que deberían ser más simples ¿se pueden simplificar?

Edit 2: Según probé se puede simplificar así:
=DIRECCION(7+COINCIDIR(MIN(D8:D22);D8:D22;0); COLUMNA(D8))
Faltaría la columna. Si siempre va a ser D...
10  Programación / Programación General / Elección al azar de punto de elipse o rectángulo. Misma probabilidad para cada punto. en: 14 Agosto 2025, 13:56 pm
Si elipse es muy complicado será rectángulo.

Quiero imitar una nube cambiando, más o menos. Circulos aparecerían detrás, crecerían y se achicarían hasta desaparecer. Hay un video que me gustó que más o menos hace eso pero no lo encuentro.

Entonces, tenemos una elipse de 200 de ancho y 100 de alto. Supongamos que está colocado en las coordenadas 0, 0. ¿Cómo los circulos podrían aparecer en cualquier parte del perímetro con igual probabilidad? No en el área.

Si es muy complicado, tenemos un rectángulo, digamos de la misma medida y lugar. Y misma pregunta.
Sobre este lo pensé y no supe. Puedo hacer que aparezca en el perímetro, pero con igual chance cada punto no sé.
Páginas: [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ... 52
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines