3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日本語プログラミング言語「なでしこ」Advent Calendar 2022

Day 9

脳トレを作ることが最大の脳トレだそうなので脳トレ作って脳トレをした

Last updated at Posted at 2022-12-08

 脳トレを作ることが最大の脳トレだそうですよ。
 そうですか。ではさっそく脳トレしなくては!

 ていうか、やっぱゲームっぽいもの作りたい☆
 わりとよくあるヤツだと思いますが、数字を順番通りに追っていく脳トレにします。

画面作る

 なでしこさんのエディタでは、はじめから標準でキャンバスが用意されていて、いきなり描画を始められるようになっているんですが、今回は標準のキャンバスを使わず新たにキャンバス作成しています。
 ゲーム画面の上部にスタートボタンなどを置きたかったからです。
 描画開始することで、以降の描画命令が、そのキャンバスに対して行われるようになります。

#プラグイン取り込み
!『https://n3s.nadesi.com/plain/drawPlus.nako3』を取り込む。# 文字幅、文字高さ取得
!『https://n3s.nadesi.com/plain/wa.nako3』を取り込む。# DOM和スタイル追加

#設定
変数 [画面幅,画面高さ]=[300,300]。
変数 背景色=「#FFFFCC」

#UI作成
スタートボタン=「ゲームスタート!」のボタン作成。改行作成。

#画面作成
ゲーム画面=[画面幅,画面高さ]のキャンバス作成。改行作成。
ゲーム画面へ描画開始。
背景色で画面クリア。

●(色で)画面クリア
    色に塗り色設定。色に線色設定。
    [0,0,画面幅,画面高さ]へ四角描画。 
ここまで。

 v1では画面クリアという命令で、画面を指定した色で塗り潰すことが出来たんですが、v3の描画クリアは文字通りクリアで、何も描画されてない状態にするとゆう命令なので、v1ライクに画面クリアとゆう関数で画面を背景色で塗り潰しています。

問題作成

 1~xまでの数字を画面上のバラバラな位置に散らばして表示したい。
 どうしたら出来るかにゃー? と、考えることが脳トレにつながるってコトなんでしょう。
 色々よい方法はあるものと思いますが、ワタシの知恵ではこんなところ。

表示マス作成

 ランダムな位置に数字を描画したいだけなんですが、完全にランダムに描画のxyを決めると、ものすごく偏ったり文字が重なってしまったりもしてしまうので、簡易的に、画面を表示文字数分マス目状に分割して、そのマス目内のランダムな位置に各数字を描画していくってことにしようと思う。
 この方法だと、表示文字数が増えれば増えるほど、表示位置のランダム感が薄れちゃうんですけど、気にしない!💧

##表示マス作成
変数 [列数,行数]=[4,4]。
変数 表示文字数=列数*行数。

# 文字が重ならないよう画面を分割して、見えないマス目を先に作成する。
変数 表示マス=空配列。
表示マス作成。
●表示マス作成。
  表示文字数回
    変数 番号=回数-1。
    表示マス[番号]=空配列。
    表示マス[番号][0]=(番号%列数)*(画面幅/列数)を切り捨て。
    表示マス[番号][1]=(番号/列数を切り捨て)*(画面高さ/行数)を切り捨て。
  ここまで。
ここまで。

 マス目を作成って言うか、その起点となるx,yを配列にしているだけですね。

問題作成

 同じ数字が重なることなく順番だけをランダムにするには、連番の配列を配列シャッフルするのが便利です。
 ここでまさに!
 配列連番作成とゆう命令が最近新しくできました。
 繰り返しで連番を作成する一手間が省けて便利になりなしたね☆
 こうしてランダムに並べ替えられた数字を表示マスに割り当てていき、マス目内のランダムな位置に表示します。

##問題作成
変数 数字=1から表示文字数までの配列連番作成。
問題作成。# テスト用
●問題作成
    背景色で画面クリア。
    「bold 32px sans-serif」に描画フォント設定。
    数字=数字を配列シャッフル。
    表示文字数回
        変数 番号=回数-1。変数 数=数字[番号]。
        変数 文字幅=数の文字幅取得。
        変数 文字高さ=数の文字高さ取得。
        変数 x=(画面幅/列数-文字幅)の乱数。
        x=x+表示マス[番号][0]。
        変数 y=(画面高/行数-文字高)の乱数。
        y=y+表示マス[番号][1]+文字高さ。
        黒色に塗り色設定。
        [x,y]へ数を文字描画。
    ここまで。
