HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2015
0303
ノダッシークイズゲームで選択肢を重複しないようにするには?10未解決


ノダッシー

リンク

2015/3/3(Tue) 15:14:14|NO.67648

フォルダに入っている画像をランダムに1枚表示し
画像が何か答えるクイズゲームを作っています
答えはファイル名から抽出し3択という仕様です

例:ハードディスクの画像が表示されたら
1.ハードディスク
2.メモリ
3.CPU
といった具合にしたいのですが、今のコードですと

1.ハードディスク.jpg
2.ハードディスク.jpg
3.メモリ.jpg

答えが被ってしまうことがあります。

被らないようにするにはどのように修正するのがいいでしょうか?
よろしくお願いします



#include "hsp3util.as" ;フォント命令を使うのに使用
;準備
celload "waku.png",1
x=30 : y=490

randomize
currentdir = dir_cur

dir = "写真\\" ;パスの\を\\に変えるのを忘れずに
chdir dir ;カレントフォルダの移動

list = ""
dirlist list,"*.jpg",1;写真フォルダのファイル名一覧を取得
filenum = stat ;取得したファイル数//17

;chdir currentdir ;実行ファイルのあるカレントディレクトリに移動する。 C:Userizutani\Desktop\問題


notesel list

*問題
time = 0
noteget filename,rnd(filenum)
picload filename

pos 10,420
gmode 2
celput 1 ;ウインドウコピー
pos 30,460
color 255,255,255
text 100 : font "MS Pゴシック", 30, 1
color 255,0,0
emes "これは何ですか?"
pos 0,0
location = rnd(3)+1 ;問題の位置をランダムに変える
gosub *monndai
gosub *選択待ち
gosub *判定
goto *問題
stop

*選択待ち
ans = 0
pos 300,500
getkey key1,97 ; テンキー「1」の入力チェック
getkey key2,98 ; テンキー「2」の入力チェック
getkey key3,99 ; テンキー「3」の入力チェック

wait 10
TIME ++ ;問題を解くのに掛った時間
title "タイマー" + TIME;残り時間を表示


if key1=1{ ; キー「1」が押されていたら
mes "1番のキーが押されました"
ans = 1 ; 解答は1
return
}
if key2=1{ ; キー「2」が押されていたら
mes "2番のキーが押されました"
ans = 2 ; 解答は2
return
}
if key3=1{ ; キー「2」が押されていたら
mes "3番のキーが押されました"
ans = 3 ; 解答は3
return
}

await 16 ; 待ち時間
goto *選択待ち ; 「*選択待ち」へジャンプ

*判定
if( ans == location) : mes "正解"
await 100
return

*monndai
color 255,255,255
if( location = 1 ) : pos 30,490 : mes filename + "←"
if( location = 2 ) : pos 30,520 : mes filename + "←"
if( location = 3 ) : pos 30,550 : mes filename + "←"
*monndai2
y+=30
pos x,y
noteget filename2,rnd(filenum)
if( filename2 == filename ) : goto *monndai2
if( location = 1 ) : pos 30,520 : mes filename2
if( location = 2 ) : pos 30,550 : mes filename2
if( location = 3 ) : pos 30,490 : mes filename2

*monndai3
y+=30
noteget filename3,rnd(filenum)
if( filename3 == filename2 ) : goto *monndai3
if( filename3 == filename ) : goto *monndai3
if( location = 1 ) : pos 30,550 : mes filename3
if( location = 2 ) : pos 30,490 : mes filename3
if( location = 3 ) : pos 30,520 : mes filename2
return



この記事に返信する


FunnyMaker

リンク

2015/3/3(Tue) 15:52:47|NO.67649

問題を簡単化して考えましょう。
ファイルがどうの名前がどうのという問題はひとまず忘れて数の問題に落としこみます。
何事もまず数の問題から出発です。(電算機ってそういうものでしょ。)

10個の非負整数 0,1,2,…,9 の中から
rnd 関数を使って3つの数を重複せずにランダム(っぽく)に選び出すだけの手続きを考えてみましょう。

これができれば、10とか3といった数をm,nとして一般化し、作りたいゲームに応用するだけです。
配列変数を利用するとよいでしょう。

[ヒント]
rnd(10)で同じ値が2度以上出たら2度目以降その値は無視して、まだ一度も出たことのない値が出るまで試行を繰り返す。
rndを信用すれば無限ループにはならないはず。

もっとエレガントなやり方もありそうですが、とりあえずこれでやってみてはどうでしょうか?



暇人

リンク

2015/3/3(Tue) 23:22:20|NO.67665

これはランダムよりシャッフルの方が良いと思う

randomize notesel list dirlist list,"*.jpg",1 filenum = stat mes list repeat filenum //シャッフル noteget filename,cnt notedel cnt noteadd filename,rnd(filenum),0 loop pos 200,0 mes list



FunnyMaker

リンク

2015/3/4(Wed) 00:00:22|NO.67668

>暇人 さん

お見事です。
note系命令はそういうところが便利ですからね。

>ノダッシー さん

一番最初に与えたヒントでは実はマズいのです。
母集団の要素数が10000、サンプル数が9000等のように大きな数になってくると
無限ループを回避できても、フリーズの危険が出てきます。

ノダッシー さんに気づいて突っ込んでほしかったのですが、正解が提示されてしまったのでこのへんにしときます。

ちなみに、配列でシャッフルするならmemcpyがおすすめです。
repeat〜loopで1要素ずつスライドするより低コストです。

