2010-02-15 21 views
13

Estoy haciendo un juego de palabras similar al boggle. El usuario se le da una cuadrícula de letras como esto:Algoritmo para elegir letras al azar para el juego de búsqueda de palabras que permite que se deletreen muchas palabras

O V Z W X 
S T A C K 
Y R F L Q 

El usuario escoge una palabra utilizando cualquier cadenas adyacentes de letras, como la palabra "pila" a través de la línea media. Las letras utilizadas son reemplazadas por la máquina, p. (nuevas letras en minúsculas):

O V Z W X 
z e x o p 
Y R F L Q 

Aviso ahora puede significar un "desbordamiento" mediante el uso de las nuevas letras. Mi problema es: ¿qué algoritmo puedo usar para elegir nuevas letras que maximicen el número de palabras largas que el usuario puede deletrear? Quiero que el juego sea divertido e implique la ortografía, p. Algunas veces, las palabras de 6 letras pero, si eliges letras malas, los juegos implican que el usuario solo deletree palabras de 3 letras y no tenga la oportunidad de encontrar palabras más grandes.

Por ejemplo:

  • Se podía elegir aleatoriamente nuevas letras del alfabeto. Esto no funciona bien

  • Del mismo modo, encontré escoger al azar, pero utilizando las frecuencias de letras de Scrabble no funcionó bien. Esto funciona mejor en Scrabble, creo que ya que tienes menos restricciones sobre el orden en que usas las letras.

  • Intenté tener un conjunto de listas, cada una representando uno de los dados del juego Boggle, y cada letra sería escogidos de un lado dado al azar (también me pregunto si puedo usar legalmente estos datos en un producto). No noté que esto funcionaba bien. Imagino que los lados dados de Boggle fueron elegidos de una manera sensata, pero no puedo encontrar cómo se hizo esto.

Algunas ideas que hemos considerado:

  • hacer una tabla de la frecuencia con pares de letras se presentan juntos en el diccionario. En aras de la discusión, digamos que E se ve al lado de A el 30% del tiempo. Al elegir una nueva carta, elegiría aleatoriamente una letra basada en la frecuencia de esta carta que aparece junto a una letra adyacente elegida al azar en la cuadrícula. Por ejemplo, si la letra vecina era E, la nueva letra sería "A" el 30% del tiempo. El debería significar que hay muchos pares decentes para usar dispersos por el mapa. Tal vez podría mejorar esto haciendo que las tablas de probabilidad de una carta ocurran entre otras dos letras.

  • De alguna manera hacer una búsqueda de lo que las palabras pueden ser escritas en la parrilla actual, teniendo las nuevas letras para ser comodines. Luego reemplazaría los comodines con letras que permitieran escribir las palabras más grandes. Sin embargo, no estoy seguro de cómo lo haría de manera eficiente.

Se agradecen otras ideas. Me pregunto si hay una forma común de resolver este problema y qué otros juegos de palabras usan.

Edit: ¡Gracias por las excelentes respuestas hasta ahora! Olvidé mencionar que realmente estoy buscando requisitos de memoria/CPU bajos si es posible, probablemente usaré el diccionario SOWPODS (aproximadamente 250,000) y mi cuadrícula podrá 6 x 6.

+1

Me gusta su idea de usar probabilidades de yuxtaposición de letras. Podrías expandirlo aún más: para cualquier ubicación de letra dada, calcula la probabilidad de que cada letra sea adyacente a las letras que las rodean inmediatamente y promedia estas probabilidades en una sola, luego escoge una letra aleatoria usando las probabilidades promediadas como ponderaciones. – Cameron

Respuesta

1

No lo hago saber sobre un algoritmo preescaneado para esto, pero ...

hay un archivo de diccionario en UNIX, y me imagino que hay algo similar disponible en otras plataformas (tal vez incluso en las bibliotecas de Java - google). De todos modos, usa los archivos que usa el corrector ortográfico.

Después de que deletreen una palabra y se descarta, tiene letras existentes y espacios en blanco.

1) De cada letra existente, vaya a la derecha, izquierda, arriba, abajo (que tendrá que entender los algoritmos recursivos). Siempre que la cadena que ha construido hasta ahora se encuentre al comienzo de las palabras o hacia atrás desde el final de las palabras en el archivo de diccionario, continúe. Cuando se encuentre con un espacio en blanco, cuente la frecuencia de las letras que necesita a continuación. Usa las letras más frecuentes.

