1
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 2023

Day 9

なでしこさんで「ひろいもの」を作るよ! ③ ~UIを追加し問題を選んで遊べるようにする~

Last updated at Posted at 2023-12-08

 なでしこ3でUIとして使えるDOM部品色々。
 あるいは、DOMイベント発火した時で全部出来るからって、v1と比べてイベントの種類少なくない?(日本語らしく書けない)と嘆いてみたりする。
 あるいはまた、問題集を素材としてなでしこ貯蔵庫にアップロードして使うことについて。

UIを作ります

 なでしこ3ではUIとして色々なDOM部品を作ることが出来ますので、活用して「ぽい」感じにしていきます。
 
👉 なでしこさん マニュアル > plugin_browser/DOM部品操作

一手戻るボタンと、最初からやり直すボタン

 
👉 なでしこさん マニュアル > plugin_browser/ボタン作成
 
 あっ、まちがえた! となった時、戻すことが出来たら便利ですよね?
 ていうか、ちょっと間違えたらもう1からやり直すしかないとか、ガックリきちゃいますよね💧
 というわけで、一つ前の状態に戻せるボタンを作ります。

戻しボタン「一手戻す」ボタン作成
戻しボタン「title」「一つ前の状態に戻す」DOM属性設定

 「title」属性を指定すると、マウスオーバーでツールチップが表示出来ます。
 なくても別に困らないけど、あるとなんだかぽい感じ♪

戻しボタンクリックした時には
    もし(拾った履歴要素数)ならば戻る
    ゲーム中フラグオン
    x=進行方向%列数y=(進行方向/列数整数部分)
    拾った履歴から配列ポップ
    ,,進行方向それ
    現在データ[][]1
    もし進行方向ならばゲーム開始# 最初から
    違えば[-x,-y]から拾えるデータ更新
    盤面描画
ここまで

 「拾った履歴」があるので、一つと言わず最初まで順に遡って戻っていくことが出来るようにします。
 拾うたびに追加していってるので、末尾にあるのが一つ前に拾ったデータということになります。
 配列ポップは、配列Aの末尾を取り出して返す命令です。
 取り出した部分は元の配列から消えてしまうけど、進むボタンは付ける予定がないのでそれで良い。
 
👉 なでしこさん マニュアル > plugin_system/配列ポップ
 
 それにしても、こんなの前からあったっけ?
 v1にはありませんでした。
 A[Aの配列要素数-1]みたいな指定をしなくてよくなり便利です♪

 ついでに、最初からやり直すボタンも作ります。

最初ボタン「最初から」ボタン作成
最初ボタン「title」「この問題を最初からやり直す」DOM属性設定

最初ボタンクリックした時には
    「最初からやり直しますか?」二択
    もしそれはいならばゲーム開始
ここまで

 うっかり間違えて押して最初に戻ってしまうとそれはそれで「あっ💧」て感じなので、二択で確認w

ヒントを表示するチェックボックス

 
👉 なでしこさん マニュアル > plugin_browser/チェックボックス作成
 
 ヒントと言っても、攻略のヒントではないんですが、拾うことの出来る石を表示する機能です。
 同一線上なら、どんなに離れていても取ることが出来るルールがあるので、うっかりしているとそこが取れるとは気づかないまま、何度やっても出来ない!? となっていることがあったりなかったりするかも知れませんからね!(ワタシがね!w)
 前回、まだ取れるとこあるのに、「あれ? ゲームオーバーにならないな。バグか?」とかなっていたのは内緒www

ヒント表示「❓」チェックボックス作成
ヒント表示「title」「チェックを入れると拾える石を明示します」DOM属性設定

 拾えるデータがあるので、「問題描画」関数で現在データを描画した後、色を変えて拾えるデータを上書きすればいいだけです。

変更した時

 チェックボックスのチェック状態が変化したら、即表示が切り替わって欲しいですよね。
 v1だと「変更した時」というイベントがあったのですが、v3ではありません。
 「DOMイベント発火した時」というイベントがあって、いちおうこれで全てのイベントが使えるようになっていますので、これを使います。

ヒント表示「change」DOMイベント発火した時には
    問題描画
ここまで

 「change」は使用頻度が結構高いので、「変更した時」くらいはあるとうれしい感。
 ワタクシが「change」を綴らなくて良くなり、プログラムの見た目の日本語らしさが向上するってだけのことですけれどね😅

