相互変換モジュール クイズゲームを作る
過去ブログの転載です。
クイズゲームでも作ってみましょう。HSPには、とても簡単に文字列を扱える「メモリノートパッド命令」というのがありますので、それを用いると外部ファイルの読み込みや書き込みがとても簡単に行えます。C言語だとファイルのポインタを作ってfscanfしてとか色々必要ですが、HSPはこのようにすれば外部ファイルを読み込めます。
r = "" // 文字列変数rを定義
notesel r // rをバッファに指定
noteload "メモ帳.txt" // 「メモ帳.txt」の内容を読み込んでrに入れる
これでrに読み込み完了です。mes r とすれば、読み込んだすべての文字を表示できます。各行を取り出すには、更に次のようにします。
k = "" // 文字列変数kを定義
repeat notemax // r(指定したバッファ)の行数ぶんrepeat
noteget k, cnt // kにrのcnt行目を代入
mes k // kを表示
loop
↑このようにすれば、一行ずつ取り出せます。一番初めの行を「0行目」と数えることに注意です。システム変数notemaxは、バッファに指定した変数の行数が返ります。バッファに指定した変数のサイズを得るには、notesizeを使います。命令noteselでバッファ指定、noteloadでバッファにファイル読み込み、notegetで指定した行の文字列を別の変数に代入します。今回使うのは読み込みだけなので、とりあえずこれまでにしておきます。
それでは、実際にクイズゲームを作ってみます。こんなかんじです。
#include "rpgfunc.as"
#define mondai 3 ;出題数はここで決める(5なら5問)
goto *@f
// 各命令の定義
#deffunc 初期処理
msg "ここいらで、ちと問題と参りましょう。"
sl "喜んで、承認しましょう", "拒否します"
slcase 1
slcase 2
msg "帰れよ"
hangup
slend
r = "" : k = "" ;文字列変数rとkを定義
notesel r ;rをバッファに指定
noteload "もんだい.txt" ;「もんだい.txt」をrに入れる
max = notemax/5 ;変数maxに、「もんだい.txt」の行数÷5を代入
if mondai > max { ;出題数が問題の総数より多いなら
dialog "問題の総数" + max + "問に対し、\n出題数" + mondai + "問は多すぎます。", 1
end ;エラーで終了
}
varsel 1, 2 : var 0, 0, 0, 0 ;変数1番「問題数」と変数2番「正解数」を0にする
swi 1, max, 0 ;スイッチ1番~max番までをOFFする
msg "では、問題です。"
return#deffunc 出題
label 1 ;ラベル1番
varsel 3 : var 0, 3, 1, max ;変数3番「問題番号」に乱数1~maxを代入
repeat max ;問題数分くりかえす
co 1, 3, 0, cnt+1 ;変数3番がcnt+1だと
co 0, cnt+1, 1 ;スイッチcnt+1番がONだと(出題済み)
golabel 1 ;ラベル1番に戻る
coend
noteget k, 5*cnt ;5*cnt行目をkに代入
msg k ;問題文表示
;si(0)~si(2)にそれぞれ選択肢の文を代入
noteget k, 5*cnt+1 : si(0) = k
noteget k, 5*cnt+2 : si(1) = k
noteget k, 5*cnt+3 : si(2) = k
noteget k, 5*cnt+4 ;次の行を代入
seikai = int(k) ;正解の番号を数値に変換して取得
sl si(0), si(1), si(2), , 0 ;選択肢si(0)~si(2)
repeat 3, 1
slcase cnt
if cnt = seikai { ;選択肢番号と正解番号が同じなら
msg "せいかい!"
varsel 2 : var 1, 0, 1 ;正解数に1加算
}
else{ ;違ったら
msg "まちがいー!"
}
loop
slend
swi cnt+1, , 1 // cnt+1番スイッチをON(同じ問題が出ないように)
coend
loop
varsel 1 : var 1, 0, 1 ;問題数に1加算
co 1, 1, 0, mondai, 4 ;変数1番「問題数」がmondai未満なら
golabel 1 ;ラベル1番に戻る
coend
return#deffunc 結果発表
msg "終わりじゃ!\n結果発表をするぞ。"
msg "正解数は" + mondai + "問中\\V[2]問でございます。\nごちそうさまでした。"
return
// 各命令の定義おわり*@
// 本体
初期処理
出題
結果発表
// 本体おわりdialog "コピーしました。" ;確認メッセージ
send
「もんだい.txt」を読み込んで実行します。
「もんだい.txt」の例……
ベイ助の色は?
青
黄
赤
3
ベイ太の初期レベルは?
5
6
7
2
BADENDの総数は?
12
14
15
2
ベイ助が主人公なのは?
愛花ちゃんのままごと
First Challenger
セーフティ・エリア
3
オイラーの定数は?
γ
e
π
1
1行目に問題文、2行目、3行目、4行目に選択肢を書きます。5行目に、どの選択肢が正解かの値を書きます。1なら1番目。こうしてプログラムを実行すれば、「もんだい.txt」から問題数を自動で読み込み、出題数分だけ問題を出すイベント命令として出力されます。
同じ問題が重複して出題されないよう、各問題番号のスイッチをONするようにしています。よって、問題数の分だけスイッチが必要なようにしています。スイッチには変数の番号が使用できないためツクールで扱うには一つ一つ設定しなければなりませんが、このようにプログラムに任せてしまうことで、何もしなくて良いことになります。問題を編集するには「もんだい.txt」のみをいじれば良いです。問題を作り終わったらプログラムを実行して貼り付ければ良いだけです。(出題数を変える場合は、プログラムの一番上にあるmondaiの値を変えます)
#defineは、マクロ定義というものです。ここではmondaiを3としなさいとしています。dialogは、ダイアログボックスの表示です。出題数の方が問題数より多いといけませんので、そのときは終了させるようにしています。5*cntとか、5*cnt+1とかの理屈は、ツクールでバトルイベントの開始条件に5xターンとか5x+1ターンとか設定するのと同じような感じです。int()は、かっこの中身のものを整数型に変換する関数です。文字列型の配列変数を作る命令はsdimというのですが、使わなくてもいきなり使えてしまえます。配列は0番からスタートするので、0番の配列を初めに使っています。si(0)が、siの0番、si(1)が、siの1番、si(2)が、siの2番、というわけです。配列の番号はこのようにかっこを使うほか、si.0、si.1、si.2、といった書き方もできます。
けっこう中身は長いですが、まあまあ、単純なことをしています。ツクールに貼り付けてしまえばこういうものだと分かることでしょう^^