Làm thế nào để cải thiện việc tạo số ngẫu nhiên này trong ngữ cảnh của tôi?


11

Trong trò chơi của tôi có một từ ở phía trên màn hình, các chữ cái đang mưa từ trên xuống và người dùng phải chạm vào các chữ cái để hoàn thành từ đó.

Hiện tại tôi đang tạo các chữ cái ngẫu nhiên (thực tế số và số ngẫu nhiên là chỉ số cho mảng các chữ cái. Ví dụ: 0 = a, 1 = b) nhưng vấn đề là phải mất quá nhiều thời gian để có được tất cả các chữ cái cần thiết để hoàn thành từ.

Điều tôi muốn là các số ngẫu nhiên mà tôi đang tạo sẽ tạo ra các chữ cái cần thiết thường xuyên hơn để người chơi không phải dành cả ngày để hoàn thành một từ.

Tôi đã thử các phương pháp sau:

  1. Phát hiện tất cả các chữ cái trong từ (từ luôn dài 6 chữ cái), tạo ra mảng chỉ số có độ dài 6, gán từng chỉ số của mảng cho số ngẫu nhiên từ chữ-2 đến chữ + 2 và cuối cùng chọn ngẫu nhiên một chỉ mục từ mảng để hiển thị.

  2. Có một biến chọn có giá trị nằm trong phạm vi [0..2], được tạo ngẫu nhiên, nếu bộ chọn == 0 thì phát hiện các chữ cái tạo ra từ đó và chọn ngẫu nhiên một chữ cái, khác ngẫu nhiên lấy bất kỳ bảng chữ cái nào từ az.

Cả hai phương pháp này đều không cung cấp cho tôi bất kỳ trợ giúp nào. Tôi sẽ rất hạnh phúc nếu bạn có thể giúp tôi.

Cảm ơn đã đọc nó, tôi hy vọng bạn hiểu câu hỏi và tôi đang chờ câu trả lời.


2
"Cả hai phương pháp này đều không cung cấp cho tôi bất kỳ trợ giúp nào" Tại sao không? Điều gì đã không làm việc với các phương pháp này?
Vaillancourt

Tôi không biết tại sao nhưng vẫn mất quá nhiều thời gian như 1 phút để có được tất cả các bảng chữ cái được yêu cầu.
Daniyal Azram

@DaniyalAzram có lẽ bạn nên tăng tần suất thêm một chút nếu những chữ cái này không xuất hiện thường xuyên, vì có vẻ như đó là vấn đề của bạn.
JFA

Câu trả lời:


21

Bạn không thực sự muốn một phân phối ngẫu nhiên. Tôi chỉ ra điều này một cách rõ ràng, bởi vì những gì chúng ta coi là "ngẫu nhiên" cho thiết kế thường không phải là sự ngẫu nhiên thực sự.

Bây giờ, với ý nghĩ đó, hãy thêm một số giá trị điều chỉnh - đây là những điều bạn sẽ thích thú cho đến khi thiết kế cảm thấy "đúng".

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

Xác suất kiểm soát khả năng một cuộc gọi nhất định tới PickLetter sẽ cung cấp cho bạn một chữ cái - ở mức 0,5, bạn sẽ nhận được một chữ cái gần như mọi lúc. Tại 0,25, một trong bốn sẽ là một chữ cái, v.v.

Điều này vẫn hơi đơn giản - bởi vì tính ngẫu nhiên là, ngẫu nhiên , bạn thực sự không có một sự đảm bảo về thời gian bạn sẽ đi giữa các chữ cái. (Về lý thuyết, bạn có thể đi mãi mãi mà không cần một chữ cái, điều đó rất khó xảy ra.) Thay vào đó, chúng ta có thể thêm một yếu tố để tăng xác suất của một chữ cái mỗi khi chúng ta không nhận được một chữ cái:

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

Được rồi, vì vậy bây giờ chúng tôi không bao giờ đi quá hai chữ cái mà không có một chữ cái. (Bởi vì, sau hai lần bỏ lỡ, chúng tôi có xác suất 1.0 để nhận được một chữ cái.)

Cuối cùng, chúng ta cần xem xét cách chọn chữ cái trong một từ hoạt động. Để cung cấp cho người chơi các chữ cái họ thực sự cần, chúng tôi cần xóa các chữ cái khỏi bộ khi họ nhận được chúng.

Ví dụ: nếu từ đó là "thử nghiệm" và người chơi đã có 's', chúng tôi không muốn cung cấp cho họ 's' khác, vì họ không cần nó!

Từ đây, phần còn lại là điều chỉnh để phù hợp với thiết kế của bạn.


Ồ Làm thế nào mà bạn thậm chí đã đưa ra điều đó ?: p Tôi sẽ kiểm tra phương pháp của bạn vào sáng mai và tôi nghĩ nó sẽ hoạt động, tôi sẽ cung cấp thêm thông tin phản hồi khi tôi kiểm tra mehod này. Cảm ơn bạn rất nhiều vì câu trả lời như vậy.
Daniyal Azram

4
Số liệu thống kê! Là một nhà thiết kế trò chơi hoặc lập trình viên, số liệu thống kê rất đáng để học hỏi. Ít nhất, một sự hiểu biết về xác suất (và cách kết hợp chúng) là vô cùng hữu ích.
ACEfanatic02

