Làm thế nào để tôi tạo ra một cách ngẫu nhiên một cách thú vị, trái ngược với giả ngẫu nhiên?


26

Tôi đang làm một trò chơi trình bày một số loại câu đố khác nhau theo trình tự. Tôi chọn mỗi câu đố với một số giả danh. Đối với mỗi câu đố, có một số biến thể. Tôi chọn biến thể với một số giả danh khác. Và như vậy.

Vấn đề là, trong khi điều này tạo ra sự ngẫu nhiên gần như thật, đây không phải là điều người chơi thực sự muốn. Người chơi thường muốn những gì họ cảm nhận được và xác định là ngẫu nhiên, nhưng chỉ khi nó không có xu hướng lặp lại các câu đố. Vì vậy, không thực sự ngẫu nhiên. Chỉ là không thể đoán trước.

Suy nghĩ một chút, tôi có thể tưởng tượng ra những cách thức khó khăn để làm điều đó. Ví dụ: tạm thời loại bỏ các lựa chọn N gần đây nhất khỏi tập hợp các khả năng khi chọn một lựa chọn mới. Hoặc chỉ định cho mỗi lựa chọn một xác suất bằng nhau, giảm xác suất của lựa chọn về 0 đối với lựa chọn và sau đó tăng dần tất cả các xác suất với mỗi lựa chọn.

Tôi cho rằng có một cách thiết lập để làm điều này, nhưng tôi không biết thuật ngữ này nên tôi không thể tìm thấy nó. Có ai biết không? Hoặc có ai đã giải quyết điều này một cách dễ chịu?


4
Cuốn sách "Trí tuệ lập trình trò chơi AI 2" có một chương về tính ngẫu nhiên được lọc, từ những gì tôi nhớ lại, chính xác là những gì bạn đang tìm kiếm. Tôi không có nó vào lúc này vì vậy tôi thực sự không thể cho bạn một câu trả lời đầy đủ.
Anton

Để thử và làm rõ: khi bạn nói 'không lặp lại câu đố', bạn có nghĩa là bạn không muốn có hai câu đố cùng loại cạnh nhau? Vì vậy, nói cách khác, nếu bạn vừa chọn một sudoku, đừng đưa ra một câu đố sudoku khác, nhưng nếu đó là Sudoku # 19, thì bạn có thể cung cấp Picross # 19 tiếp theo (nói cách khác, số biến thể không thành vấn đề) ?
Steven Stadnicki


1
OK, bản sao của tôi về Trí tuệ lập trình trò chơi AI 2 đã xuất hiện. Tôi đọc chương về tính ngẫu nhiên được lọc và kiểm tra mã nguồn. Đây có lẽ là cách tiếp cận tốt nhất. Nó cho phép tôi chỉ sử dụng các số ngẫu nhiên, nhưng sau đó lọc các số đó để các mẫu không mong muốn không xảy ra. Có vẻ như nhiều bằng chứng đạn hơn túi shuffle.
Hilton Campbell

1
Một bản cập nhật khác ... cho ứng dụng cụ thể của tôi, tính ngẫu nhiên được lọc không thực hiện được. Tôi thực sự muốn người chơi chơi qua tất cả các loại và kiểu phụ trước khi lặp lại, vì vậy tôi đã đi với một túi xáo trộn.
Hilton Campbell

Câu trả lời:


25

Nếu bạn có số lượng câu đố hữu hạn, bạn có thể:

  • Xây dựng một danh sách các câu đố, hoặc tất cả chúng hoặc một số được chọn ngẫu nhiên;
  • Xáo trộn danh sách này (xem ví dụ Shuffle Shuffle );
  • Hãy để người chơi của bạn chơi qua danh sách này;
  • Khi danh sách trống, bắt đầu với một danh sách mới.

CHỈNH SỬA

Tôi không biết điều này, nhưng duyệt SE khiến tôi nhận ra rằng đây thực sự được gọi là "túi xáo trộn". Một số infos ở đây , ở đây hoặc ở đó .

CHỈNH SỬA 2

Knuth Shuffle cổ điển đi theo cách này:

To shuffle an array a of n elements (indices 0..n-1):
    for i from n  1 down to 1 do
        j  random integer with 0  j  i
        exchange a[j] and a[i]

Steven Stadnicki đã chỉ ra một cách đúng đắn trong bình luận của mình rằng loại điều này không ngăn cản sự lặp lại trên một cải tổ. Một cách để tính đến điều này là thêm một trường hợp đặc biệt cho mục cuối cùng:

To reshuffle an array a of n elements and prevent repetitions (indices 0..n-1):
    return if n <= 2

    // Classic Knuth Shuffle for all items *except* the last one
    for i from n  2 down to 1 do
        j  random integer with 0  j  i
        exchange a[j] and a[i]

    // Special case for the last item
    // Exchange it with an item which is *not* the first one
    r  random integer with 1  r  n - 1
    exchange a[r] and a[n - 1]

