擬似ランダムではなく、「楽しく」ランダムに生成するにはどうすればよいですか?


26

さまざまな種類のパズルを順番に提示するゲームを作っています。擬似乱数で各パズルを選択します。各パズルには、多くのバリエーションがあります。別の擬似乱数でバリエーションを選択します。等々。

問題は、これがほぼ真のランダム性を生み出す一方で、これはプレイヤーが本当に望んでいることではないということです。プレイヤーは通常、自分が何であるかを認識し、ランダムであると特定しますが、それはパズルを繰り返す傾向がない場合のみです。だから、本当にランダムではありません。ただ予測不可​​能です。

少し考えてみると、それを行うためのハックな方法が想像できます。たとえば、新しい選択肢を選択するときに、可能性のあるセットから最新のN個の選択肢を一時的に削除します。または、すべての選択肢に等しい確率を割り当て、選択時に選択肢の確率をゼロに減らしてから、選択ごとにすべての確率をゆっくりと増やします。

これを行う確立された方法があると思いますが、用語がわからないので見つけることができません。知ってる?または、誰かがこれを楽しい方法で解決しましたか?


4
「AI Game Programming Wisdom 2」という本には、フィルタリングされたランダム性に関する章があります。これは、私が思い出す限り、まさにあなたが探しているものです。現時点ではそれがありませんので、完全に答えることはできません。
アントン

明確にするために:「パズルを繰り返さない」と言うとき、同じタイプの2つのパズルを隣り合わせたくないということですか?つまり、数独を選んだ場合、別の数独パズルを提供しないでください。それが数独#19の場合、次にピクロス#19を提供しても構いません(つまり、バリエーション番号は重要ではありません) ?
スティーブンスタドニッキー


1
OK、AIゲームプログラミングの知恵2のコピーが到着しました。フィルター処理されたランダム性に関する章を読み、ソースコードをチェックアウトしました。これがおそらく最良のアプローチです。乱数を使用するだけで、予期しないパターンが発生しないように数値をフィルタリングできます。シャッフルバッグよりも防弾効果があるようです。
ヒルトンキャンベル

1
さらに別の更新...私の特定のアプリケーションでは、フィルター処理されたランダム性ではうまくいきませんでした。プレイヤーに繰り返しの前にすべてのタイプとサブタイプをプレイしてもらいたいので、シャッフルバッグを使用しました。
ヒルトンキャンベル

回答:


25

パズルの数に限りがある場合、次のことができます。

  • すべてのパズルまたはランダムに選択したパズルのリストを作成します。
  • このリストをシャッフルします(たとえば、Knuth Shuffleを参照)。
  • プレイヤーにこのリストをプレイさせます。
  • リストが空になったら、新しいリストから始めます。

編集

私はこれを知りませんでしたが、SEをブラウズすると、これが実際に「シャッフルバッグ」として知られていることに気づきました。ここここ、またはそこにいくつかの情報があります。

編集2

古典的なKnuth Shuffleは次のようになります。

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は、この種のことはシャッフルの繰り返しを妨げるものではないとコメントで正しく指摘しました。これを考慮する方法は、最後のアイテムに特別なケースを追加することです:

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
これは機能する可能性がありますが、プレイスルーのたびにシャッフルする場合は、終了した同じアイテムで開始しないように少し注意する必要があります。
スティーブンスタドニッキー

@Steven確かに。このアイテムは新しいリストから除外できます。実際には、いくつかのランダムなアイテムのみのリストを作成し、残りのアイテムのみで次のリストを作成することが考えられます。したがって、100個のアイテムがある場合は、たとえば10のシャッフルリストを作成します。このリストを使用して、90個のうち10個のアイテムが選択されていない次のものを作成します。
ローランクーヴィドゥー

+1。「もっと楽しい」このテクニックのサポートが追加されました。これは、たとえばテトリスが「ランダムな」ピースを生成する方法です。各ピースの1つのセットがシャッフルされ、繰り返し処理されます。これにより、真のランダム性が必然的に生成する重複の長いシーケンスが回避されます。
KutuluMike

1
@Hilton私は、この種の「ランダムになるまでwhileループが私に欲しいものを与える」アプローチを嫌う傾向があります...これが問題を引き起こす可能性はほとんどありません。それでも、私は常にこれがランダムな無限ループまたはパフォーマンス低下の呼び出しであると感じています-デバッグするにはひどいです。前のリストの最後の項目を新しいリストから除外すると、同じ結果を得るために一度だけシャッフルできます。
ローランクーヴィドゥ

1
あなたは正しいです、そして私は同じ予約をしました。前の最後のアイテムを除外するのではなく、一度シャッフルするだけで、前の最後のアイテムが最初になった場合、他のアイテムとランダムに交換します。
ヒルトンキャンベル

2

lorancouのアプローチの変形:パズルの種類ごとに、(シャッフルされた)パズル番号の配列を保持します。その後、そのタイプのパズルをヒットするたびに、リストから次の数字を取得します。たとえば、数独パズル、ピクロスパズル、ケンケンパズルがあり、それぞれにパズル#1..6があるとします。パズルの種類ごとに1つずつ、3つのシャッフルされた数字の1..6の配列を作成します。

  • 数独:[5、6、1、3、4、2]
  • ピクロス:[6、2、4、1、3、5]
  • ケンケン:[3、2、5、6、4、1]

これで、lorancuが示唆するように、パズルの種類をシャッフルします。[Picross、Sudoku、Kenken]と表示されたとしましょう。次に、特定のタイプのパズルをヒットするたびに、その「シャッフルリスト」の次の番号を使用します。全体として、パズルプレゼンテーションは[数独#5、ピクロス#6、ケンケン#3、数独#6、ピクロス#2、ケンケン#2、...]になります。

ループのたびに同じ全体的な順序でパズルを保持したくない場合は、「ランダムに選択し、最後のいくつかのピックを無視する」オプションが最適だと思います。これをもう少し効率的にする方法もあります。たとえば、20個のアイテムがあり、最後に選択した5個を無視したいとします。その後、ランダムに数字1..20を選択して最後の5以外の数字を取得するまで「リロール」する代わりに、数字1..15を選択してパズルタイプを何歩も歩き、パズルタイプをスキップします選択された(最後に選択された5つのパズルを保持するビット配列を保持することにより、これを簡単に行うことができます)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.