タブン、もともとのフォームの用途だと、色々入力して最後にsubmitを押して送信だからchangeで発動させることはそんなに無いという考えなのかもだけど、プログラムのUIとして活用する場合には、チェックボックスとかセレクトボックスとか変更したら即作動しないと気分良く使えないことが多いのねん。

チェックの有無を取得

 次に、問題描画に、ヒント表示のチェックが入っていた場合の描画を追加。
 チェックボックスにチェックが入っているか否かは、ヒント表示の「checked」をDOM属性取得もしくはヒント表示["checked"]を直接参照することで確認出来ます。
 しかしながら、「checked」すら綴れないワタクシですよ💧
 v1ですと、ヒント表示の値で取得出来たのに比べると、ひじょーにツラい。
 「checked」は、DOM和属性にも入っていないですし。
 チェックボックスが作れるようになっているんだから「checked」を参照するのは必至なのにナゼなんだ。
 でも、心配ご無用ですよ☆
 DOM和属性やDOM和スタイルは辞書型変数なので、自前で好きに追加が可能です🎶

DOM和属性["チェック"]「checked」

 あっ、DOM和属性が使えるのはDOM属性取得DOM属性設定だけで、プロパティ値を直接参照する場合は当然ですが使えません~。

 で、こんな感じ?

#問題を描画
●問題描画
    白色塗り色設定1.5線太さ設定
    現在データ反復:
        
描画行マス幅*(対象キー+1)
        対象反復:
            
描画列マス幅*(対象キー+1)
            もし対象ならば[描画列,描画行]マス幅/2-1円描画
    もし(ヒント表示「チェック」DOM属性取得)オンならば:
        
黄色塗り色設定
        拾えるデータ反復:
            
描画行マス幅*(対象キー+1)
            対象反復:
                
描画列マス幅*(対象キー+1)
                もし対象ならば[描画列,描画行]マス幅/2-1円描画
ここまで

 突然のインラインインデント構文。
 行末に「:」と書くことで一時的にインデント構文が使える便利機能です☆
 
👉 なでしこ3 マニュアル > 文法/インラインインデント構文
 
 ワタクシ基本的には「ここまで」がだるく無い人なのですが、二次元配列の二重ループに、もし文まで加わって、「ここまで」いっぱい並びすぎ! 邪魔くさ!! ってなったのでw
 こうゆう時に一時的にインデント構文の使えるインラインインデント構文が、個人的にとても好きです❤

 あと、インラインインデント構文のhtml変換はまだ試したこと無かったなーと思いついたので。
 バッチリだいじょぶでしたね👍

ヒント表示.png

 できました☆

問題選択のセレクトボックス

 これまで問題のデータは一つだけだったので、「中之字」という変数に直接入れていましたが、問題の数が増えるので、問題の名称をキーにした辞書型変数で問題集を作ることにします。

辞書型変数

 辞書型変数は、なでしこ1ではハッシュと呼ばれている機能です。
 
👉 なでしこさん マニュアル > 文法/辞書型変数
 
 なでしこ3では、配列同様JSON記法で初期化することが出来るようになっていて、なにげに便利です☆

#問題集
問題集{
"中の字":[
[0,1,1,0,0],
[0,0,1,0,0],
[1,1,1,1,1],
[1,0,1,0,1],
[1,1,1,1,1],
[0,0,1,0,0],
[0,0,1,0,0],
[0,0,1,0,0],
[0,0,1,0,0]
],
"井筒":[
[0,1,0,0,1,0],
[1,1,1,1,1,1],
[0,1,0,0,1,0],
[0,1,0,0,1,0],
[1,1,1,1,1,1],
[0,1,0,0,1,0]
]
}

 こんな感じ?
 実際にはもっとありますけれど、とりあえず。

 セレクトボックスは、選択肢を配列で指定して作ります。
 
👉 なでしこさん マニュアル > plugin_browser/セレクトボックス作成
 
 問題集のキー値が問題の名称になっているので、それを配列にして与えたいです・・・と思ったら、辞書キー列挙という命令がありました!
 
👉 なでしこさん マニュアル > plugin_system/辞書キー列挙
 
 辞書型変数のキー一覧を配列変数の型で取得する命令です。
 まさにこれ!

問題一覧問題集辞書キー列挙
問題セレクト問題一覧セレクトボックス作成

 ここでも、セレクトボックスで問題を選択したら、即石が置き換わって欲しいので「change」ですよ。