1
Hãy đến để đề nghị điều tương tự. Câu trả lời chính xác. Cũng nên nhớ rằng, một giải pháp như thế này có thể là một cách để giới thiệu mức độ khó khăn. Dễ = 0,5, trung bình = 0,25, cứng = 0,10. v.v.
TASos

Tôi không đồng ý rằng điều này không ngẫu nhiên. Đây là ngẫu nhiên, nó chỉ là một phân phối từng phần trong khi chúng ta thường nghĩ về phân phối đồng đều. Và để thêm vào ý tưởng của bạn, tôi sẽ đi xa hơn là "Chọn một chữ cái ngẫu nhiên trong từ" Tôi sẽ phân phối nó bằng các chữ cái xuất hiện nhiều nhất. Ví dụ: "mississippi" cần nhiều hơn và vì vậy tôi chọn nhiều hơn.
Blaine


21

Bạn có thể cân nhắc xác suất của tất cả các chữ cái của bạn theo tần suất xuất hiện trong ngôn ngữ mà từ của bạn đang sử dụng. Một hướng dẫn tốt là tập hợp chữ viết nguệch ngoạc . Ví dụ, phiên bản tiếng Anh có 12 chữ E nhưng chỉ có một chữ Z và một chữ Q.

Một cách đơn giản để thực hiện điều này là bằng cách đặt tất cả các chữ cái trong một chuỗi liên tiếp với mỗi chữ cái xuất hiện thường xuyên như mong muốn và sau đó RNG của bạn lấy một chữ cái từ một vị trí ngẫu nhiên. Ví dụ mã giả:

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

char randomLetter = letters[randomIntegerBetween(0, letters.length - 1)];

2
+1 Đây là một khái niệm tốt, nhưng tôi nghi ngờ có một triển khai thanh lịch hơn.
Evorlor


Để phân phối chi tiết hơn, bạn có thể lưu trữ một bảng tần số chữ cái được chia tỷ lệ sao cho tổng của chúng thành 1, tạo một số ngẫu nhiên từ 0 đến 1 và lặp qua bảng trừ tần số của mỗi chữ cái từ số ngẫu nhiên cho đến khi trở thành số không hoặc âm. Bạn thậm chí có thể tối ưu hóa điều này bằng cách sắp xếp các chữ cái phổ biến nhất đầu tiên trong bảng. Hoặc sử dụng một cái gì đó giống như phương thức bí danh để tránh lặp hoàn toàn trên bảng.
Ilmari Karonen

4
Điều này sẽ không giải quyết vấn đề. Vấn đề là người dùng cần các chữ cái cụ thể để kết thúc trò chơi. Nói rằng họ cần một Z? Sau đó thì sao? Điều này sẽ chỉ làm cho các chữ cái hiếm trở nên khó khăn hơn để làm cho người dùng thậm chí còn thất vọng hơn.
AmazingDreams

@AmazedDreams chỉ ra điều tốt nhưng chúng ta có thể sửa đổi nó một chút vì vậy tôi sẽ gán thêm trọng lượng cho các bảng chữ cái được yêu cầu và giảm trọng lượng cho người khác. Tôi phải nói rằng đây là khái niệm rất tốt để làm theo.
Daniyal Azram

4

Đây là một cách để cải thiện nó bằng một tham số duy nhất k mà bạn có thể điều chỉnh.

Thay vì chỉ chọn một chữ cái ngẫu nhiên:

  1. chọn một lá thư ngẫu nhiên A
  2. chọn một số ngẫu nhiên X
  3. nếu X > k A không ở trong [list of remaining needed letters], hãy thử lại ở 1.

Càng nhỏ k, thư cuối cùng Asẽ càng thường xuyên thực sự cần thiết.

Để điều chỉnh thuật toán, hãy chơi với bất kỳ giá trị nào k, vd k = 0.5 . Nếu bạn thấy trò chơi quá khó, hãy thử 0.4thay vào đó, vv cho đến khi bạn tìm thấy một giá trị hợp lý. Điều này cũng trực tiếp cung cấp cho bạn một cài đặt khó khăn , ví dụ bạn có thể muốn tăng lên khi người chơi tiến lên trong trò chơi.


Cảm ơn câu trả lời nhưng điều này có vẻ giống như câu trả lời của ACEfanatic02.
Daniyal Azram

3

Một cách đơn giản để đảm bảo rằng các chữ cái được yêu cầu hiển thị trong một thời gian nhất định là sử dụng điền vào một mảng với các chữ cái trong từ và phần còn lại của bảng chữ cái (có thể lặp lại), sau đó xáo trộn ngẫu nhiên mảng (c ++ có std :: Random_shuffle trong thư viện chuẩn, nếu bạn đang sử dụng một ngôn ngữ khác thì không khó để thực hiện).

Nếu bạn muốn các chữ cái trong từ hiển thị nhanh hơn, hãy đặt nhiều bản sao của các chữ cái trong mảng.


0

Nếu bạn đang sử dụng C ++, bạn có thể sử dụng bản phân phối đã có sẵn http://en.cppreference.com/w/cpp/numeric/random/piecewise_constant_distribution

Nó cũng được khấu hao theo độ phức tạp thời gian liên tục tốt hơn các phương pháp ngây thơ. thí dụ:

#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';
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.