Bagaimana cara meningkatkan pembangkitan angka acak ini dalam konteks saya?

11

Dalam permainan saya ada kata di bagian atas layar, surat-surat turun hujan dari atas dan pengguna harus menyentuh huruf untuk menyelesaikan kata.

Saat ini saya menghasilkan huruf secara acak (sebenarnya angka acak dan angka adalah indeks untuk array huruf. Misalnya: 0 = a, 1 = b) tetapi masalahnya adalah bahwa terlalu banyak waktu untuk mendapatkan semua huruf yang diperlukan untuk menyelesaikan kata.

Yang saya inginkan adalah bahwa angka acak yang saya hasilkan harus menghasilkan huruf yang diperlukan lebih sering sehingga pemain tidak perlu menghabiskan sepanjang hari untuk menyelesaikan satu kata.

Saya telah mencoba metode berikut:

  1. Deteksi semua huruf dalam kata (panjang kata selalu 6 huruf), buat larik indeks dengan panjang 6, tetapkan setiap indeks larik ke angka acak dari huruf-2 ke huruf + 2 dan pada akhirnya pilih secara acak satu indeks dari array untuk ditampilkan.

  2. Memiliki variabel pemilih yang nilainya berada dalam kisaran [0..2], dihasilkan secara acak, jika pemilih == 0 kemudian deteksi huruf yang menghasilkan kata dan pilih satu huruf secara acak, jika tidak secara acak dapatkan alfabet apa pun dari az.

Kedua metode ini belum memberi saya bantuan. Saya akan sangat senang jika Anda dapat membantu saya.

Terima kasih sudah membaca ini, saya harap Anda mengerti pertanyaannya dan saya menunggu jawabannya.

Daniyal Azram
sumber
2
"kedua metode ini tidak memberi saya bantuan" Mengapa tidak? Apa yang tidak berhasil dengan metode ini?
Vaillancourt
Saya tidak tahu mengapa tetapi masih membutuhkan waktu terlalu lama seperti 1 menit untuk mendapatkan semua huruf yang diperlukan.
Daniyal Azram
@DaniyalAzram Anda mungkin harus meningkatkan frekuensi lagi jika huruf-huruf ini tidak cukup sering muncul, karena sepertinya itulah masalahnya.
JFA

Jawaban:

21

Anda sebenarnya tidak menginginkan distribusi acak. Saya menunjukkan ini secara eksplisit, karena apa yang kita anggap "acak" untuk desain biasanya bukan keacakan yang sebenarnya.

Sekarang, dengan itu dalam pikiran, mari kita tambahkan beberapa nilai tweaker - ini adalah hal-hal yang Anda akan mengutak-atik sampai desain terasa "benar".

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
    }
}

Probabilitas mengontrol seberapa besar kemungkinan panggilan yang diberikan ke ChooseLetter akan memberi Anda huruf kata - di 0,5, Anda akan mendapatkan huruf kata secara kasar setiap waktu. Pada 0,25, satu dari empat akan berupa sepatah kata, dll.

Ini masih agak sederhana - karena keacakan, yah, acak , Anda tidak benar-benar memiliki jaminan berapa lama Anda akan pergi di antara kata-kata. (Secara teori, Anda bisa pergi selamanya tanpa huruf kata, itu sangat sangat tidak mungkin.) Sebaliknya, kita dapat menambahkan faktor untuk meningkatkan kemungkinan kata huruf setiap kali kita tidak mendapatkannya:

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;
    }
}

Oke, jadi sekarang kita tidak pernah pergi lebih dari dua huruf tanpa sepatah kata pun. (Karena, setelah dua kesalahan, kita memiliki probabilitas 1,0 untuk mendapatkan sepatah kata.)

Akhirnya, kita perlu mempertimbangkan bagaimana memilih huruf dalam kata bekerja. Untuk memberikan pemain surat yang benar - benar mereka butuhkan, kita perlu menghapus surat dari set saat mereka mendapatkannya.

Misalnya, jika kata itu adalah "tes", dan pemain sudah memiliki ',' kami tidak ingin memberi mereka 'lain', karena mereka tidak membutuhkannya!

Dari sini, sisanya disesuaikan agar sesuai dengan desain Anda.