問題セレクト「change」DOMイベント発火した時には
    ゲーム開始
ここまで

 そして、問題のデータを作ったり、各種データを初期化する部分を、「ゲーム開始」関数として呼び出せるようにします。

 そうそう、最初作ったプログラムは動いたのに、関数に入れたら動かなくなっちゃった! とゆう事件があります。
 たしか、掲示板の質問でもあったような気がする。

ローカル変数

 なでしこでは、宣言せずに変数を使うことが出来ますが、関数の中で初めて出てきた変数はローカル変数となって、その関数内でしか使えない変数になるので、他から参照しようとするとそんな変数無いよ! と言われてしまうんだよね。

 しかも、v1とv3では仕様に違いがあって、関数の中で宣言された変数は、どちらもローカル変数になるんですが、グローバルに同名の変数がなく、宣言無しで関数の中で初めて出てきた変数の場合、v1ではグローバル変数として扱われますが、v3ではローカル変数になるので注意が必要です。
 
👉 なでしこさん マニュアル > 文法/ローカル変数
 
 というわけで、なんにしろグローバルで宣言しとくの忘れず。

#宣言
現在データ空配列
拾えるデータ空配列
拾った履歴空配列
進行方向

●ゲーム開始
    問題問題集[問題セレクトテキスト取得]配列複製
    #初期化
    現在データ問題行数列数碁石データ整形
    拾えるデータ現在データ配列複製
    進行方向拾った履歴空配列
    #描画
    盤面描画
    ゲーム中フラグオン
ここまで

セレクト.jpg

 できました☆

素材のアップロードとAJAX取得

 なでしこ貯蔵庫にはプログラムに使う素材をアップロードすることが出来るようになっています☆
 ワタシの知りうる古典に載っている問題は全部で12問あり、全部をプログラムの中に貼っ付けると邪魔くさいので、プログラムとは分けてデータとしてアップロードすることにします。

 問題集のデータ部分を「問題集.json」として別途保存しておきます。
 ここで!
 タブン間違えてらっしゃる方が結構いるっぽいのですが、データとして素材ファイルに記述するのはデータ部分だけ。なでしこのプログラムではありません。
 問題集={ JSONデータ }みたいな変数への代入や、区切ったりCSV取得したりなどはプログラムの方で行うようにします。

問題集を貯蔵庫へアップロードします

 なでしこ貯蔵庫では、ログインしなくてもプログラムを作ったり公開したり出来るようになっていますが、素材のアップロードはログインが必要です。
 ログイン状態だと、エディタの下の方に「アップロード画面を開く」ボタンがあります。

 アップロード出来るのは、画像、音声、テキスト。
 より具体的に言えば、JPEG/PNG/GIF/MP3/OGG/CSV/TSV/JSON/TXT/MIDのみです。(と、これら以外の拡張子のファイルをアップロードしようとすると、言われます)
 今回は、JSONデータなのでだいじょぶ✨

JSONさんの注意点

 なでしこさんのJSON記法はルールが少しゆるくなっています。
 たとえば、

[1,2,3,]

 コレが通ります。

 しかし、本物のJSONさんのルールでは、要素の末尾にいらないカンマ(,)が入っていたらエラーなります。
 こうですね。

[1,2,3]

 それで、直接プログラム中で指定していた時は出来たのに、データとしてアップロードして取得したらエラーなっちゃう的なことが起きることがあります(起こりました🤣)のでご注意です。
 なんなら、JSONエンコードしたヤツをデータにすればOKです☆

著作権

 ファイルを選択して、タイトルを入力して、著作権の確認。
 著作権的に問題のないファイルって何なのさ。ふわっとした書き方すぎる~💧
 しかし、利用規約を読むと、アップロード出来るファイルは、基本的には自分が作成したもののみと考えた方が良さそうです。
 なぜなら、当サービスに書き込んだプログラムや素材データの著作権は投稿者にありますとの条項があるからです。
 再配布可のフリー素材だとしても、著作権自体は作った人にあるハズですが、タイトル以外にファイルに関する付帯情報を記入出来る欄も無いため、他の人が作ったファイルを投稿すると自作発言してることになっちゃいます。

 さて、今回の問題を作ったのはワタクシじゃありませんが、作者は江戸時代の人なので、とうの昔に著作権は消失しています。そして、JSONデータにしたのはワタクシです。だいじょぶ!
 でも、リスペクトで原典を書き記しておきたいのが人情なのですが、書ける欄も無いのでこの記事の最後に記しておきます。