ここまで。

 できました!
 問題作成は、スタートボタンを押した時に実行されるようにする予定ですが、テストのためとりあえず。
 まあまあランダムな位置にランダムな順番で数字が表示されるようになりました☆

 うーん、でも、文字のサイズもバラバラなったほうが、らしいかな?
 見た目の大きさに惑わされず、ちゃんと数字の順に追っていくの方が、難易度も少し上がって良さそげです。表示位置のランダム感も多少はアップする予感(タブンね)
 文字サイズは決め打ちから、各数字ごとに乱数で決めることに変更。

  //「bold 32px sans-serif」に描画フォント設定。
  表示文字数回
      文字サイズ=(35の乱数)+14。
      「bold {文字サイズ}px sans-serif」に描画フォント設定。

2022-12-07 (1).png
 いい感じ☆
 とりあえず、本とかのつもりであれば、もう遊べます。やったね!!

正解の判定

 そうはいっても、せっかくコンピューターなんですから、ちゃんと正しく押せたかどうかは判定して欲しい。
 人間、うっかり一個飛ばしたり、順番間違えたりしても気づかないコトありますからね~。

正解の位置を記憶

 手っ取り早い方法として、問題作成時に正解の位置を記憶しておくことにします。

##問題作成
変数 数字=1から表示文字数までの配列連番作成。
変数 正解=空配列。# 正解の位置を記録しておく配列
問題作成。# テスト用。後で消す。
●問題作成
    背景色で画面クリア。
    数字=数字を配列シャッフル。
    表示文字数回
        文字サイズ=(35の乱数)+14。
        「bold {文字サイズ}px sans-serif」に描画フォント設定。
        変数 番号=回数-1。変数 数=数字[番号]。
        変数 文字幅=数の文字幅取得。
        変数 文字高さ=数の文字高さ取得。
        変数 x=(画面幅/列数-文字幅)の乱数。
        x=x+表示マス[番号][0]。
        変数 y=(画面高/行数-文字高)の乱数。
        y=y+表示マス[番号][1]+文字高さ。

        # 正解を記録
        正解[数-1]=空配列。
        正解[数-1]=[x,y,文字サイズ]。

        黒色に塗り色設定。
        [x,y]へ数を文字描画。
    ここまで。
ここまで。

 あとはマウスのイベントです。
 スマホとかならタッチですが、とりあえず。(一応、動くことは動きます)
 マウスを押したら、マウスXとマウスYに座標が入るので、それがその数の正解の位置の内部にあるかどうかを判定しています。
 v1では文字描画のxyは左上でしたが、v3ではy座標はアルファベットのベースラインなのでご注意です(数字なら下端ということにしてだいじょぶそう)

#イベント
描画中キャンバスをマウス押した時には、
    もし、(正解の配列要素数)=0ならば、戻る。
    変数 [x,y,文字サイズ]=正解[0]。
    数=表示文字数-(正解の要素数)+1。
    「bold {文字サイズ}px sans-serif」に描画フォント設定。
    文字幅=数の文字幅取得。
    文字高さ=数の文字高さ取得。
    変数 [判定x1,判定y1,判定x2,判定y2]=[x,y-文字高さ,x+文字幅,y]。
    もし、((判定x1≦マウスX)かつ(マウスX≦判定x2))かつ((判定y1≦マウスY)かつ(マウスY≦判定y2))ならば、正解の0を配列削除。
    もし、(正解の配列要素数)=0ならば、「おめでとう!」と言う。
ここまで。

 できました。
 コレで、正しく順番通りに押していけば、最後16を押した時に「おめでとう!」と言ってくれます☆
 でも、ちゃんと押せてなかったの気づかずに最後まで行っちゃったら?!:sob:
 押したのが合ってたかどうか、いっこいっこお知らせして欲しい。

音でお知らせ

 オーディオファイルは、なでしこ貯蔵庫にアップロードして使用することが出来ます。
 先にオーディオ開くしておく。

