QA@IT

javascript完全に行き詰まりました。助けてください! 要素31個の配列をランダムで重複なしに出力し、31回ボタンを押すと出力が終わるプログラム

9830 PV

教師である母のために役立つプログラムを書いているのですが、どれだけ試行錯誤しても分かりません。enter link description here。学校のクラスの人数31人をランダムで一人指名するプログラムです。一人一回指名され、31回目で全員が発言するようにしたいのですが、今のままだと同じ人を何回か指名することがあり、重複しないようにしたいのですが、どうしても表現できません。かなり情弱でして、関数や変数の名前もぐちゃぐちゃですが、重複せずランダムで数字(出席番号)を出力するプログラムを作りたいです。そこで、僕に代わって書いてください。お願いします!自分だと永遠に書けません!
自分の書いたプログラムはどれも複雑なものは無いですが一応説明させていただくと、

関数choice : 変数r,配列liRandom,変数rがとる値によって変わるif文31個がある

変数r : 配列liRandomのlengthの範囲でランダムに取りうる数字+1が代入される。

配列liRandom : iZero~iThirtyが入っている。 配列liRandomは0~30、合計31,変数rは1~31、合計31です。rが1の時liRandomは0の関係にあり、rが31の時liRandomはundefinedなのですが、エラーを抑制するにはこれがベストだと思います。

id zOne~zThirtyOne : 生徒の席を表に表していて、一席ずつzOne,zTwoとidを振っている。変数rが選んだ席をチェックするため

id a1~a31 : 変数rが選んだ結果を履歴として残しておくために用意した。document.getElementで変数rに書き換える

配列littleOut : これに変数rが選んだ値を先頭に追加していくと、、配列の2番目、3番目は前に引き当てた数字になる。最初から2番目3番目は無いのでundefinedになるが、if文でundefinedを空白に書き換えている

id subText,threeText : 一回前と二回前まで自分が押した数字を確認できるように配列littleOutの2番目、3番目をこのidに出力する

こんなところです。できるだけ原型を残すスタンスでお願いします。回答お願いします。(土下座100回のつもり)

回答

同じような質問があったので、手法をもう一つ。
「31人からランダムに1人選んで、元のリストから削除して別のリストに入れるを31回繰り返す」でもOK。
JavaScript はすっかり忘れたので、C# で。

// 0~30 が入ったリストを用意する
List<int> source = new List<int>();
for (int i = 0; i < 31; ++i)
{
    source.Add(i);
}

List<int> dest = new List<int>();
Random rnd = new Random();

// source の内容を、ランダムに dest に並べ(移し)替える
while (source.Length > 0)    // source が空になるまで続ける
{
    int index = rnd.Next(source.Length);  // source に残っている中から1つ選ぶ
    dest.Add(source[index]);  // destに入れて
    source.RemoveAt(index);   // sourceから削除
}
編集 履歴 (0)

ちゃんとは見ていませんが、どうしようも無い感じのコードです。
idはz1~z30のようにしましょう。
同じような記述を繰り返さないで済むようにしましょう。

下記で、x[0]~x[29]に重複の無い1~30の乱数が入ります。参考にしてください。

var x =[];
for(var i=0; i<30; i++){
    do{
        var r = Math.floor(Math.random()*30)+1;
        for(var j=0; j<i; j++){
            if(x[j]==r) break;
        }
    }while(j<i);
    x[i] = r;
}
編集 履歴 (0)
  • ありがとうございます! -

「31人から、31回、重複なしに、ランダムに選ぶ」という考え方を変えれば簡単です。
「31人をランダムに並べ替え、前から順番に全員選ぶ」とすればできるでしょ?つまり、31人からランダムに2つ選び(これは同じでないことを保証する)、入れ替えるという作業をn回行います。

編集 履歴 (0)
  • おお!、確かにそうですね。少しテストしたのですが望んだ結果になりました。これだと自分でも書けるので最高です。最初に配列arrayに1~31を宣言しランダムに並び替え、変数iに1を代入。関数myFunctionにi++とiの値によって変えるifの処理でarrayの先頭、2番目、3番目....を取得、表示すれば簡単かつ完璧です。教えていただきありがとうございます! -
ウォッチ

この質問への回答やコメントをメールでお知らせします。