問題集をAJAXで取得する

 アップロードが出来たらURLが表示されるので、それからAJAXで取得するだけ!
 AJAXって何よ? 的な説明は出来ませんのでぐぐりましょう😅

#問題集取得
問題集URL『https://n3s.nadesi.com/image.php?f=384.json』
問題集問題集URLからAJAX_JSON取得

 なでしこのAJAX関係の命令はなんか色々紆余曲折があって命令が乱立しています。
 似たような名前の違う命令や、違う名前の同じ命令があってコンランしますが、まけません!(>_<)/
 マニュアルも整理されて、だいぶ見やすくはなりました。
 今回は、直接JSONデータが取得出来る「AJAX_JSON取得」を使いました。
 
👉 なでしこ3 マニュアル > plugin_browser/AJAX_JSON取得

入りきらない問題

 やってみたら、「五の字」の横幅が広くて、当初「中の字」に合わせていた碁盤の目に入り切りませんでした💧
 問題集の中の最大値で行列数を設定し、キャンバスのサイズを計算するように変更しました。
 なお、ここでの行数、列数は、実際に石の置ける外枠を除いた線の本数です。

できました!

#問題集取得
問題集URL『https://n3s.nadesi.com/image.php?f=384.json』
問題集問題集URLからAJAX_JSON取得

#設定
DOM和属性["チェック"]「checked」
変数 [行数,列数,マス幅,画面幅,画面高さ][11,11,30,0,0]
行列数カウントして画面サイズ計算

●行列数カウント
    問題集反復
        仮列数対象[0]要素数もし列数仮列数ならば列数仮列数
        仮行数対象要素数もし行数仮行数ならば行数仮行数
    ここまで
ここまで

●画面サイズ計算
  画面幅(列数+1)*マス幅
  画面高さ(行数+1)*マス幅
ここまで

ゲーム中フラグオフ

#データ
現在データ空配列
拾えるデータ空配列
拾った履歴空配列
空データ空配列
行数空データ[回数-1]0列数だけ配列要素作成ここまで

進行方向# 戻しボタンで進行方向を使うため
問題一覧問題集辞書キー列挙

#ゲーム画面とUI作成
問題セレクト問題一覧セレクトボックス作成
「     」ラベル作成
戻しボタン「一手戻す」ボタン作成
戻しボタン「title」「一つ前の状態に戻す」DOM属性設定
最初ボタン「最初から」ボタン作成
最初ボタン「title」「この問題を最初からやり直す」DOM属性設定
ヒント表示「❓」チェックボックス作成
ヒント表示「title」「チェックを入れると拾える石を明示します」DOM属性設定
改行作成
ゲーム画面[画面幅,画面高さ]キャンバス作成
改行作成

#UIイベント
問題セレクト「change」DOMイベント発火した時には
    ゲーム開始
ここまで

最初ボタンクリックした時には
    「最初からやり直しますか?」二択
    もしそれはいならばゲーム開始
ここまで

戻しボタンクリックした時には
    もし(拾った履歴要素数)ならば戻る
    ゲーム中フラグオン
    x=進行方向%列数y=(進行方向/列数整数部分)
    拾った履歴から配列ポップ
    ,,進行方向それ
    現在データ[][]1
    もし進行方向ならばゲーム開始# 最初から
    違えば[-x,-y]から拾えるデータ更新
    盤面描画
ここまで

ヒント表示「change」DOMイベント発火した時には
    問題描画
ここまで

ゲーム開始

●ゲーム開始
    問題問題集[問題セレクトテキスト取得]配列複製
    #初期化
    現在データ問題行数列数碁石データ整形
    拾えるデータ現在データ配列複製
    進行方向拾った履歴空配列
    #描画
    盤面描画
    ゲーム中フラグオン
ここまで

#マス目を描画
●盤面描画
    ベージュ色塗り色設定線太さ設定
    [0,0,画面幅,画面高さ]四角描画
    線太さ設定
    列数[マス幅*回数,0]から[マス幅*回数,画面高さ]まで線描画ここまで
    行数[0,マス幅*回数]から[画面幅,マス幅*回数]まで線描画ここまで
    問題描画