1
Điều này có thể hoạt động nhưng bạn phải cẩn thận một chút nếu bạn cải tổ lại sau mỗi lần phát không bắt đầu với cùng một mục bạn đã kết thúc.
Steven Stadnicki

@Steven Thật vậy. Mục này có thể được loại trừ khỏi danh sách mới. Trên thực tế, có thể là một ý tưởng để xây dựng một danh sách chỉ một vài mục ngẫu nhiên và xây dựng danh sách tiếp theo chỉ với các mục còn lại. Vì vậy, nếu bạn có 100 mục, hãy xây dựng, ví dụ: danh sách được xáo trộn gồm 10. Khi hoàn thành với danh sách này, hãy tạo mục tiếp theo với 10 mục trong 90 mục chưa được chọn trước đó.
Laurent Couvidou

+1. Đã thêm hỗ trợ cho kỹ thuật này là "vui hơn": đây là cách Tetris, ví dụ, tạo ra các mảnh "ngẫu nhiên". Một tập hợp của một trong mỗi mảnh được xáo trộn và lặp đi lặp lại, điều này tránh được các chuỗi dài trùng lặp mà sự ngẫu nhiên thực sự chắc chắn sẽ tạo ra.
KutuluMike

1
@Hilton Tôi có xu hướng không thích kiểu tiếp cận "vòng lặp while cho đến khi ngẫu nhiên mang lại cho tôi những gì tôi muốn" ... Không chắc là điều này sẽ gây ra bất kỳ rắc rối nào. Tuy nhiên, tôi luôn cảm thấy như đây là một lời kêu gọi các vòng lặp vô hạn ngẫu nhiên hoặc hiệu suất giảm - rất tệ để gỡ lỗi. Không bao gồm mục cuối cùng của danh sách trước đó từ danh sách mới cho phép bạn xáo trộn chỉ một lần, cho cùng một kết quả.
Laurent Couvidou

1
Bạn nói đúng, và tôi đã có những đặt phòng tương tự. Thay vì loại trừ mục cuối cùng trước đó, bây giờ tôi chỉ cần xáo trộn một lần, và sau đó nếu mục cuối cùng trước đó là đầu tiên, tôi trao đổi ngẫu nhiên với một số mục khác.
Hilton Campbell

2

Một biến thể trong cách tiếp cận của lorancou: đối với mỗi loại câu đố, hãy giữ một dãy các số câu đố (xáo trộn); sau đó mỗi khi bạn trúng một câu đố kiểu đó, hãy lấy số tiếp theo ra khỏi danh sách. ví dụ: giả sử bạn có các câu đố Sudoku, Picross và Kenken, mỗi câu đố có câu đố # 1..6. Bạn sẽ tạo ba mảng xáo trộn của các số 1..6, một cho mỗi loại câu đố:

  • Sudoku: [5, 6, 1, 3, 4, 2]
  • Picross: [6, 2, 4, 1, 3, 5]
  • KenKen: [3, 2, 5, 6, 4, 1]

Bây giờ, bạn sẽ xáo trộn các loại câu đố giống như lorancu gợi ý; giả sử nó xuất hiện [Picross, Sudoku, Kenken]. Sau đó, mỗi khi bạn trúng một câu đố thuộc loại nhất định, hãy sử dụng số tiếp theo trong 'danh sách xáo trộn' của nó; tổng thể bài thuyết trình của bạn sẽ là [Sudoku # 5, Picross # 6, Kenken # 3, Sudoku # 6, Picross # 2, Kenken # 2, ...]

Nếu bạn không muốn giữ các câu đố theo cùng một thứ tự mỗi lần qua vòng lặp, thì tôi nghĩ rằng 'chọn ngẫu nhiên, bỏ qua vài lựa chọn cuối cùng' là lựa chọn tốt nhất. Có nhiều cách bạn có thể làm cho việc này hiệu quả hơn một chút, quá; chẳng hạn, giả sử bạn có 20 thứ và bạn muốn bỏ qua 5 thứ được chọn cuối cùng. Sau đó, thay vì chọn ngẫu nhiên một số 1..20 và 'rerolling' cho đến khi bạn nhận được một số ngoài 5 cuối cùng, thay vào đó chỉ cần chọn một số 1..15 và đi qua các loại câu đố của bạn trong nhiều bước, chỉ cần bỏ qua bất kỳ loại câu đố nào đã được chọn (bạn có thể thực hiện việc này một cách dễ dàng bằng cách giữ một mảng bit chứa 5 câu đố được chọn cuối cùng).

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.