ついにこの日が来ましたか。初のソフト開発です!
では、その仕様を考えていきましょう。開発は、仕様を考えることから始まります。
今回作るのは、なんと、なんと……数当てゲームです。(@o@!)
初級講座らしいものですね。
ちなみに、僕の処女作(初めて作る作品のこと)とほぼ同じものを作ります。
数を当てるんですから、なにか「ランダムな数(乱数)」が必要です。
レイアウトの時の講座を思い出してください。
その時説明無く紹介した、rnd関数というものを使えば、簡単に問題が作れます。(実はこの為の伏線だったり)
それともう一つ、ランダムな数を得るには、1 〜 いくつまでにするかを決めなければなりません。
大きすぎず、小さすぎない範囲で、今回は 100 とします。
次に、答える方法です。プレイヤーが何も出来ないというのは、もはやゲームじゃないので、なにか必要です。
今回は単に数値を聞くだけなので、input 命令を使用しましょう。
input から数値を受け取る方法は、前の講座でノータッチだったサンプルを見てください。
最後にもう一つ、間違っていたときのヒントの出し方です。
こういう簡素なゲームは、ソフトとプレイヤーのクロストークが必要なのです (ということにしておきましょうよ?)。
という事で:
開発をするには作業場が必要です。
最初に「作れ!」って言ったフォルダの中に、「数当てゲーム」なり、「NumberHitGame」なり、フォルダを作ってください。
そこが、この開発の作業場になります!
ちなみに、ファイルやフォルダに日本語を使うのは、あまり良いことではありません。
また、半角スペースなどは厳禁です。気をつけましょう。
開発の前に、大まかな処理の流れを考えてみます。ざっとで良いですけどね。
僕は、こう考えました。
簡潔すぎるタイトルですね……。
それはいいとして、「定義」では、主に #const などを書いておきます。
「プリプロセッサ命令」という、# から始まる命令は、必ずプログラムの先頭に書きます。
// packopt は後々…… #packopt name "数当てゲーム" #packopt hide 1 // 定数(= const)を宣言 #const IDW_Main 0 // メイン画面のウィンドウID #const MAX_ANSWER 100 // 答えの最大 #const ANS_LIMIT 6 // 回答できる限界
HSPでは本来必要のない処理ですが、僕は必ず書くようにしています。
それには、もちろん理由があります。
これを書いておくと、変数がどんな役割をしているのかが、すぐに調べられます。いわば変数表ですね。
では、今回使う変数を用意。
// 変数を用意 *SetVariable dim question // 問題 dim answer // プレイヤーの回答 dim nAnsCount // 回答した回数 dim ID_Edit // input のオブジェクトID
次に、画面を準備します。
いつものは大きすぎるので、ちっちゃめにしましょう。
ボタンや入力ボックスなんかもここで設置します。
// スクリーンを構築する *CreateMainWindow screen IDW_Main, 480, 320, 0 // メイン画面 title "数当てゲーム ver.1.0" // タイトルバーには、ゲーム名を表示させる objsize 80, 25 // ボタンの大きさを設定 pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" pos 30, 80 : input answer, 120, 24 // 回答 pos 160, 80 : button "答える", *GoAnswer // 答え合わせ pos 50, 140 // カレントポジションを移動
問題を事前に作らないといけないので、この辺りでします。
問題を作ると言っても、ただ単に「乱数」を発生させるだけで、あまり小難しい話じゃないです。
この前も使った、なかなか便利な rnd関数 なのですが、これは、「0 〜 (p1 - 1)」という、いわゆる0ベースの数値を返してきます。
※0ベース……0 を基準とする数値のこと。
これを「1 〜 p1」にするために、返ってきた値(返り値)を + 1 します。
// 問題を作る *CreateQuestion // 0〜MAX_ANSWER-1 なので、+1 して 1〜MAX_ANSWER にする question = rnd(MAX_ANSWER) + 1 // 停止 *main stop
step5 までで、前処理は終了です。
ここでは、「答える」ボタンが押された時にする処理を書きます。
入力された数値を答えと比較して、同じなら正解、違ったら別のメッセージを表示します。
// 判定処理 ( button で飛んでくる ) *GoAnswer // (注意) 判定する順番は大事です。 nAnsCount ++ // 答えた回数を数える if ( answer == question ) { // 正解 goto *Clear // 正解したときのラベルに飛ぶ } else : if ( (1 <= answer && answer <= MAX_ANSWER) == 0 ) { mes "1 〜 "+ MAX_ANSWER +" で選んでね。" } else : if ( answer * 2 < question ) { // 問題は、回答の二倍以上 mes "小さすぎない?" } else : if ( answer / 2 > question ) { // 問題は、回答の半分以下 mes "大きすぎない?" } else : if ( answer < question ) { // 問題は、回答より大きい mes "もっと大きいよ" } else : if ( answer > question ) { // 問題は、回答より小さい mes "もっと小さいよ" } // ここに来るということは、正解じゃない if ( nAnsCount >= ANS_LIMIT ) { // 限界まで答えていたら goto *TimeUp // 時間切れのラベル } stop
ゲームが終わったときの処理を書きます。
正解したときも、失敗し続けて時間切れとなったときも、一度ここにジャンプしてきます。
ここでゲームを終わらせても良いのですが、今回は、もう一度ゲームを新たに始めるようにします。
// 正解した *Clear color 0, 0, 255 font msgothic, 50, 1 // "MS ゴシック" の代わり mes "正解!お見事!!" dialog "正解です!\nあなたは "+ nAnsCount +"回で正解しました", 0, "おめでとう" // 画面をリセット redraw 2 color 255, 255, 255 : boxf : color sysfont 0 // 最初のフォント pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" // もう一度書く(消されたから) pos 50, 140 // カレントポジションを移動 redraw 1 // 問題変更 nAnsCount = 0 goto *CreateQuestion stop // 時間切れ *TimeUp color 255, 0, 0 font msgothic, 60, 1 mes "タイムアップ!!" dialog "時間切れです。答えは "+ question +"でした。", 0, "残念" // 画面をリセット redraw 2 color 255, 255, 255 : boxf : color sysfont 0 // 最初のフォント pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" // もう一度書く(消されたから) pos 50, 140 // カレントポジションを移動 redraw 1 // 問題変更 nAnsCount = 0 goto *CreateQuestion stop
さぁ、これで完成です!!
動くかどうか、試してみましょう!
……おやおや……。何度実行しても答えが同じ……。
ハッ!
randomize が無いいいいいいいいぃぃぃぃぃぃぃ……。
じゃ、僕のわざとらしいミスを修正した完全版を公開して、今回は終了です。
わかんないところとかがあったら、過疎ってる某掲示板 に、遠慮無く書き込んでください。
それでは、また次回。
数当てゲームのスクリーンショット
やったーーー!!
ありゃりゃ (o-o?)
// 数当てゲーム #packopt name "数当てゲーム" #packopt hide 1 // 定数(= const)を宣言 #const IDW_Main 0 // メイン画面のウィンドウID #const MAX_ANSWER 100 // 答えの最大 #const ANS_LIMIT 6 // 回答できる限界 *initialize randomize // 一回だけ使えばいい // 変数を用意 *SetVariable dim question // 問題の答え dim answer // プレイヤーの回答 dim nAnsCount // 回答した回数 dim ID_Edit // input のオブジェクトID // スクリーンを構築する *CreateMainWindow screen IDW_Main, 480, 320, 0 // メイン画面 title "数当てゲーム ver.1.0" // タイトルバーには、ゲーム名を表示させる objsize 80, 25 // ボタンの大きさを設定 pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" pos 30, 80 : input answer, 120, 24 // 回答 pos 160, 80 : button "答える", *GoAnswer // 答え合わせ pos 50, 140 // カレントポジションを移動 // 問題を作る *CreateQuestion // 0〜MAX_ANSWER-1 なので、+1 して 1〜MAX_ANSWER にする question = rnd(MAX_ANSWER) + 1 // 停止 *main stop // 判定処理 ( button で飛んでくる ) *GoAnswer // (注意) 判定する順番は大事です。 nAnsCount ++ // 答えた回数を数える if ( answer == question ) { // 正解 goto *Clear // 正解したときのラベルに飛ぶ } else : if ( (1 <= answer && answer <= MAX_ANSWER) == 0 ) { mes "1 〜 "+ MAX_ANSWER +" で選んでね。" } else : if ( answer * 2 < question ) { // 問題は、回答の二倍以上 mes "小さすぎない?" } else : if ( answer / 2 > question ) { // 問題は、回答の半分以下 mes "大きすぎない?" } else : if ( answer < question ) { // 問題は、回答より大きい mes "もっと大きいよ" } else : if ( answer > question ) { // 問題は、回答より小さい mes "もっと小さいよ" } // ここに来るということは、正解じゃない if ( nAnsCount >= ANS_LIMIT ) { // 限界まで答えていたら goto *TimeUp // 時間切れのラベル } stop // 正解した *Clear color 0, 0, 255 font msgothic, 50, 1 mes "正解!お見事!!" dialog "正解です!\nあなたは "+ nAnsCount +"回で正解しました", 0, "おめでとう" // 画面をリセット redraw 2 color 255, 255, 255 : boxf : color sysfont 0 // 最初のフォント pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" // もう一度書く(消されたから) pos 50, 140 // カレントポジションを移動 redraw 1 // 問題変更 nAnsCount = 0 goto *CreateQuestion stop // 時間切れ *TimeUp color 255, 0, 0 font msgothic, 60, 1 mes "タイムアップ!!" dialog "時間切れです。答えは "+ question +"でした。", 0, "残念" // 画面をリセット redraw 2 color 255, 255, 255 : boxf : color sysfont 0 // 最初のフォント pos 20, 50 : mes "1 〜 "+ MAX_ANSWER +"までの私を当ててみよ!" // もう一度書く(消されたから) pos 50, 140 // カレントポジションを移動 redraw 1 // 問題変更 nAnsCount = 0 goto *CreateQuestion stop
追伸:このスクリプトを完璧に理解する必要はありません。今はまだ、「だいたい」の感じが分かったらそれでいいのです。
by 上大