Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Serapis

#1931
Una imagen vectorial, es una imagen que se crea a base de órdenes gráficas, tipo: Rellenar el fondo de color azul, cambiar el color de pluma a blanco, dibujar un circulo de radio 23'6 con centro en las cordenads 45-120, dibujar una línea desde 20-80 hasta 40-135, rotar 10º en el eje x el rectángulo blablaba...

Esto permite que las imágenes se puedan rescalar manteniendo básicamente la misma calidad de las imágenes. Como son órdenes y no se guardan datos de píxeles, el tamaño del fichero es muy pequeño en comparación con una imagen que guarda la info del color de cada píxel, incluso aunque esté comprimido en jpg (por ejemplo).
La desventaja es que no es nada fácil hacer imágenes de cualquier tipo de esta forma. Para cosas como esquemas y así, en cambio es muy adecuado, porque son de la misma naturaleza.

Un proceso ideal, es que partiendo de una foto (por ejemplo), luego un programa fuere capaz de recrearla idénticamente usando precisamente órdenes gráficas, a base de leer la imagen e interpretar que orden o conjunto de ellas podrían emular tal o cual parte de la imagen... Esto está en pañales, aún.

Hay un montón de formatos gráficos de este tipo de imágenes. El formato que recomienda el W3C es el svg, y que casi todos (o todos) los navegadores web soportan a día de hoy (muy habitual en uso en wikipedia)...

https://www.w3.org/Graphics/SVG/
https://es.wikipedia.org/wiki/Gr%C3%A1ficos_vectoriales_escalables
https://www.w3.org/Graphics/SVG/WG/wiki/Secret_Origin_of_SVG
#1932
Foro Libre / Re: ¿Remedio gatuno?
13 Enero 2019, 19:44 PM
Cita de: warcry. en 12 Enero 2019, 23:40 PM
pues yo discrepo contigo @El_Andaluz, a mi con celo no se me ha escapado ninguna gata, que maulla y se restriega por toda la casa si, pero que le de por escaparse no, los gatos (masculino) si se escapan de casa con el celo, y sin el también, por eso de tener un territorio y poder pelearse con otros gatos y montar a las gatas de su territorio.
Completamente de acuerdo...

Una gata nunca se escapa de casa aunque tenga celo. Los machos sí... pueden pasar fuera solo unas horas o unos días, o puede no volver nunca, si algún capullo te lo mata, lo encierra o se mete en un sitio del que es fácil entrar pero no salir (suele ser el caso de casas abandonadas, con corrales, terrazas, etc...).
#1933
Java / Re: Grafos con listas de adyacencia
13 Enero 2019, 19:17 PM
Por cómo lo cuentas no queda claro:
1 - Si el ejercicio consiste en trasladar dichos datos a las listas y ya.
2 - O si el ejercicio auténtico ha de comenzar una vez pasados esos datos a las listas para luego operar con ellos. Es decir en este caso resulta pueril, obtener la lista de nodos únicos, pués se hace a mano todo.

La lista única de elementos será:
---> Madrid, Valencia, Alicante, Zaragoza, Barcelona Huesca
Permíteme ahorrar tecleo, sustituyendo el nombre de la ciudad por su inicial (pués no hay repes):
Lista única: MVAZBH

La forma de describir las relaciones, sería así:
   M = V|Z  
Es decir Desde Madrid puede irse por igual a Valencia que a Zaragoza, (son opciones).
Una ciudad a la que se accede desde varios puntos, aparecerá más de una vez a la derecha del '=', es el caso de Zaragoza:
   M = Z
   H = Z
Una ciudad a la que no se accede desde ninguna parte, solo aparecerá a la izquierda, por ejemplo Madrid y Huesca.
Técnicamente en teoría de compiladores, solo una producción es la raíz, el resto de producciones así se las llama 'muertas'.
Todos los términos que solo aparecen a la derecha (nunca llevan a otro nodo), se llaman terminales.
Todas las producciones que describen este grafo sería:
   M = V|Z
   V = A
   A = ""   // nulo
   Z = B
   B = ""  // nulo
   H = Z
...ahora bien si introducimos el concepto de lista, entonces (esas producciones, ciudades a) las que no se accede desde ninguna parte, son miembros-términos de lista, supongmaos que lista lo representamos como 'L', entonces la raíz será:
   L = M|H
Es decir, a Madrid y Huesca se accede desde Lista...
Como es la raíz, conviene ponerla encima del resto.
Así finalmente esta sería la lista de listas.
   L = M|H
   M = V|Z
   V = A
   A = ""   // nulo
   Z = B
   B = ""  // nulo
   H = Z

