質問: 条件付きの乱数の作り方を質問させてください。 スマホのパズルゲームを製作しております。(初心者、unity5.6使用) 10ピースのパズルがあり、 ゲーム開始時に、パズルピースをシャッフルします。 --- パズルピース |1|2|3|4|5|6|7|8|9|10| スロット |A|B|C|D|E|F|G|H|I|J| --- スロット「A」に対しては「1」が正解でスロット「B」に対しては「2」が正解とします。(同様に「J」まで続く) (スロットは固定で、パズルピースがシャッフルされます) その際に問題になる条件が、 シャッフル時に、偶然に正解位置に割り振られる事を避けたい、という条件です。 つまり、スロット「A」には「1」以外を、スロット「B」には「2」以外を割り振りたいです。 (もちろん数字の重複も避けたいです) この場合、 下記のような、正解位置を避けたシャッフルパターンを手動で作るのがいいでしょうか? 例えば |10|6|2|1|7|8|6|4|5|9| のような数列をあらかじめ5パターンくらい用意して、 それをランダムに使い回すのがいいでしょうか? (自分で作った数列5パターンをシーンロード時に 5パターンの中からランダムにどれかを選択し使用する) または 正解位置を避けながら、なおかつ同じ数字の重複も避けたの乱数の制作はC#で可能でしょうか? ※シーンが進むにつれてパズルのピースは増えて50個~60個になる予定です。 --- **現状のプログラムの状態** 1 まずシャッフルしたパズルピースを実際にシーン上に配置 2 シャッフル時に偶然に正解位置に置かれていないかを、コリジョン判定を利用して調べる 3 偶然に正解があった場合はシーンをリロードして再シャッフル (全部のピースが完全に正解位置を避けるまで何度もシャッフルする) というプログラムを作ったのですが、 この方法ですとスマホの実機上で実行した場合、 特にパズルピースの数が多い場合に、実機のメモリの消費が激しいようなので、 メモリ消費の少ない方法を探しております。 ご教授よろしくおねがいいたします。
回答: 動作未検証&どこまでメモリ消費するか分かりませんが、以下はいかがでしょう? 1. 最初に正解のスロットにピースをはめる。 2. そこから1スロット毎に、別のランダムなスロットとピースを入れ替える。 2-1. ただし入れ替えた結果どちらかのスロットが正解となる時は次のスロットを入れ替え先とする。次のスロットも正解になる場合は更に次のスロットを入れ替え先とする。 2-2. 最後までスロットが選択出来ず、自分のスロットに正解ではないピースが入っていれば2へ戻る。 3. 並び替え後の配列の通りにオブジェクトを配置する。 動作例 ・開始時(正解):分かりやすいように数を減らしています |A-1|B-2|C-3| ↓ ・スロットAのピースと、別のランダムなスロット(Cが選ばれたとする)のピースを入れ替え (どちらも正解ピースではないことをチェック→問題無し) |A-3|B-2|C-1| ↓ ・スロットBのピースと、別のランダムなスロット(Aが選ばれたとする)のピースを入れ替え (どちらも正解ピースではないことをチェック→問題無し) |A-2|B-3|C-1| ↓ ・スロットCのピースと、別のランダムなスロット(Aが選ばれたとする)のピースを入れ替え Aと入れ替えるとAが正解になってしまうので次のスロットを見る →Bと入れ替えるとCが正解になってしまうので次のスロットを見る →最後のスロットまで来たが、スロットC(自分自身)が正解ではないので問題無し(入れ替えはしない) |A-2|B-3|C-1| ↓ ・全てのスロットを入れ替え終わったのでループ処理終了 ↓ ・出来上がった順にピースを配置すればOK |2|3|1| ※速度や負荷を考慮すると入れ替え前に「現在のスロットに入っているピースが正解ではない場合、入れ替えを行わない」という判定を入れてもいいかもしれません。 ※下手にやると「終了しない処理」になりそうなのでご注意ください。「n回ループしてたら最初からやり直し」とか必要かも。