No va a garantizar una palabra que usted no ha comprobado el final o el principio correspondiente, pero creo que sería mucho más fácil de implementar que una búsqueda exhaustiva y obtener muy buenos resultados.

+0

¿Podría dar un pequeño ejemplo? No estoy seguro de cómo funcionaría esto. – BobbyJim

7

Aquí es un método simple:

Escribir un programa de solución rápida para el juego usando la misma lista de palabras que va a utilizar el reproductor. Genere, digamos, 100 tableros posibles diferentes al azar (probablemente sea una buena idea usar frecuencias de letras, pero no es esencial). Para cada tablero, calcule todas las palabras que se pueden generar y califique el tablero en función del número de palabras encontradas o el recuento ponderado por la longitud de la palabra (es decir, la suma total de las palabras de todas las palabras encontradas). Luego solo elige la mejor tabla de puntuación entre las 100 posibilidades y dale eso al jugador.

También en lugar de estar siempre recogiendo el tablero de puntuación más alta (es decir, la junta más fácil) que podría tener diferentes umbrales de puntuación para hacer el juego más difícil para los expertos.

+0

Gracias. Esta es probablemente la idea más a prueba de balas en la que podría, por ejemplo, garantizar (la mayoría de las veces) que siempre habrá una cierta cantidad de palabras grandes para elegir. Mi placa será de 6x6 y usar un trie lleva demasiada memoria, pero no estoy seguro de cómo podría usar esto de manera eficiente. – BobbyJim

+0

Usar una lista de prefijos de palabras (trie) le dará el mejor rendimiento si tiene la memoria. Si almacenas el trie comprimido, probablemente puedas crear un trie completo en unos pocos MBs, supongo. Si no es así, todavía puede conseguir probablemente una lista de palabras de prefijo de longitud hasta 5 en la memoria, y luego cambiar a binario (o interpolados) búsqueda de la lista de palabras completa para comprobar si hay partidos de más de 5. Alternativamente ... contar los prefijos hasta hasta la longitud 5 y suponga que muchas palabras parciales pequeñas dan una buena oportunidad de una palabra larga sin verificar explícitamente las palabras largas. –

+1

Si te atreves puedes usar un DAWG que está almacenado en una matriz. Hay una excelente conferencia de vídeo de Stanford en la que se encuentra aquí: http://www.youtube.com/watch?v=TJ8SkcUSdbU El cuento es que ella logró almacenar 250.000 palabras 0.32 MB –

2

Una pequeña variación en el enfoque de la carta de par: el uso de la frecuencia de pares de letras en palabras largas - por ejemplo 6 letras o más - ya que es su objetivo. También podría desarrollar una ponderación que incluyera todas las letras adyacentes, no solo una aleatoria.

+0

¡Bien acerca de usar las palabras largas de 6 letras! Consideré usar trigramas (solo considero la frecuencia de 3 pares de letras) pero su idea suena más cercana a lo que realmente quiero. – BobbyJim

2

This wordgame Hace un tiempo, que se comporta muy similarmente a lo que describes, usa tablas de frecuencia en inglés para seleccionar letras, pero primero decide si generar una vocal o consonante, lo que me permite asegurar una tasa de vocales dada el tablero. Esto parece funcionar razonablemente bien.

+0

Gracias. ¿Qué usaste para la frecuencia vocal/consonante? Lo que siento es que, en cada cuadrícula 2x2 local, probablemente deberías tener al menos una vocal. De lo contrario, podría obtener grupos de consonantes "atrapados" en las esquinas que no puede usar en palabras. ¿Usaste solo usar tablas de frecuencia de letras regulares y no p. frecuencias de letras emparejadas? – BobbyJim

+0

@Bobby: porque muta el tablero después de cada palabra, el jugador puede "saltar lejos" en grupos de letras difíciles a través del tiempo - Se podría pensar en que, como parte de la estrategia de juego. El/tasa consonante vocal está cableado a 0,559 - obtuve ese valor y las frecuencias de letras mediante la recopilación de estadísticas en algunos libros electrónicos que tenía por ahí :) – moonshadow

+0