変数 ピ=「https://n3s.nadesi.com/image.php?f=213.mp3」をオーディオ開く。# あたり音
変数 ブ=「https://n3s.nadesi.com/image.php?f=214.mp3」をオーディオ開く。# ハズレ音

 そして、マウス押した時の処理。
 先にオーディオ停止を入れるのは、再生中にもう一度オーディオ再生しても再生位置はそのままで続きが再生されるので、短い効果音とはいえ素早く押していったらまだ残響が再生中で、あれ音が鳴らない?! みたいになる可能性があるからです。
 オーディオ停止することで再生位置が0に戻ります。

描画中キャンバスをマウス押した時には、
    もし、(正解の配列要素数)=0ならば、戻る。

    # 先に停止を入れる。
    ピをオーディオ停止。ブをオーディオ停止。

    変数 [x,y,文字サイズ]=正解[0]。
    数=表示文字数-(正解の要素数)+1。
    「bold {文字サイズ}px sans-serif」に描画フォント設定。
    文字幅=数の文字幅取得。
    文字高さ=数の文字高さ取得。
    変数 [判定x1,判定y1,判定x2,判定y2]=[x,y-文字高さ,x+文字幅,y]。

    もし、((判定x1≦マウスX)かつ(マウスX≦判定x2))かつ((判定y1≦マウスY)かつ(マウスY≦判定y2))ならば、:
        正解の0を配列削除。
        ピをオーディオ再生。
    違えば、:
        ブをオーディオ再生。
    もし、(正解の配列要素数)=0ならば、:
        「おめでとう!」と言う。
        ピをオーディオ停止。
ここまで。

 コレで、クリックするたび音が鳴るようになりました!
 でも、音は出したくない時もあるよねー。

色でお知らせ

 正解だったら、色付ける。
 でも、色変えっぱなしだと、ゲームの難易度が下がってしまうので、一瞬だけ色を付けて、すぐ元に戻すことにする。

変数 正解判定=いいえ。
描画中キャンバスをマウス押した時には、
    もし、(正解の配列要素数)=0ならば、戻る。
    正解判定=いいえ。
    ピをオーディオ停止。ブをオーディオ停止。# 先に停止を入れる。
    変数 [x,y,文字サイズ]=正解[0]。
    数=表示文字数-(正解の要素数)+1。
    「bold {文字サイズ}px sans-serif」に描画フォント設定。
    文字幅=数の文字幅取得。
    文字高さ=数の文字高さ取得。
    変数 [判定x1,判定y1,判定x2,判定y2]=[x,y-文字高さ,x+文字幅,y]。

    もし、((判定x1≦マウスX)かつ(マウスX≦判定x2))かつ((判定y1≦マウスY)かつ(マウスY≦判定y2))ならば、:
        正解判定=はい。
        ピをオーディオ再生。
        赤色に塗り色設定。
        [x,y]へ数を文字描画。
    違えば、:
        正解判定=いいえ。
        ブをオーディオ再生。
ここまで。

描画中キャンバスのマウス離した時には、
    もし、(正解の配列要素数)=0ならば、戻る。
    もし、正解判定=はいならば、
        変数 [x,y,文字サイズ]=正解[0]。
        数=表示文字数-(正解の要素数)+1。
        黒色に塗り色設定。
        [x,y]へ数を文字描画。
        正解の0を配列削除。
    ここまで。
    0秒待つ。
    もし、(正解の配列要素数)=0ならば、
        「おめでとう!」と言う。
        ピをオーディオ停止。
    ここまで。
ここまで。

 マウスを押したら色を変えて、離したら戻すで、チカッとします。
 ちょっと、ぽくなってきた☆

時間の計測

 こうゆうのって、タイムと間違えた数とで「アナタの脳年齢」とか言ってきたりするんだよね~。
 脳年齢とやらをどうやって判定してるのかはともかく、とりあえず時間は計測したい。
 なでしこでは、で現在の時刻を取得出来ます。
 ゲームスタート時にを取得しておいて、終了時にもを取得して、秒差を求めればいいんですよねー。なでしこにはまさに秒差とゆう命令があるので、