ACEfanatic02
sumber
Wow! bagaimana Anda bahkan datang dengan itu?: p Saya akan menguji metode Anda besok pagi dan saya pikir itu akan berhasil, saya akan memberikan lebih banyak umpan balik setelah saya menguji metode ini. Terima kasih banyak atas jawabannya.
Daniyal Azram
4
Statistik! Baik sebagai perancang atau pemrogram game, statistik sangat layak dipelajari. Paling tidak, pemahaman tentang probabilitas (dan cara menggabungkannya) sangat berguna.
ACEfanatic02
1
Datang untuk menyarankan hal yang sama. Jawaban yang bagus Juga perlu diingat, bahwa solusi seperti ini bisa menjadi cara untuk memperkenalkan tingkat kesulitan. Mudah = 0,5, sedang = 0,25, sulit = 0,10. dll
Tasos
Saya tidak setuju bahwa ini tidak acak. Ini IS acak, itu hanya distribusi sedikit demi sedikit sedangkan kita biasanya memikirkan distribusi seragam. Dan untuk menambah ide Anda, saya akan melangkah lebih jauh dari sekadar "Pilih huruf acak dalam kata" Saya akan mendistribusikannya dengan huruf yang paling banyak muncul. Sebagai contoh "mississippi" membutuhkan lebih banyak dan saya jadi pilihlah lebih banyak.
Blaine
21

Anda dapat mempertimbangkan kemungkinan semua huruf Anda sesuai dengan frekuensi kemunculannya dalam bahasa yang digunakan kata-kata Anda. Panduan yang baik adalah kumpulan scrabble . Versi bahasa Inggris, misalnya, memiliki 12 E tetapi hanya satu Z dan satu Q.

Cara sederhana untuk menerapkan ini adalah dengan meletakkan semua huruf dalam string berturut-turut dengan setiap huruf muncul sesering yang diinginkan dan kemudian minta RNG Anda mengambil surat dari posisi acak. Contoh kodesemu:

const String letters = "AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJ/*...and so on...*/"

char randomLetter = letters[randomIntegerBetween(0, letters.length - 1)];
Philipp
sumber
2
+1 Ini adalah konsep yang baik, tetapi saya curiga ada implementasi yang lebih elegan.
Evorlor
Untuk distribusi yang lebih berbutir halus, Anda dapat menyimpan tabel frekuensi huruf yang diskalakan sehingga jumlahnya menjadi 1, menghasilkan angka acak dari 0 hingga 1, dan mengulangi tabel mengurangi frekuensi setiap huruf dari angka acak hingga menjadi nol atau negatif. Anda bahkan dapat mengoptimalkan ini dengan menyortir huruf paling umum terlebih dahulu di tabel. Atau gunakan sesuatu seperti metode alias untuk menghindari perulangan di atas meja sepenuhnya.
Ilmari Karonen
4
Ini tidak akan menyelesaikan masalah. Masalahnya adalah pengguna membutuhkan huruf khusus untuk menyelesaikan permainan. Mengatakan mereka membutuhkan Z? Lalu bagaimana? Ini hanya akan membuat huruf langka lebih sulit untuk membuat pengguna semakin frustrasi.
AmazingDreams
@AmazingDreams menunjukkan hal yang baik, tetapi kita bisa memodifikasinya sedikit sehingga saya akan memberikan bobot lebih untuk abjad yang diperlukan dan lebih sedikit bobot untuk yang lain. Saya harus mengatakan ini adalah konsep yang sangat baik untuk diikuti.
Daniyal Azram
4

Berikut adalah salah satu cara untuk memperbaikinya menggunakan satu parameter tunggal kyang dapat Anda atur.

Alih-alih hanya memilih surat acak:

  1. pilih huruf acak A
  2. pilih nomor acak X
  3. jika X > k dan A tidak ada [list of remaining needed letters], coba lagi pada 1.

Semakin kecil k, semakin sering surat akhir Aakan menjadi salah satu yang benar-benar dibutuhkan.

Untuk mengubah algoritma, mainkan dengan nilai apa pun untuk k, misalnya k = 0.5 . Jika Anda merasa gim ini terlalu sulit, cobalah 0.4, dll. Hingga Anda menemukan nilai yang masuk akal. Ini juga secara langsung memberi Anda pengaturan kesulitan , yang misalnya Anda mungkin ingin meningkat saat pemain maju dalam permainan.

sam hocevar
sumber
Terima kasih atas jawabannya tetapi ini sepertinya jawaban ACEfanatic02.
Daniyal Azram
3

Cara sederhana untuk menjamin bahwa huruf yang diperlukan muncul dalam waktu tertentu adalah dengan menggunakan isi array dengan huruf dalam kata dan sisa alfabet (mungkin diulang), kemudian acak acak array (c ++ has std :: random_shuffle di perpustakaan standar, jika Anda menggunakan bahasa yang berbeda tidak sulit untuk diterapkan).

Jika Anda ingin huruf-huruf dalam kata muncul lebih cepat, masukkan lebih banyak salinan kata-kata dalam array.

GuyRT
sumber
0

Jika Anda menggunakan C ++ Anda bisa menggunakan distribusi yang sudah ada http://en.cppreference.com/w/cpp/numeric/random/piecewise_constant_distribution

Ini juga memiliki amortisasi kompleksitas waktu konstan yang lebih baik daripada metode naif. contoh:

#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';
    }
}
Sopel
sumber