h16k / kanji-puzzle-js

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

marp
true

HTML&CSS&JavaScript入門

漢字パズル生成ツールを作ろう

Demo


目次


HTML

index.html


body全体

<body>
    <h2>Kanji Puzzle Maker</h2>


    <input name="答え" type="text" id="answerText" placeholder="漢字2文字で入力" onkeypress="enter(event.keyCode);">
    
    <button onclick="createPuzzleProcess();"> 生成</button>
    <br>
    <input type="radio" id = "blue" name="tempColor" value="blue" checked onclick="colorChange();">
        <label for = "blue">Blue</label>
    <input type="radio" id = "green" name="tempColor" value="green" onclick="colorChange();">
        <label for = "green">Green</label>
    <input type="radio" id = "orange" name="tempColor" value="orange" onclick="colorChange();">
        <label for = "orange">Orange</label>    
    <input type="radio" id = "pink" name="tempColor" value="pink" onclick="colorChange();">
        <label for = "pink">Pink</label>
    
    <h3 id="createResult"></h3>
    
    <p id="note"></p>

    <canvas id="puzzleCanvas"></canvas>
    <canvas id="answerCanvas"></canvas>
</body>

アプリ名

<h2>Kanji Puzzle Maker</h2>
  • 見出しの部分

答えとなる熟語を入力する場所

<input name="答え" type="text" id="answerText" placeholder="漢字2文字で入力" onkeypress="enter(event.keyCode);">
  • <input>は入力フォームを作成するタグ
  • nameinputタグの名前
  • typeは入力するデータの種類
  • idはタグを一意に識別できる名前
  • placeholderは何も入力していないときにうっすら表示されるテキスト
  • onkeypressで、この入力フォームの中で何かキーが押されたときの処理を指定
    • ここではenterという関数を呼び出している
      • 引数は「押したキー(のコード)」

パズル生成ボタン

<button onclick="createPuzzleProcess();">生成</button>
  • <button></button>はボタンを作成するタグ
  • タグの間にボタンに表示するテキストを書く
  • onclickで、このボタンが押されたときに行う処理を指定
    • ここでは、createPuzzleProcess()を実行
<br>
  • 改行

色選択・変更ボタン

<input type="radio" id = "blue" name="tempColor" value="blue" checked onclick="colorChange();">
<label for = "blue">Blue</label>
<input type="radio" id = "green" name="tempColor" value="green" onclick="colorChange();">
<label for = "green">Green</label>
---略---
  • <input>type="radio"にすることで、ラジオボタンを作成できる
  • valueでこのボタンが選択されているときに何という値として扱うかを指定
  • checkedをつけると最初から選択状態になる
  • nameが同じラジオボタンは1つのグループ扱いとなる
    • ユーザーはこの中から1つしか選択できない
  • <label>でinputタグにラベルを付ける
    • for = "blue"だったらid="blue"のinputタグと紐づく
    • ○の横にblueなどと表示されるようになる

パズル生成結果のお知らせ

<h3 id="createResult"></h3>

<p id="note"></p>
  • <h3></h3>で見出し3(3番目に大きい見出し)を作成
    • 最初の状態では何も表示するものがない
      • あとでパズルの生成結果に応じてテキストが入ることになる
      • idを手掛かりに
  • <p></p>で段落を作成
    • 最初の状態では何も表示するものがない
      • あとでパズルの生成結果に応じてテキストが入ることになる
      • idを手掛かりに

生成したパズル画像を表示する場所

<canvas id="puzzleCanvas"></canvas>
<canvas id="answerCanvas"></canvas>
  • <canvas></canvas>で図を表示する場所を作成できる
    • 最初の状態では何も表示するものがない
      • あとでパズルの生成結果に応じてパズルの画像が入ることになる
      • idを手掛かりに

Javascript

puzzleList.js


パズル生成のためのデータ

