¿Cómo mejorar esta generación de numbers aleatorios en mi context?

En mi juego hay una palabra en la parte superior de la pantalla, las letras están lloviendo desde arriba y el usuario tiene que tocar las letras para completar la palabra.

Actualmente estoy generando letras random (en realidad los numbers aleatorios y los numbers son el índice de la matriz de letras, por ejemplo: 0 = a, 1 = b) pero el problema es que toma demasiado time get todas las letras requeridas para completar el palabra.

Lo que quiero es que los numbers aleatorios que estoy generando generen las letras requeridas más a menudo para que el jugador no tenga que pasar todo el día para completar una palabra.

He intentado seguir los siguientes methods:

  1. Detecta todas las letras de la palabra (la palabra siempre tiene 6 letras), genera la matriz de índices de longitud 6, asigna cada índice de la matriz al número aleatorio de la letra-2 a la letra + 2 y al final elige aleatoriamente un índice de la matriz para mostrar.

  2. Tener una variable selectora cuyo valor esté en el range [0..2], generada aleatoriamente, si selector == 0 luego detectar letras que forman la palabra y elegir aleatoriamente una letra, de lo contrario get aleatoriamente cualquier alfabeto de az.

Ambos methods no me han brindado ninguna ayuda. Estaré muy feliz si puedes ayudarme.

Gracias por leer esto, espero que hayas entendido la pregunta y estoy esperando la respuesta.

En realidad, no quieres una distribución aleatoria. Señalo esto explícitamente, porque lo que consideramos "aleatorio" para el layout generalmente no es verdadero aleatoriedad.

Ahora, con eso en mente, agreguemos algunos valores de ajuste: estas son las cosas con las que jugará hasta que el layout se sienta "correcto".

ChooseLetter() { const float WordLetterProbability = 0.5f; if (Random.NextFloat01() < WordLetterProbability) { // Pick a random letter in the word } else { // Pick a random letter *not* in the word } } 

La probabilidad controla la probabilidad de que una llamada determinada a ChooseLetter le proporcione una palabra: a 0.5, obtendrá una letra de palabra aproximadamente cada dos por tres. En 0.25, uno de cada cuatro será una letra de palabra, etc.

Esto todavía es un poco simplist, porque la aleatoriedad es, bueno, aleatoria , en realidad no tienes garantía sobre cuánto time pasarás entre las letras de las palabras. (En teoría, puedes ir para siempre sin una letra de palabra, es muy muy poco probable). En cambio, podemos agregar un factor para boost la probabilidad de una letra de palabra cada vez que no obtenemos una:

 const float BaseWordLetterProbability = 0.5f; const float WordLetterProbabilityIncrease = 0.25f; float WordLetterProbability = BaseWordLetterProbability; ChooseLetter() { if (Random.NextFloat01() < WordLetterProbability) { // Pick a random letter in the word WordLetterProbability = BaseWordLetterProbability; } else { // Pick a random letter *not* in the word WordLetterProbability += WordLetterProbabilityIncrease; } } 

Bueno, ahora nunca vamos más de dos cartas sin una palabra. (Porque, después de dos errores, tenemos una probabilidad de 1.0 de get una letra de palabra).

Finalmente, debemos tener en count cómo funciona la elección de la letra en una palabra. Para poder proporcionar al jugador las letras que realmente necesita, debemos eliminar las letras del set a medida que las recibe.

Por ejemplo, si la palabra es "testing", y el jugador ya tiene 's', no queremos darles otra 's' porque no la necesitan.

A partir de aquí, el rest es ajustar para adaptarse a su layout.

Puede ponderar la probabilidad de todas sus letras de acuerdo con la frecuencia con la que ocurren en el idioma en que están sus palabras. Una buena pauta es el set de scrabble . La versión en inglés, por ejemplo, tiene 12 E pero solo una Z y una Q.

Una forma simple de implementar esto es colocar todas las letras en una cadena consecutiva con cada letra que aparece tantas veces como se desee y luego hacer que su RNG tome una carta de una position aleatoria. Ejemplo de pseudocódigo:

 const String letters = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJ/*...and so on...*/" char randomLetter = letters[randomIntegerBetween(0, letters.length - 1)]; 

Aquí hay una manera de mejorarlo usando un solo parámetro k que puede ajustar.

En lugar de simplemente elegir una letra random:

  1. elige una letra aleatoria A
  2. elige un número aleatorio X
  3. si X > k y A no están en [list of remaining needed letters] , intente de nuevo en 1.

Cuanto menor es k , más a menudo la letra final A será la que realmente se necesita.

Para modificar el algorithm, juegue con cualquier valor para k , por ejemplo , k = 0.5 . Si encuentras que el juego es demasiado difícil, testing 0.4 lugar, etc. hasta que encuentres un valor razonable. Esto también le proporciona directamente una configuration de dificultad , que, por ejemplo, puede querer boost a medida que el jugador avanza en el juego.

Una forma simple de garantizar que las letras requeridas aparezcan dentro de un time determinado es usar llenar una matriz con las letras de la palabra y el rest del alfabeto (quizás repetido), luego aleatoriamente mezclar la matriz (c ++ tiene std :: random_shuffle en la biblioteca estándar, si usa un idioma diferente, no es difícil de implementar).

Si desea que las letras de la palabra aparezcan más rápidamente, coloque más copys de las letras de las letras en la matriz.

Si está utilizando C ++, puede usar una distribución ya existente http://en.cppreference.com/w/cpp/numeric/random/piecewise_constant_distribution

También ha amortizado la complejidad del time constante, que es mejor que los methods ingenuos. ejemplo:

 #include <iostream> #include <string> #include <map> #include <random> #include <numeric> int main() { constexpr double containedLetterWeight = 3.0; constexpr int iterations = 10000; std::string word = "DISTRIBUTION"; std::mt19937 rng(123); std::vector<double> values('Z' - 'A' + 2); std::iota(values.begin(), values.end(), 0.0); std::vector<double> weights('Z' - 'A' + 1, 1.0); for(const auto& c : word) weights[c - 'A'] = containedLetterWeight; std::piecewise_constant_distribution<> dist(values.begin(), values.end(), weights.begin()); std::map<char, int> results; for(int n = 0; n < iterations; ++n) { ++results[static_cast<char>(dist(rng)) + 'A']; } for(const auto& p : results) { std::cout << p.first << ' ' << static_cast<float>(p.second) / iterations << '\n'; } }