ここまで

#問題を描画
●問題描画
    白色塗り色設定1.5線太さ設定
    現在データ反復:
        
描画行マス幅*(対象キー+1)
        対象反復:
            
描画列マス幅*(対象キー+1)
            もし対象ならば[描画列,描画行]マス幅/2-1円描画
    もし(ヒント表示「チェック」DOM属性取得)オンならば:
        
黄色塗り色設定
        拾えるデータ反復:
            
描画行マス幅*(対象キー+1)
            対象反復:
                
描画列マス幅*(対象キー+1)
                もし対象ならば[描画列,描画行]マス幅/2-1円描画
ここまで

#問題を盤面の中央に配置できるようデータ整形
●(Aを行数と列数に)碁石データ整形
    問題A配列複製
    追加行数行数-(問題表行数)
    追加列数列数-(問題表列数)
    上追加行数追加行数/2切り捨て
    下追加行数追加行数/2切り上げ
    左追加列数追加列数/2切り捨て
    右追加列数追加列数/2切り上げ
    追加行空配列
    問題表列数追加行0配列追加ここまで
    上追加行数問題0追加行配列挿入ここまで
    下追加行数問題追加行配列追加ここまで
    追加列空配列
    問題表行数追加列0配列追加ここまで
    左追加列数問題0追加列表列挿入して問題代入ここまで
    右追加列数問題(問題表列数)追加列表列挿入して問題代入ここまで
    問題戻す
ここまで

#イベント
描画中キャンバスマウス押した時には
    もしゲーム中フラグオフならば戻る
    ,マウス位置取得
    もし拾えるデータ[][]1ならば
        現在データ[][]0
        進行方向[,]進行方向更新
        拾った履歴[,,進行方向]配列追加
        進行方向[,]から拾えるデータ更新
    ここまで
    盤面描画0.1秒待つ終了判定
ここまで

●マウス位置取得
    ((マウスX-マス幅/2)/マス幅)整数部分
    ((マウスY-マス幅/2)/マス幅)整数部分
    [,]戻す
ここまで

●(座標の)進行方向更新
    ,座標進行方向
    ,,,[列数*-1,列数,-1,1]
    もし(拾った履歴要素数)0ならば
        前列,前行拾った履歴[(拾った履歴要素数)-1]
        もし(前行)ならば進行方向
        もし(前行)ならば進行方向
        もし(前列)ならば進行方向
        もし(前列)ならば進行方向
    ここまで
    進行方向戻す
ここまで

●(進行方向と座標から)拾えるデータ更新
    ,座標
    拾えるデータ空データ配列複製
    上下左右[[0,-1],[0,1],[-1,0],[1,0]]
    上下左右反復
        x,y対象
        もし進行方向*-1y*列数xならば続ける# 後戻り禁止
        [,]から対象拾える石探索
    ここまで
ここまで

●(座標から方向へ)拾える石探索
    ,座標x,y方向
    もし(+x)また(+y)また(+x(現在データ表列数)-1)また(+y(現在データ表行数)-1)ならば戻る
    もし現在データ[+y][+x]ならば
        拾えるデータ[+y][+x]
    違えば
        [+x,+y]から方向拾える石探索
    ここまで
ここまで

●終了判定
    現在データ空データ同じ配列か確認
    もしそれはいならば:
        
「クリア!」言う
        ゲーム中フラグオフ戻る
    拾えるデータ空データ同じ配列か確認
    もしそれはいならば:
        
「失敗!」言う
        ゲーム中フラグオフ戻る
ここまで

●(AとBの|Bが)同配列確認
    もし(AJSONエンコード)=(BJSONエンコード)ならばはい戻る
    いいえ戻る
ここまで

動作確認

参考文献

 問題集に収録した12問は、以下の古典に載っている物です。
 答えがバッチリ載っているので、どうしても解けなかったらカンニングしましょう。
 くずし字も変体仮名も読めなくてもだいじょぶ!

『勘者御伽双紙』 中根法舳 1743 「八 ひろひものの事 七ヶ條

『和国知恵較べ 巻下』 環中仙 1727 「ますのひろい物」他4問

つづきます

 完成したけど続きますw
 当初の目標に、「問題を自分で作ったりしたい」てのがありましたよね~。忘れてましたが😅
 とゆうわけで、次回は問題作成機能を追加してみます。
 

1
0
3

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
1
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?