また、シャッフルでなくてもランダム入れ替えという手もあります。
母集団から重複を許してランダムに2つ要素を選んで入れ替えるという操作を適当回数(サンプル数/2 + 1 回くらいでいいんじゃないでしょうか)繰り返してください。



ノダッシー

リンク

2015/3/4(Wed) 13:15:06|NO.67671

FunnyMakerさん暇人さん返信ありがとうございます
暇人さんの提示して頂いたシャッフルを使えば問題をダブらずに出題できるところまでは出来たのですが
解答(ファイル名から3つ抽出)を被らないようにするにはどうしたらいいでしょうか?
文字列の比較または、他に方法がありましたお願いします

フォルダには
1_ハードディスク.jpg
2_ハードディスク.jpg
3_aキバン.jpg
4_aキバン.jpg
5_aキバン.jpg
6_bキバン.jpg
7_bキバン.jpg
8_cキバン.jpg
9_スクラップ.jpg
10_スクラップ.jpg
11_プラスチック.jpg
12_プラスチック.jpg
13_プラスチック.jpg
14_プラスチック.jpg
15_フレキ.jpg
16_ゴウキン.jpg
17_ゴウキン.jpg
と、今後も追加する予定です



ノダッシー

リンク

2015/3/4(Wed) 13:18:32|NO.67672

この場合
ハードディスクの画像が表示され
選択肢に
1_ハードディスク.jpg
2_ハードディスク.jpg
12_プラスチック
のようにハードディスクが2つ出てしまうのが好ましくありません
設計をこうした方がいい等アドバイス的なものでも構わないので何かありましたらご教示下さい



FunnyMaker

リンク

2015/3/4(Wed) 13:29:35|NO.67673

ん? なんか不思議ですね。
例えば、
「1_ハードディスク.jpg」と「2_ハードディスク.jpg」の「1」,「2」というのはどういう意味ですか?

問題番号のことですか?



y.tack

リンク

2015/3/4(Wed) 16:43:13|NO.67675

識別子2個で区別したらどうですか?
1_A_ハードディスク.jpg
2_A_ハードディスク.jpg
として"_"でsplitかけるみたいな



y.tack

リンク

2015/3/4(Wed) 17:14:22|NO.67676

識別子2個あるのもあるみたいなんで識別子3個にするとか

1_A_x_ハードディスク.jpg
2_A_x_ハードディスク.jpg
3_B_a_キバン.jpg
4_B_a_キバン.jpg
5_B_a_キバン.jpg
6_C_b_キバン.jpg
7_C_b_キバン.jpg
8_D_c_キバン.jpg
9_E_x_スクラップ.jpg
10_E_x_スクラップ.jpg
11_E_x_プラスチック.jpg
12_E_x_プラスチック.jpg
13_E_x_プラスチック.jpg
14_E_x_プラスチック.jpg
15_F_x_フレキ.jpg
16_G_x_ゴウキン.jpg
17_G_x_ゴウキン.jpg



暇人

リンク

2015/3/4(Wed) 20:00:20|NO.67691

シャッフルでもやってるが
選択肢として使ったのはnotedelで削除しちゃえば良い

font "MS Pゴシック", 30, 1 randomize notesel list dirlist list,"*.jpg",1 filenum = stat repeat filenum //シャッフル noteget filename,cnt notedel cnt noteadd filename,rnd(filenum),0 loop mno=0 *問題 if mno=filenum {title "正解数"+anscnt+"/"+filenum+" 終了":stop} notesel list title "問題数"+(mno+1)+"/"+filenum noteget filename,mno gradf 0,0,640,480,1,$004488,$112244 //picload filename list_tmp=list //一旦リストをコピー notesel list_tmp //note系を使うので notedel mno //問題に使ったのは削除 dmans=rnd(notemax) //不正解の選択肢ナンバー noteget filename2,dmans //不正解の名前 notedel dmans //取り出したので削除 dmans=rnd(notemax) noteget filename3,dmans color 255,0,0 pos 50,200 mes "これは何ですか?" color 255,255,255 location = rnd(3)+1 ;問題の位置をランダムに変える repeat 3 pos 30,300+((cnt+location-1)\3)*30 if cnt=0 {mes filename+"←"} if cnt=1 {mes filename2} if cnt=2 {mes filename3} loop TIME=0 repeat wait 10 title "正解数"+anscnt+"/"+filenum+" タイム "+TIME TIME++ getkey key1,97 ; テンキー「1」の入力チェック getkey key2,98 ; テンキー「2」の入力チェック getkey key3,99 ; テンキー「3」の入力チェック pos 0,420 if key1=1{ ; キー「1」が押されていたら mes "1番のキーが押されました" ans = 1 ; 解答は1 break } if key2=1{ ; キー「2」が押されていたら mes "2番のキーが押されました" ans = 2 ; 解答は2 break } if key3=1{ ; キー「2」が押されていたら mes "3番のキーが押されました" ans = 3 ; 解答は3 break } loop if( ans == location) {mes "正解":anscnt++}else{mes "不正解"} await 1000 mno++ //次の問題にシフト goto *問題



ノダッシー

リンク

2015/3/5(Thu) 15:03:22|NO.67702

FunnyMakerさん
y.tackさん
暇人さん
アドバイスと素敵なスクリプトありがとうございました



ONION software Copyright 1997-2021(c) All rights reserved.