- ベストアンサー
問題がランダムに出るクイズ
制作環境:FlashMX2004 用意する質問は15問程度用意し、実際に回答する問題数は8問程度で、アクセスのたびに15問の中から8問の問題がランダムに出るというクイズをつくりたいと思っています。 クイズの問題を外部swfファイルにするか、1つのswfファイル内で完結するほうが良いのかは、作り易い方で制作したいと考えております。 特にわからないところは15問の問題からランダムに8つの問題を抽出して取り扱う方法です。 ご存知の方がおられましたら、お教えください。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
どこまで考えて,どこで行き詰まったのでしょうか? そこが大切なポイントです。 書かれていることは,複数の要素を組み合わせて実現していくことです。 1つ1つの要素を作っていって,詰まった部分を明白にしないと,自力では先に進めません。 また,質問としても少し要素が多いです一応1つの例を挙げるという形のものでしたら回答可能ですが, 回答できるギリギリの範囲です。 説明の都合上,最後から説明します。 ほとんど明白にわかるところは, 普通に考えると, >> クイズの問題を外部swfファイルにするか、 → Movieclip.loadMovie("ランダム.swf"); >> 1つのswfファイル内で完結する → Movieclip.gotoAndStop(ランダムフレーム数); のどちらかだろうということです。 だから,もし,外部swfファイルにするのでしたら, もしランダムな数が 4 と出たら, 「4.swf」とか「question4.swf」とか「q4.swf」などを読み込めば良いことになりますから, 「qMC」というインスタンス名のムービークリップを _root. に用意した場合 例えばボタンのスクリプトだと, on (release) { _root.qMC.loadMovie("q4.swf"); } となります。 あとは 4 なら 4 をランダムに出せばいいのです。 ランダム動作は ActionScript に限らずどの言語でも同じです。 結局ランダムな数を出してその数から何かをするだけです。 ここまではよろしいのでしょうか? あと,いちいち2つの場合を書けませんから, 以下も loadMovie の方で説明を書きます。 スクリプトは全てコピペで使用可能だと思います。 ==================================== とりあえず, 外部に 「q0.swf」~「q14.swf」 という問題ムービー(15ファイル)を用意してください。 (試しですから,それぞれ 0 ~ 14 の数字が書いてあるだけのSWFファイルでもかまいません。) そして,それをロードする親ムービーの方ですが, 「q0.swf」~「q14.swf」 と同じフォルダに用意するものとします。 まず, それらの問題をロードするムービークリップを _root(メインムービーのステージ上)に用意してください。 用意のしかたですが, 白い一辺 5mm くらいの塗りを描いて,それをムービークリップに変換して, ステージの左上の角くらいに配置します。 その場所が 「q0.swf」~「q14.swf」 の左上のコーナーが来る位置になります。 そしてそのムービークリップに 「qMC」 というインスタンス名を付けてください。 そして,同じく _root に問題を次々に読み込ませるボタン(ボタンシンボル)を作成してください。 ここまでできたら やっと,ActionScript がやっと書ける状態です。 以下スクリプト例ですが, 説明の為にも,スクリプトは徐々に進化させます。 実際にプログラミングするにはこのような手順を踏むという説明にもなると思います。 ◎ 読み込み実験 上の状況がちゃんとできているかどうか,とりあえず動作検証をします。 ボタンに次のようなスクリプトを書きます。 ---_root に置いたボタンのスクリプト-------------- on (release) { // 「qMC」 に 「q0.swf」 をロード _root.qMC.loadMovie("q0.swf"); } ----------------------------------------- ステージ上に,「q0.swf」が無事表示されたら成功です。 読み込まれなければ,「インスタンス名」や「ファイル名」や「パス」を点検します。 一応読み込まれる問題の 「q0.swf」~「q14.swf」 の方が, 親ムービーよりも小さいという想定をしています。 問題によってボタンが隠れたりするようでしたら, 「qMC」 の位置や大きさを調節してください。 次にランダム関数です。 ◎ ランダムに問題を表示させる ---_root に置いたボタンのスクリプト-------------- on (release) { // 変数qNum に0~14(15個)のうちいずれかの数を代入 qNum = Math.floor(Math.random()*15); // 「qMC」 に 「q?.swf」 をロード _root.qMC.loadMovie("q"+qNum+".swf"); } ------------------------------------------ 詳細はこのあたりを参考にしてください↓。 ---Flash TechNote--- 「Math.random() でランダムな整数を取得する方法」 http://www.adobe.com/jp/support/flash/ts/documents/fl0173.html 実際にやってみるとわかりますが, 上のスクリプトだとボタンをクリックする度に永遠に問題が表示されます。 >> 8つの問題を抽出して取り扱う ができていません。 つぎに8問に制限をします。 ◎ ランダムに8つの問題を表示させる ---フレーム1のスクリプト------------------------ // 変数k の初期値を設定 k = 1; ------------------------------------------ ---_root に置いたボタンのスクリプト-------------- on (release) { // もし k が 8 以下であれば if (k<=8) { // 変数qNum に0~14(15個)のうちいずれかの数を代入 qNum = Math.floor(Math.random()*15); // 「qMC」 に 「q?.swf」 をロード _root.qMC.loadMovie("q"+qNum+".swf"); // k に 1 を加算する k++; } else { // ←問題終了時の動作を書く } } ------------------------------------------ フレームに 変数 k というもの(カウンター的役割)を用意して, ボタンがクリックさせる度にその k の値を +1 するようにしています。 k が 8 になるまで,ランダムな問題を出題します。 「// ←問題終了時の動作を書く」 の部分は,こちらではどうするのかわかりませんから考えてください。 だいたい,普通の方ならここぐらいまではできるのではないかと思います。 最初に, どこまで考えて,どこで行き詰まったのでしょうか? そこが大切なポイントです。 と書いたのは, ここら辺まではうまくできたのだけど, この先で詰まったのかなと思ったのが,書いた理由の1つです。 上のスクリプトには大きな欠陥があります。 単に 15問 なら 15問 の中からランダムに問題を抽出しているので, 「q1.swf」→「q8.swf」→「q1.swf」→「q1.swf」→「q13.swf」… とロードされる可能性もあります。 つまり何度でも同じ問題が出題される可能性があります。 単語カードのようなものでしたら,むしろこのままの方が良いような気もします。 しかし,ちゃんとした問題だとこれではまずいと思うので, 何度でも同じ問題が出題されない方法を考えねばなりません。 数学に強い人なら, この点はすぐにクリアされるのでしょうけど,私はすぐにはクリアできませんでした。 数年前にここで詰まって,趣味で作っていたものですが,それを一度あきらめたことがあります。 でも,その1ヶ月後くらいに, 思わぬところで思わぬもの(Excelファイル)に出会えたので, スルッとクリアすることができました。 詳細はこちらに書いています↓。 「質問:長方形がランダムに消えるやつ」 http://oshiete1.goo.ne.jp/kotaeru.php3?q=2070264 ↑教えて!goo ↓OKWave (同じです) http://okwave.jp/kotaeru.php3?q=2070264 上のURLには, 以下のようなスクリプトが書いてあります(インデントを付けました)。 //---重複を許さない順列の作成---// // randArrという配列を作成 randArr = new Array(); // randArrの1~nの要素(エレメント)に乱数を取得 for (i=0; i<n; i++) { randArr[i] = Math.random(); } // permArrという配列を作成 permArr = new Array(); // permArrの要素を初期化 for (i=0; i<n; i++) { permArr[i] = 0; } // randArr の各要素に入った数の // 大きさの順を permArr の要素に並べる for (j=0; j<n; j++) { for (i=0; i<n; i++) { if (randArr[j]>=randArr[i]) { permArr[j] += 1; } } } これを使います。 ◎ ランダムに8つの問題を重複せずに表示させる ---フレーム1のスクリプト------------------------ // 全問題数を設定(可変) n = 15; // 抽出問題数の設定(可変) kMax = 8; // k の初期値を設定 k = 1; //---重複を許さない順列の作成---// // randArrという配列を作成 randArr = new Array(); // randArrの1~nの要素(エレメント)に乱数を取得 for (i=0; i<n; i++) { randArr[i] = Math.random(); } // permArrという配列を作成 permArr = new Array(); // permArrの要素を初期化 for (i=0; i<n; i++) { permArr[i] = 0; } // randArr の各要素に入った数の // 大きさの順を permArr の要素に並べる for (j=0; j<n; j++) { for (i=0; i<n; i++) { if (randArr[j]>=randArr[i]) { permArr[j] += 1; } } } ----------------------------------------- ---_root に置いたボタンのスクリプト-------------- on (release) { // もし k1 が kMax 以下であれば if (k<=kMax) { // 「qMC」 に 「q?.swf」 をロード _root.qMC.loadMovie("q"+(permArr[k]-1)+".swf"); // k に 1 を加算する k++; } else { // ←問題終了時の動作を書く } } ----------------------------------------- 最初にこのスクリプトを出しても, 全然意味がわからないと思うので, 順を追ってスクリプトを進化させる説明方法を取りました。 最後に出しても意味がわからないかもしれませんが, なぜこんなに複雑なスクリプトになるのかという理由と, 開発手順は理解しやすいと思います。 重複を許さない順列の作成 方法はまだ他にもあります。 もっと質の良い重複しない順列を,もっと簡素なコードにする方法を考えてみるのも面白いと思います。 以上のような具合に, 1要素1要素,確実に片付けて行ってください。 そして,どの要素がわからないのかを自分で突き止めてください。 そうでないと,書かれているような問題出題マシーンはできません。 それと, loadMovie の方を選んだのは,gotoAndStop よりお薦めだからです。 問題が増えた場合,もしくは問題を入れ替えたい場合に, loadMovie の方がメンテナンスがしやすいです。 上に書いた,変える部分(変わる可能性がある部分) ---フレーム1のスクリプト--------------------- // 全問題数を設定(可変) n = 15; // 抽出問題数の設定(可変) kMax = 8; は,一応ここに固めていますが, フレームに問題数設定を用意しておくのではなく, 外部テキストファイルに用意しておいて,それを親ムービーから読み込む形にすれば, 親ムービーを触ることなく,問題追加や問題数変更ができます。 簡単に言うと「出題システム」と「問題データ」と「システム管理データ」とを分ける形です。 そういう形をとると, 国語問題,理科問題,算数問題など色々な問題に対して システムを変えることなく,ひたすら問題データファイルを作成し続けられます。 効率的です。 問題出題システムというのは,少し大きなものであれば, Flash に限らずたいていそういう形でできています。 またそうしておくと, データ作成屋さん(クイズの専門家)とシステム開発屋さん(プログラミングの専門家)に分業することもできます。 (実は私の本職は Flash とは少ししか関係がない,問題データ作成屋さんだったりします。)
その他の回答 (1)
- perse
- ベストアンサー率74% (113/152)
配列のシャッフルを用いた方法です。 問題用と答え用の配列を用意します。 問題と回答は配列の番号で対応しています。例えばqes[4]の回答はans[4]です。 問題配列、答え配列をそれぞれシャッフルします。 あとは配列の先頭から必要な問題数を取り出すだけです。 シャッフルの仕方は配列の要素をランダムに2つ選んでその2つを入替えています。 これを数回繰り返すことで配列内の要素がランダムに並び変わります。 var qes = new Array(); var ans = new Array(); //問題 qes[0] = "質問0"; qes[1] = "質問1"; qes[2] = "質問2"; qes[3] = "質問3"; qes[4] = "質問4"; qes[5] = "質問5"; qes[6] = "質問6"; qes[7] = "質問7"; qes[8] = "質問8"; qes[9] = "質問9"; //答え ans[0] = "答え0"; ans[1] = "答え1"; ans[2] = "答え2"; ans[3] = "答え3"; ans[4] = "答え4"; ans[5] = "答え5"; ans[6] = "答え6"; ans[7] = "答え7"; ans[8] = "答え8"; ans[9] = "答え9"; // //配列のシャッフル(要素の入替) //シャッフルする回数 var maze = 10; for (var i = 0; i<maze; i++) { rnd1 = Math.floor(Math.random()*qes.length); rnd2 = Math.floor(Math.random()*qes.length); tmp1 = qes[rnd1]; tmp2 = ans[rnd1]; qes[rnd1] = qes[rnd2]; ans[rnd1] = ans[rnd2]; qes[rnd2] = tmp1; ans[rnd2] = tmp2; } //確認表示 var mondai = 5; for (var i = 0; i<=mondai; i++) { trace(qes[i]); trace(ans[i]); }
補足
返事が大変遅くなりすみませんでした。 なるほど、Perlでいうところのハッシュのような使い方をするわけですね。 今回は使いませんでしたが大変参考になりました。
補足
返答が遅くなり本当にすみませんでした。 丁寧なご回答で、ActionScript初心者の私でも、なんとか理解することが出来ました。今回は更新がほとんどないものでしたので、結局ひとつのファイルで作成することになりましたが、次回以降のとても良い参考になりました。 ありがとうございました。