終了時間=今。
タイム=開始時間から終了時間までの秒差。
「おめでとう!{改行}タイムは{タイム}秒です{改行}{誤答数}回まちがえました」と言う。

 こんだけ!
 1分以上かかる人なんてきっといない~、と思っててきとーこいてますよw
 あと、間違えた数は、誤答数の変数を用意して、ハズレ音を再生する時に、1ずつ増やしていけばいいだけだよね。

スタートボタン

 作るだけ作って機能させてなかったスタートボタンですが、稼働させます。
 実行したらいきなり時間計測され始めているとか、精神衛生上良くないですからねw
 エディタでゲーム画面全部見えてなかったりしたらスクロールとかしてる間に時間が過ぎちゃう:sweat_smile:
 スタートボタンをクリックしたら問題作成して、開始時間を今に設定するだけ☆
 誤答数も、ここでクリアしときます。

スタートボタンをクリックした時には、
    問題作成。
    誤答数=0。
    開始時間=今。
ここまで。

スタートボタン無効化

 ゲーム中にうっかりスタートボタンが押ささるとよろしくないので無効化します。
 スタートボタンをクリックしたら、まず無効化して、

スタートボタンをクリックした時には、
    スタートボタンの「無効化」に、はいをDOM属性設定。

 ゲーム終了時に、戻す。

    スタートボタンの「無効化」にいいえをDOM属性設定。

 無効化・・・disabledです。ぜったい綴れないのねん💧
 !『https://n3s.nadesi.com/plain/wa.nako3』を取り込む。で、「無効化」の和スタイルが使えるようになります。
 このためだけにプラグイン取り込むのばからしいって人は、がんばって綴りましょうw
 あるいはDOM和スタイルは辞書型変数なので、自分でそのプログラムで必要なものだけ追加登録することもできます。
 ここではプラグイン取り込んでる前提で、標準以外の和スタイルも使っていっちゃう。

カウントダウン

 ゲーム開始時のカウントダウンも付けてみます。
 スタートボタン押してから、さらに心の準備がしたい人ですw
 ていうか、あるとちょっと、ぽくなる(?)

●カウントダウン
  背景色で画面クリア。
    文字サイズ=64。
  「bold {文字サイズ}px sans-serif」に描画フォント設定。
  数を3から1まで繰り返す
      文字幅=数の文字幅取得。
      文字高さ=数の文字高さ取得。
      x=(画面幅-文字幅)/2。y=(画面高さ+文字高さ)/2。
      背景色に塗り色設定。黒色に線色設定。5に線太設定。
      [画面幅/2,画面高さ/2]に文字サイズ/2+5の円描画。
      黒色に塗り色設定。
    [x,y]へ数を文字描画。
    1秒待つ。
    背景色で画面クリア。
  ここまで。
ここまで。

その他

タッチに対応

 マウスのイベントでも動くことは動くと書いたんですが、色でお知らせ機能が働いてない。
 やっぱりちゃんとしなくては。
 まるっとコピペして、マウスX,マウスYをタッチX,タッチYに書き換えてもいいんですけど、違いは判定に使うx,yがマウスかタッチかだけなのに無駄が過ぎるので、それぞれ一つの関数にまとめて、イベントから呼ぶようにする。
 タッチのとき、マウスだけでも一応動くようになってるせいでタッチ開始時マウス押した時のイベントが両方発生しているために変なってハマったのは内緒:joy:
 マウスの時にタッチXに値が入ってたら戻るようにした。

逆順

 大きい数から小さい数へ、も出来るようにした。
 思ったより難易度は上がらなかった💧
 ワタシのとっての最凶は、アルファベットの逆順だと思う。
 いちいちABCの歌歌わないと、次が何か出て来ないのねん:sweat:

できました!

 コード全体は貯蔵庫エディタで見た方が、シンタックスハイライトもついて見やすいです。

おまけ

 アドベントカレンダー八日目の記事で、わたしがすっごい前に作ったヤツを紹介頂いたんだけど、サンドボックスで表示にundefined出る病が発生しているから直そうと思ったら古すぎて修正出来なかったので、今回の色々流用してちょっと見た目いい感じにして(そうでもない💧)再掲しました。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?