Bien, gracias. De hecho, he probado mi juego con el comportamiento de caída, pero he descubierto que los jugadores tienden a ignorar las letras de abajo cuando las letras no son muy buenas y pasan todo el tiempo en la parte superior.Estaba pensando en cartas que caían de todas las direcciones de alguna manera. O conviértalo en un requisito para deshacerse de las letras antiguas. Además, las letras caídas dificultan, p. arregla el número de vocales en las posiciones de la cuadrícula local. Sin embargo, podría estar pensando en esto. :) Me gustaría bastante si, por ejemplo, cada cuadrícula tenía al menos una palabra larga para que los expertos pudieran presumir. – BobbyJim

2

Deberías buscar n-gramming y Markovian Models.

Su primera idea está muy poco relacionada con los algoritmos de Markovian. Básicamente, si tiene un corpus de texto grande, digamos de 1000 palabras. Lo que puede hacer es analizar cada letra y crear una tabla para conocer la probabilidad de una letra determinada después de la letra actual.

Por ejemplo, sé que la letra Q de mis 1000 palabras (4000 letras en total) se usa solo 40 veces. Luego calculo qué letras probables siguen usando mi tabla hash de markov.

Por ejemplo, QU ocurre el 100% del tiempo, así que sé que, si su aplicación selecciona aleatoriamente Q, debo asegurarme de que la letra U también esté incluida. Luego, la letra "I" se usa el 50% del tiempo, y "A" el 25% de las veces y "O" el 25% del tiempo.

En realidad es muy complicado de explicar y apuesto a que hay otras explicaciones sobre los defectos por ahí que son mucho mejor que esto.

Pero la idea es que, dado un corpus de texto legítimamente grande, puede crear una cadena de letras X que probablemente sean consistentes con el idioma inglés y por lo tanto debería ser fácil para los usuarios pronunciar palabras. Puedes elegir mirar hacia adelante en un valor de n-gram, cuanto más alto sea el número, más fácil será hacer tu juego. Por ejemplo, un n-gramo de dos probablemente haría muy difícil crear palabras sobre 6, pero un n-gramo de 4 sería muy fácil.

La Wikipedia lo explica muy mal, así que no habría que seguir.

Echa un vistazo a este generador de Markov:

http://www.haykranen.nl/projects/markov/demo/

+0

Gracias, suena interesante. ¿Podría elaborar un poco más sobre el n-gram de 4 idea? Yo, por ej. seleccione una cadena adyacente de 4 letras, diga "C-H-A-N", cerca de mi ubicación de letra aleatoria, luego solicite a una mesa que elija una letra que generalmente sigue a las 3 letras "CHAN", p. "G" como en "CAMBIANDO"? – BobbyJim

+0

Siempre he tenido miedo de las cadenas de Markov. El artículo principal de la wiki es confuso pero este es bastante bueno: http://en.wikipedia.org/wiki/Examples_of_Markov_chains – BobbyJim

+0

n-gramming es justo donde se descompone algo en N número de gramos. Por ejemplo, en un 1-gram de la palabra Boggle es 1 gramo BOGGLE 2-gramo (comúnmente llamado un bigram) Sería B BO OG GG GL LE E 3-gramo (comúnmente llamado una trigrama) sería B BO BOG OGG GGL GLE LE E En un 4 gramos (Sólo llamado n-gram) sería B BO BOG bogg OGGL GGLE GLE LE E Usted puede ver cómo si usas una cadena de markov con un n-gram particular, puedes agrupar secuencias de caracteres particulares que ocurren en común. Incidentalmente, a medida que aumentas el n-gram, encontrarás que el juego se vuelve más fácil. – Layke

0

lo podría hacer en este Java implementation del Jumble algorithm encontrar juegos de cartas que permutar a múltiples palabras del diccionario:

 
$ java -jar dist/jumble.jar | sort -nr | head 
11 Orang Ronga angor argon goran grano groan nagor orang organ rogan 
10 Elaps Lepas Pales lapse salep saple sepal slape spale speal 
9 ester estre reest reset steer stere stree terse tsere 
9 caret carte cater crate creat creta react recta trace 
9 Easter Eastre asteer easter reseat saeter seater staree teaser 
9 Canari Carian Crania acinar arnica canari carina crania narica 
8 leapt palet patel pelta petal plate pleat tepal 
8 laster lastre rastle relast resalt salter slater stelar 
8 Trias arist astir sitar stair stria tarsi tisar 
8 Trema armet mater metra ramet tamer terma trame 
... 
Cuestiones relacionadas