Una lista siempre se compone de elementos, ítems, nodos da igual como los quieras llamar...
El caso es que como (sucede en los grafos) cada elemento es a su vez una lista...
Se debe crear una clase lista, y estos podrían ser sus miembros:
Nombre (ejemplo): "Lista", "Madrid", Huesca
Siguiente: la/las listas a la que se accede desde él. Como pueden ser más de una ciudad, esto en efecto en vez de ser un nodo es una lista.
Padre: Nodo que dirige hacia él. Si cabe la posibilidad que más de un nodo apunte a él, también debe ser una lista, en vez de un nodo.
Estos miembros serán útiles para su recorrido.

Sin embargo como tenemos aún un valor más que consignar y no es único (la distancia), es conveniente que cada lista contenga a su vez un nodo y sea éste el que accede a la lista (es decir Siguiente será una instancia de nodo).

Clase Nodo:
Origen: Una referencia a la lista (la ciudad) en la que está.
Destino: Una referencia a la lista (la ciudad) a la que se llega.
Valor, distancia, tiempo: el dato a consignar, por ejemplo 300.

Entonces la lista (L = M|H), tendrá dos nodos.

Lista L = CrearLista("Lista")


Lista = funcion CrearLista(string Nombre)
   lista Ls = nueva Lista
   Ls.Nombre = Nombre

   devolver Ls
fin funcion



n = CrearNodo( "Lista", "Madrid", 0)
L.add(n)

n= CrearNodo(Lista, Huesca, 0)
L.Add(n)

// Nota: origen es obligado que exista ya. Destino puede o no existir.
nodo = Funcion CrearNodo(Lista Origen, Lista Destino, string sDestino, entero Valor)
   Si Destino = null luego
       Destino = CrearLista(sDestino)
   Fin si
   n = nuevo nodo
   n.Origen = Origen
   n.destino = Destino
   n.Valor = valor

   devolver n
fin funcion


He dejado para el final, el pegamento que une todo, la función general que se invoca.
Pero antes de ello, es preciso darse cuenta que la lista de producciones, aunque es completa y correcta, no contiene los valores, así que modificamos las produciones d ela siguiente manera:
Z = B-300
Es decir señala que desde Zaragoza se accede a Barcelona con una distancia de 300.
Ahora modificamos todas las producciones para canonizarlas de dicha manera:
   L = M-0|H-0
   M = V-300|Z-300
   V = A-200
   A = "-0"   // nulo y distancia 0
   Z = B-300
   B = "-0"  // nulo
   H = Z-100

Todavía se puede simplicar el formato (para poder enviarlo como n string a una función 'GenerarGrafo' que devuelva como resultado la lista raíz...), en dos pasos:
1 - Si acordamos que de cada producción la primera es la ciudad origen, así podemos deshacernos del '='
   LM-0|H-0
   MV-300|Z-300
   VA-200
   A-0   // nulo y distancia 0
   ZB-300
   B-0  // nulo
   HZ-100
2 - y disponerlas todas juntas en un unico string, pero diferenciadas por un separador, por ejemplo ';'...
   LM-0|H-0;MV-300|Z-300;VA-200;A-0;ZB-300;B-0;HZ-100

string producciones = "LM-0|H-0;MV-300|Z-300;VA-200;A-0;ZB-300;B-0;HZ-100"
Lista L = GenerarGrafo(producciones)

Ahora ya podemos pasar este string con tal formato, que contiene todos los datos del grafo, a una función que desguace e interprete el string, para generar la lista.

La función generar grafo:
- Primero debe partir el string recibido por el carácter ";" dejándolo en un array (función Split, suelen partir un string por un char o string y dejarlo en un array)

// Algo así suelen funcionar las funciones de split....
array de string prods = split(producciones, ";")

- Cada índice en ese array contiene una producción. Como cada producción puede tener más de un nodo, nuevamente debe partirse mediante un split y el separador "|", en las ciudades (array ciudades).
- Si éste array tiene ciudades (´vease que las ciudades 'terminales' no llevan a ninguna otra, luego estaría vacío), la primera debe separarse en la ciudad origen (que es la que usamos para crear la lista para dichas ciudades) y la primera ciudad...
Ejemplo:

prods(1) = "MV-300|Z-300"
array de string ciudades = Split(prods(x), "|")
Si ciudades.count > 0
   string origen = ciudades(0).firstchar
   ciudades(0).deletefirstChar

   lista ls = CrearLista(origen)

   por cada ciudad en ciudades
        3******
      nodo n = CrearNodo(Ls, Ld,
      ...
   siguiente
fin si

- Luego, antes de crear los nodos, en las ciudades aún estarán en la forma 'inicial + distancia', luego nuevamente hay que hacer un split, para separar la letra del valor y así poder crear el nodo, con los parámetros precisos.

En resumen, la función GenerarGrafo, será interpretar el parámetro de entrada para ir separándolo en sus partes y en varios bucles anidados, ir tratando cada cosa. A la entrada se obtiene el array de producciones, luego en un primer bucle se procesa cada producción. Que lo que haces es desguazar dicha producción en la ciudad origen y las ciudades a las que se accede. Si la ciudad es terminal, no tendrá ciudades, peor sí sí tiene.... Entonces en un segundo bucle se procesa cada ciudad de una producción, en el se separa la ciudad del valor de la distancia y luego crea el nodo con tales datos, y cada nodo se inserta en la lista de dichas producciones, etc...



Probablemente te resulte complicado de entender de una sola lectura, así que te aconsejo releerlo varias veces... y luego ya si eso, haces preguntas concretas.
 
#1934
Google, está más por su labor continuista de asalto a la privacidad y venta de datos que por hacer cacharos que a la vez de útiles sean absolutamente seguros.
#1935
Pués sí que funciona, sí...

Me viene de perlas, porque hay muchas veces que solo quieres escuchar audio, y mantener la pantalla encendida solo sirve para agotar antes la batería, y si la apagas, se corta el vídeo... así que perfecto.
#1936
Hay varia smaneras, una smás optimas que otras, y según el caso  hay un algoritmo (counting  Sort) que resulta el más efectivo pero puede incurrir en un costo excesivo de memoria (asocaidos al valor máximo y mínimo) y al mismo tiempo de tiempo (si el array es pequeño pero dichos valores son muy distantes entre sí...

Así que te indicaré la manera adecuada para todos los casos (y no solo números o número enteros).

1 - Ordenar el array.
2 - Recorrer el array con dos bucles.
El externo (el primero) empieza por el primer ítem en el array y acaba en el penúltimo. Este penúltimo, se irá reduciendo a medida que se tapen los repes con los que están por encima. Puede hacerse con un bucle while, condicionado a alcanzar el último -1, teniendo en cuenta que el último se va reduciendo en la medida en que aparezcan los repes.
El interno es también un bucle de tipo 'while' se repite el valor tomado en el primer bucle, la cuenta en este empieza (la primera vez solo) uno más arriba que el primero y acaba condicionado mientras se repita y no se alcanza el último índice del array.


// Realiza 3 operaciones: 1-ordenar el array, bajar los no repes tapando los repes, y copia a un nuevo array los no repes.
Funcion EliminarRepes(array de enteros valores() )
   entero numRepes
   // 1º Ordenar el array
   Llamada a  Ordenar (valores) // da igual si se ordena de menor a mayor o de mayor a menor
   // 2º Bajar los no repes tapando los repes,
   numRepes = EliminarRepes2(valores)
   // 3º Copiar a un nuevo array los no repes.
   valores = copyArray(valores, valores.Count - n)
fin funcion


// Recorre con dos bucles, en el primero se marca con 'i' el valor a buscar
//     con el segundo bucle se busca la cantidad de repes que hay para ese valor y
//     se van bajando, así cada repe, es 'tapado', por el que está por encima de él.
//     Al final del array quedarán valores sucios, de haberse bajado 'n' repes, ahí acaba el primer bucle.
//  'j' y 'k' son los índices de recorrido en cada bucle.
//  'n' es la cantidad de repes que se va hallando.
// 'ultimo' es el último actualizado a cada vez que se salga del bucle que localiza repes y baja lo.
entero = Funcion EliminarRepes(array de enteros valores() )
   entero i, j, k, n, u, ultimo

   u = valores.count -1 //el índice mayor del array
   ultimo = (u -1)
   k = 1: j=0
   Hacer mientras (j< ultimo)
       i = valores(j)
       
       si ( valores(k) = i )
           Hacer
               n = (n +1)
               valores(j+n) = valores(k)
               k = (k+1)
           Repetir mientras ((valores(k) = i ) y (k<u))
           ultimo = (valores.ultimo -1 - n)  //actualizamos cual será el último.
       Sino
           valores(j+n) = valores(k)
           k= (k+1)
       Fin si

       j= (j+1)
   siguiente

   devolver n
fin funcion

// Copia a un nuevo array la 'cantidad' de ítems del array valores a un nuevo array
//    se devuelve el array copiado.
array de enteros = copyArray(array de enteros valores(), entero cantidad)
   entero k
   array de enteros sinRepes()
 
   alojar tamaño para sinRepes(0 a cantidad-1)
   bucle para k desde 0 hasta cantidad -1
       sinRepes(k) = valores(k)
   siguiente
   devolver sinrepes
fin funcion


Pasar el código a pseudocódigo, sin cometer errores (y corigiendo algún gazapo que se me haya escapado, cosas de +1, -1, etc... que a veces se escapa al hacerlo de corrido), queda enteramente a tu esfuerzo... lo que te exige entenderlo, no copiar y pegar.
#1937
Foro Libre / Re: ¿Remedio gatuno?
12 Enero 2019, 17:07 PM
Para los cables, haz lo del pimentón picante... ni vinagre ni amoníaco. Con el vinagre tienes el problema del líquido aparte que no a todos los gatos les disgusta. Con el amoníaco, tienes el problema de que es tan molesto para tí como para ellos... El pimentón picante, solo afecta en el pmomento preciso en que decida 'hincarle el diente' a un cbale, por lo que en efecto lo asocia a: "los cables pican y mucho", lo suelta inmediato... y lo volverá intentar más veces, por eso hay que tener la servilleta cerca y mejor que te vea frotarlos... porque así asocia que lo haces tú, porque no quieres que los toque... y lo acabna entendiendo y sin traumas ni para tí, ni para el gato, ni para tu equipo informático.

CitarTenía pensado lavarla al menos 1 vez al mes como recomendaban, para estar limpia y sana, eso decían...
Eso podría funciona única y exclusivamente si lo aplicas a un gato que tienes desde que nació. Salvo los gatos del lago Van (Turquía), que son los únicos gatos del mundo, que no solo no les asusta el agua, si no que les encanta bañarse...

Lo que si puedes hacer es coger un paño (dedicado en exclusiva a ellos), humedecerlo sin llegar a estar empapado y con él fortarles... sin apretar... les gusta sobretodo si se sienten sucios.
Cuando alguna vez  he recogido un gato callejero, suele ser que han perdido la higiene personal, porque saben que enfermarían... una vez en casa, en un ambiente  aséptico (comparado con vivir en la calle), pueden retomar el aseo personal, pero como se parte de un estado a vece slamentable, toca limpiarles uno  con un trapo dos o 3 veces al día... después de una semana o así, ellos empezarán a hacerlo, cuando entiendan que ya no supone un riesgo para su salud hacerlo. Si no acabna por hacerlo, se les puede forzar untando un poquito de vinagre en el mismo trapo humedecido, les estimula a hacerlo...

De los veterinarios, no debes hacer mucho caso. Los veterinarios, son 'medicos de animales', punto... respecto de la forma de ser de los animales no saben más que cualquiera. Siempre exageran con las 'enfermedades' que pueden tener... que sí que a veces se dan, pero en situaciones de riesgo extremo. Al escucharles parecería que se da el 100% de los casos, lo cual resulta ridículamente absurdo.
No castres a tu gata si no sale de casa... si escuchas al veterinario, te dirá que así evitas que tenga un cáncer de ovarios... en efecto, si le extirpas la matriz, jamás tendrán cáncer de ovarios, pero pregunta al veterinario si él se ha extirpado el colon, para evitar padecer un cáncer de colon, y el hígado para evitar padecer un cáncer de hígado... y la cabeza así evitamos tener un aneurisma cerebral fijo. Yo me he topado con muchas animalistas que están a favor de la estirilización pero además de cirugía mayor, ni siquiera de la sencilla (esto es, a un perro en vez de seccionarle el conducto seminal, le extraen los textículos... ni qué decir de a dónde va a parar esa extracción luego ni a qué precio se vende a la industría farmacéutica y cosmética)... el caso es que a cada una que me soltaba la misma mandanga '...así se evita que tengan cáncer de ovarios...', les preguntaba si ellas también se habían operado para evitar el mismo cáncer o extirpado las tetas porque al fin y al cabo el cáncer de mama en las mujeres se da en mayor grado que el cáncer de matriz en las gatas... Da igual que trates de hacerles reflexionar, están cegadas por la obsesión del lavado cerebral que tienen...
El caso es que eliminar un órgano, no delimita que no aparezca un cáncer... quizás, si habiendo un 'problema interno' el cuerpo deriva que acabe en los ovarios, no existiendo ovarios, quién te garantiza que entonces ese 'problema interno' no lo derive al hígado, a los pulmones a otra parte del cuerpo?... otra cosa es que fuera siempre que un cáncer de ovarios tuviera su origen SIEMPRE (y no solo su manifestación), en los propios ovarios...

Si el origen es incierto, la manifestación será cualqueir parte... vamos que es como derramar agua en el suelo, si hay varios agujeros se llenan de agua, si tapas un agujero en específico, el agua que antes paraba en él, ahora irá a parar a otro agujero, ergo... no solucionas realmente nada, a cambio sueltas money de tu bolsillo, y fuerzas a pasar a un animal sano por un quirófano ¿¿¿¿Habrá algo más absurdo que eso?????.
...y con riesgo inmimente de una infección y posible revisita y cirugía para eliminar la infección + money además con antibióticos (todavía no te has enfrentado a hacerle tragar una pastilla a un gato, en el mundo no hay nada más complicado que eso (con algunos es relativamente fácil, si no es el caso, acaba en "misióm imposible") jajajajja...) y todavía no evitas el riesgo de muerte....
Los veterinarios, al fin y al cabo, son 'empresarios' y como tal barren para casa, así que siempre te dirán que compres comida de la que ellos venden (que por supuesto es inmensamente más cara), que los operes de esto y aquello, que... sé sensato, imagina que en vez de hablar de tú gato, fuera un médico y hablara de tí... ¿¿¿Harías lo que te propone????.
Tenlos al corriente de las vacunas y listo. Para lo demás el juicio de un veterinario no tiene más validez que la de tu vecino o la de cualquiera de este foro.
#1938
Tienes el código un poco enfarragoso.

antes de ponserse a escribir código, es mejor verlo en tu mente... Realmente se trata de reflejar tal como lo hacmeos en la realidad. Y así acostumbra a escribir en prosa, primero... verás que luego es casi traducir/transcribir...

Al iniciar el juego:
1 - Si no quedan cartones, crear x cartones.
Esta sola línea ya sugiere  3 cosas:
- Señala que debe haber un campo que refleje el número de cartones libres.
- Una función que crea cartones.
- Un parámetro en la función que señala cuantos cartones se van a crear...
- Previamente debe quedar claro, cuantas bolas contiene el bingo: 80, 90, 100, 120, etc...
- Previamente debe quedar claro, cuantos valores contiene cada cartón... 12,15, etc...


Y podría ser algo así:


   entero BolasXBingo = 100
   entero BolasPorCarton = 20

   entero SiguienteCarton          // Indice dle siguiente cartón disponible en la banca.
   entero CartonesXPartida = 2  // cantidad mínima a repartir para jugar una partida.
   array string CartonesBanca(0 a 99)  //tendrían la forma: -3-7-11-19-25-11-48-91-....94-  Es decir cada número de bola está encerrado entre guiones.



   funcion NuevaPartida
       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
           CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
       fin si

       ... más cosas que se irán añadiendo debajo.
   fin funcion



   Funcion CrearCartones(entero NumCartones, entero Inicio)
       entero k, fin

       fin = (Inicio + NumCartones)

       Si (fin <=BolasXBingo)
           bucle para k desde Inicio hasta fin
               CartonesBanca(k) = CrearNuevoCarton
           siguiente
       Sino
           bucle para k desde Inicio hasta BolasXBingo
               CartonesBanca(k) = CrearNuevoCarton
           siguiente

           fin = (fin modulo BolasXBingo)
           bucle para k desde 0 hasta fin
               CartonesBanca(k) = CrearNuevoCarton
           siguiente
       Fin si
   fin funcion

   // Crea un cartón nuevo. Sus bolas no están repetidas en el cartón, pero alguna puede aparecer en otros cartones.
   // Un cartón es un string, con los números d elas bolas encerrados todos ellos entre guiones, así:
   //        "-5-9-13-14-26-29-30-36-45-48-51-54-62-66-73-79-85-89-92-98-"
   string Funcion CrearNuevoCarton
       entero k, n
       string carton = "-"

       bucle para k desde 1 a BolasPorCarton
           Hacer
               n = random(entre 1 y BolasXBingo)
           Repetir mientras ExisteBolaEnCarton(carton, n) = TRUE

           carton = (carton + n.ToString + "-"
       Siguiente
     
       Devolver carton
   fin funcion

   // Verifica si existe una bola dada en un cartón.
   // Esta función se invoca mientras se crea un cartón y cuando se extrae una bola del bingo.
   buleano ExisteBolaEnCarton(string Carton, entero bola)
       string b = "-" + bola.ToString + "-"  //bola.ToString es una conversión de entero a string.
     
       //una búsqueda para ver si el string 'b' está contenido en el string 'carton'.
       // OJO: para buscar la bola 5, realmente buscamos "-5-", sino daría ok, si contuviera 15, 25, etc...
       devolver Carton.contiene(b)
   fin funcion


2 - Repartir cartones entre los jugadores.
Esta línea sugiere varias cosas:
- Hay varios jugadores, luego un campo debe reflejar cuantos jugadores son.
- Cuántos jugadores mínimos, se requieren para jugar el bingo. Quien dice jugadores, dice cartones.
- Es válido que un jugador tenga más de 1 cartón?.
- Los cartones simplemente se 'reparten' o se 'compran'...
Comprando la dinámica dle juego se complica un poco más, pués hay que poner precio a los cartones y ver si el jugador tiene suficiente dinero para comprar, además de llevar la cuenta del dinero de cada jugador más el de la banca.
-- Se puede simplicar repartiendo siempre por ejemplo x cartones (1,2 por ejemplo) a cada jugador.
-- Se puede simplificar dejando constante el número de jugadores (2,3,4,5,6 por ejemplo).
- Implica una función Repartir, que toma el siguiente cartón disponible y lo entrega al jugador.
Esto puede hacerse de 2 maneras, o se invoca una funcion 'getCarton', donde el  jugador es un parámetro de dicha función, donde se devuelve el cartón y al recibir se entrega al jugador.

Seguimos completando la función 'nuevapartida'... y el código fuera de funciones...

   entero JugadoresEnPartida = 2  // NUEVO: esto se pone arriba
   array entero CartonesDeJugadores(0 a JugadoresEnPartida -1) // NUEVO: ídem

   funcion NuevaPartida
       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
            CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
        fin si
   
       llamada a RepartirCartones  //NUEVO
     
       ... más cosas que se irán añadiendo debajo.
   fin funcion


RepartirCartones será una función que reparta todos los catones necesarios de la partida (en la modalidad simple para el juego basta así) que a su vez invoca a otra función que entrega el siguiente cartón disponible en la banca, en el array CartonesBanca.


   // hemos estabecido (para ejemplo) que se reparte 1 carton por jugador, y que aunque haya dos jugadores, su valor se almacena en JugadoresEnPartida y los cartones de cada en el array CartonesDeJugadores
   funcion RepartirCartones
       entero k

       bucle para k desde 0 a JugadoresEnPartida
             CartonesDeJugadores(k) = GetSiguienteCarton
       fin bucle
   fin funcion

   entero Funcion GetSiguienteCarton
       string carton

       carton = CartonesBanca(SiguienteCarton)
       SiguienteCarton = (SiguienteCarton +1)
       Si (SiguienteCarton = BolasXBingo) luego SiguienteCarton = 0

       devolver Carton
   fin funcion


3,4 y 5 - Ya tenemos creados los cartones y cada jugador con su cartón, aún faltan 3 cosas... iniciar el sorteo, verificar cuando se extrae una bola si tal o cual cartón la contiene y verificar cuando se canta bingo (cuando el juego acaba).
Volvemos a editar la función nueva partida... ya que es el 'main' del juego, la función principal.


   entero ValorPremio = 100  // NUEVO: esto se pone arriba
   array entero BolasBingo(0 a BolasXBingo-1) // NUEVO: ídem
   entero SiguienteBola   // NUEVO: ídem

   funcion NuevaPartida
       entero jugadorpremiado // NUEVO: ídem

       Si ((SiguienteCarton+CartonesXPartida)  => BolasXBingo)
            CrearCartones((BolasXBingo-CartonesXPartida), SiguienteCarton)
        fin si
   
       llamada a RepartirCartones  //NUEVO

       Llamada a BarajarBingo   // barajar el 'bombo'
       jugadorpremiado = Sortear  //sacar bolas del bingo

       Llamada a EntregarPremio(jugadorpremiado, ValorPremio)  //100 monedas para el ganador.
   fin funcion


3 - Recrear el bombo con sus bolas y barajarlas todas de una sola vez.

   funcion BarajarBingo
       entero i, j, k

       // Esto realmente es crear el bingo, bastaría invocarlo una sola vez cuando se abre el programa, las demás veces, solo barajarlo
       bucle para k desde 0  hasta BolasXBingo-1
           BolasBingo(k) = k+1   //las bolas se guardan en un array del 0 al 99, por ejemplo, pero el valor de las blas comienzan en 1 hasta el 100.
       siguiente

       // Ahora se baraja, con el algoritmo del sombrero (Fisher-Yates-Durstenfeld)
       bucle para k desde BolasXBingo-1 hasta 1 retrocediendo
           j = random(enter 0 y k)
           i = BolasBingo(j)
           BolasBingo(j)= BolasBingo(k)
           BolasBingo(k) = i
       siguiente

       SiguienteBola = 0
   fin funcion


4 - Como en el bombo se han barajado ya todas las bolas de una sola vez, el sorteo consiste en sacarlas en orden...

   entero = Funcion Sortear
       entero jp, bola

       // El bucle acaba cuando se da el premio.
       // NOTA: que salvo que esté mal programado, el premio se otorgará sí o sí, como muy tarde, con la última bola del bombo
       //     por ello resulta estéril añadir como segunda condición: (SiguienteBola < BolasXBingo)
       Hacer
           bola= BolasBingo(SiguienteBola)
           llamada a VerificarCartones(bola)
           jp = VerificarPremiado
           SiguienteBola= (SiguienteBola + 1)
       Repetir mientras  (jp= -1)

       devolver jp  // jp es el jugador premiado.
   fin funcion


Ahora verificamos cartones, esto es, tachamos la bola extraída en cada cartón que la contenga.

   Funcion VerificarCartones(entero BolaExtraida)
       entero k, ini, fin
       
       fin = (SiguienteCarton - 1)
       ini = (fin - CartonesXPartida)

       // OJO: Podría darse el caso que un cartón sea el 100 y el otro el 1... queda a tu esfuerzo, solucionar tales casos.
       bucle para k desde ini hasta fin
           Si ExisteBolaEnCarton(CartonesDeJugadores(k), BolaExtraida)
               TacharBola(CartonesDeJugadores(k), BolaExtraida)
           Fin si
       Siguiente
   fin funcion

   function TacharBola(string carton, entero bola)
       string b = bola.ToString
       carton.Remplazar(b, "x")   // se busca el texto (número) de la bola 'b' en cartón y se remplaza por 'x'
   fin funcion


5 - Esta función revisa cada cartón para ver si alguno tiene tachada todas las bolas.
Es más óptimo hacer esta revisión al mismo tiempo que revisa la bola a tachar, lo anoto más abajo como una observación.

   entero = Funcion VerificarPremiado
       entero k, ini, fin
       
       fin = (SiguienteCarton - 1)
       ini = (fin - CartonesXPartida)

       // OJO: Podría darse el caso que un cartón sea el 100 y el otro el 1... queda a tu esfuerzo, solucionar tales casos.
       bucle para k desde ini hasta fin
           Si CartonTieneTodasTachadas(CartonesDeJugadores(k))
               devolver k
           Fin si
       siguiente
       devlver -1
   Fin funcion

   // esta función es subóptima. Trata de buscar si contiene todas las bolas tachadas.
   buleano = funcion CartonTieneTodasTachadas(string carton)
       entero j, k, n
       string x
       
       j=0
       bucle para k desde 1 hasta BolasPorCarton
           // la función contiene, devuelve la posición donde aparece 'x', si no se encuentra teóricamente devuelve -1
           //     el parámetro j, indica desde donde comenzar a buscar
           n = Carton.Contiene("x", j)  
           Si (n > j)
               j = n+1
           sino
               devolver FALSE
           fin si    
       siguiente

       devolver TRUE
   fin funcion




NOTAS:
- Pasar el pseudocódigo a código queda a tu esfuerzo.
- Puede haber más de un premiado a la vez (esto es, tendrían un cartón idéntico), queda también a tu esfuerzo, o bien impedir esto, o bien repartir el premio entre los jugadores, así como verificar todos los cartones en busca d epremio. En el pseudocódigo se asume que solo un jugador puede ganar, luego si swe encuentra un ganador se aborta el resto de la búsqueda.
- No se añade pseudocódigo para la función EntregarPremio, queda a tu esfuerozo, si resulta de interés al caso.
- Una ligera optimización sobre cartones: En el propio cartón se podría indicar además las bolas restantes para bingo, por ejemplo al inicio o final del string del cartón se podría poner el número de bolas sin tachar (cuandos e crea el cartón se pone el número total de blas por cartón) y cuando se tache una, tomar el valor, restar uno y actualizar dicho valor (resulta muy fácil si es al comienzo o final dle string). Si un cartón llega a cero, será premiado, con lo que la misma función de verificar cartones para tachar bolas y buscar cartón premiado sería la misma.... como cada bola va encerrada entre guiones "-34-", este valor podría diferenciarse encerrándolo de forma diferente, así nunca se encontrará por error ese número, como una bola y se tache.


- Finalmente nota, que el pseudocófigo no es óptimo, ateniéndose a: "juego del bingo simplificado". Ya que por ejemplo, al crear cartones, nunca se buscan aleatoriamente los números, sino que las bolas del bingo deben proporcionar números de cartones exactos (por ejemplo  de un bingo de 100 bolas, da 5 cartones de 20 números, un bingo de 90 bolas da 6 cartones de 15 números, un bingo de 84 bolas da 7 cartones de 12 bolas, etc...), entonces las bolas del bingo, primero se crea un array del 1 a la última bola, y se baraja... entonces ese array acotado en tandas de 20, 15, 12... esto es, según la cantidad de bolas por cartón, son lo que definen un cartón. Así en ese array las bolas dle primer cartón son las que ocupan las posiciones en el array del 0 al 19, el 2º cartón 20 a 39... el 5º cartón 80 a 99). Y para ser equitativos, además habría de cumplirse ciertos requisitos mucho más restrictivos sobre los cartones, esto es estar equitativamente compensados en el reparto de bolas, a nadie le haría gracia tener las bolas 5,6,7,8,9 y 24,25,26,27,28 en su cartón...sino mas bien 2 o 3 bolas de cada decena... Cuando no es así, no es verdaderamente equitativo el azar para cada jugador. Eso sí, para un ejecrcicio vale...

- Quizás se me haya escapado algún gazapo... confío que en tal caso puedas verlo sobre la marcha.
#1939
Buscar que dos o más usuarios tengan la misma cuenta, y la usen desde distintas ubicaciones... a esto le llaman IA????.

Juas... hoy ya, a cualquier cosa le llaman IA.

#1940
Foro Libre / Re: ¿Remedio gatuno?
11 Enero 2019, 20:24 PM
A los gatos les gusta jugar con cuerdas y tal... no tener juguetes es una forma de buscarlos. De todas formas a veces da igual los juguetes que tengan, al final se aburren. Les gusta más el juego interactivo, igual que les pasa a los niños...

Para los cables, lo que yo hago siempre que tengo un gato 'nuevo' es coger un poco de pimentón picante, sobre una servilleta de papel, froto los cables varias veces... y dejo que se acerquen, cuando lo prueban 2, 3 veces... dejan ya de insistir, mas aún si de nuevo ves que se acercan, coges e papel (con los resto del pimentón en polvo), se lo enseñas y sa va ligero... Al final pierte interés por los cables... cuestión a lo sumo de 2-3 días.

Subirse al teclado... es difícl evitarlo, la forma en que lo solucioné (hace muchos años) es tener una bandeja bajo la mesa y la mesa donde antes estaba el teclado, queda libre, así puede echarse ahí... o bien tener una mesa muy espaciosa, y ponerles un cojín.
Al final, lo que buscan es tu cariño, y estar cerca de tí, para ellos es una forma de aprobación, de sentirlo. Los gatos gustan de romper la distancia interpersonal, porque así es como se saben poseedores del cariño de su amigo y compañero.
Con paciencia también consigues que no pisen el teclado... los míos pasan por entre él, y siempre lanzan las patitas fuera del teclado... aunque no evita que te ponga d eos nervios, porque las pocas veces que pisan pisan teclas activando funciones que ni conocías y que no te resulta claro ni como desactivar (cosa de pisar simultáneamente múltiples teclas).
Esta paciencia para el teclado, consiste en que cuando los ves venir hacia el teclado, retirar el conector del teclado, dejar que se paseen y apartarles suavemente al tiempo que les repites insistentemente 'no, no me pises el teclado'... de alguna manera después de escucharlo chorrocientas mil veces, parecen entenderlo bien...

Sobre la torre, lo único que se me ocurre en la forma que describes tenerlo, es amarrarla bien, sea atándola con cuerdas, con algo metálico atornillado, etc... que quede firmamente sujeto a la mesa, o lo tira todo o nada.

Yo también suelo tener el pc en una mesita con ruedas por la comodidad de moverla de acá para allá, pero es un tablet PC, cuya base es bastante estable...