const stringPuzzles = `哀楽 哀願 安楽 音楽 快楽 楽園 楽屋 ------';
  • 文字列をstringPuzzlesに格納
  • 文字列は、1行ごとに↓
    • 先頭に「答えとなる熟語」
    • その後ろに「答えの1文字目or2文字目を使った熟語」が並んでいる
    • 上の例では「哀楽」が答えで、哀や楽を使った熟語が後ろに並んでいる
      • 熟語は常用漢字を使ったもののみ
        • 難易度が高くなりすぎないように

パズル生成のためのデータを1行ごとに分割

const puzzleStringDividedPerLine = stringPuzzles.split('\n');
  • stringPuzzlesに格納されている文字列を1行ごとに分割し、puzzleStringDividedPerLineに格納
    • .split()で文字列を分割できる
      • ()にはどこで分割するかを指定
        • ここでは改行を表す\nで分割
        • ほかにも、例えばsplit(',')にすればカンマで分割される
    • puzzleStringDividedPerLineはリストになっている
      • ["哀楽 哀願 安楽 音楽 快楽 楽園 ...","悪意 悪化 悪寒 悪気 悪口 ...", ...]
      • というイメージ

後で使うリストとマップを用意

const hintList = [];
const puzzleIndexMap = new Map();
  • hintListpuzzleIndexMapを用意しておく
    • hintListは配列
    • puzzleIndexMapはマップ
      • マップはキー(key)とそれに対応する値(value)を対応させて保持するオブジェクト
      • 参考

パズルのデータを使いやすい形に整理する① 繰り返し処理

puzzleStringDividedPerLine.forEach(function(puzzleString, ind){
	----------------------
});
  • 配列名.forEach( コールバック関数(要素の値, 要素のインデックス) )
    • 配列の先頭から要素を1つずつ呼び出してコールバック関数を実行
      • 要素の値は要素の値に、
      • 要素のインデックスは要素のインデックスに渡される
    • 今回の場合
      • puzzleStringDividedPerLineの要素を1つずつ取り出しながら、要素をpuzzleStringに、要素のインデックスをindに渡してfunctionを実行

パズルのデータを使いやすい形に整理する② 繰り返しの中身1

puzzleStringDividedPerLine.forEach(function(puzzleString, ind){
    let aPuzzle = puzzleString.split(' ');
    hintList.push(aPuzzle.slice(1,-1));
    puzzleIndexMap.set(aPuzzle[0], ind);

});
  • let aPuzzle = puzzleString.split(' ');の部分
    • puzzleStringの中身は、 ["哀楽 哀願 安楽 音楽 快楽 楽園 ...","悪意 悪化 悪寒 悪気 悪口 ...", ...] のようなリストの要素
      • "哀楽 哀願 安楽 音楽 快楽 楽園 ..."というような感じ
    • これを空白で分割し、["哀楽", "哀願", "安楽", "音楽", "快楽", "楽園" ...]というようなリストを作成

パズルのデータを使いやすい形に整理する③ 繰り返しの中身2

puzzleStringDividedPerLine.forEach(function(puzzleString, ind){
    let aPuzzle = puzzleString.split(' ');
    hintList.push(aPuzzle.slice(1,-1));
    puzzleIndexMap.set(aPuzzle[0], ind);

});
  • hintList.push(aPuzzle.slice(1,-1));の部分
    • aPuzzleは、["哀楽", "哀願", "安楽", "音楽", "快楽", ...]という感じ
    • これ(の一部)をhintListに追加(配列名.push()()内を配列に追加)
      • hintList[["哀願", "安楽", "音楽", "快楽", "楽園" ...],["悪化", "悪寒", "悪気", "悪口", ...]]というような二次元の配列に
      • aPuzzle.slice()によって配列の一部を取り出す(次ページ)

パズルのデータを使いやすい形に整理する③ 繰り返しの中身2.5

  • aPuzzle.slice(1,-1)の部分
    • 配列名.slice(x,y)で配列のxからy-1番目の要素までを取得
      • 例えば[0,1,2,3,4,5]の配列examに対してexam.slice(1,3)を適用すれば[1,2]が取得できる([1,2,3]ではない)
    • つまりここではaPuzzleの先頭と末尾の要素を除いた配列を取得している
      • 先頭は答えとなる熟語→hintListには不要
      • 末尾は、実はaPuzzleの末尾の要素が""になっている
        • パズルのデータを作るときにミスりました。謝罪。
        • よって、いらない。

パズルのデータを使いやすい形に整理する④ 繰り返しの中身3

puzzleStringDividedPerLine.forEach(function(puzzleString, ind){
    let aPuzzle = puzzleString.split(' ');
    hintList.push(aPuzzle.slice(1,-1));
    puzzleIndexMap.set(aPuzzle[0], ind);

});
  • puzzleIndexMap.set(aPuzzle[0], ind);の部分
    • マップ名.set(キー,値)で、マップにキーと値を登録
    • ここではpuzzleIndexMapに以下を登録
      • キー:aPuzzleの先頭の要素
        • aPuzzleは、["哀楽", "哀願", "安楽", "音楽", "快楽", ...]という感じなので、先頭の要素=答えとなる熟語
      • 値:ind
        • こうすることで、キーの熟語が答えになるパズルを作るときに、hintListの何番目を見たらいいかがわかるようになる

index.js

コメントを読みつつ解読してみよう!

(後日解説する予定がないこともない)

About


Languages

Language:JavaScript 98.9%Language:HTML 0.6%Language:CSS 0.5%