1
2

More than 1 year has passed since last update.

wordle のヒントサイトをJavaScriptのテキストファイル操作と正規表現で作る

Last updated at Posted at 2022-01-24

人気の wordle …… でも英単語知らな過ぎてぴえん😢

とっても面白いのですがさすがに知らない英単語はきつい・・・ちょっとくらいヒントが欲しい。
ということでヒントを出してくれるサイトを作ってみます。
(場合によってはほぼ答え)

wordle の説明は省略。

JavaScript使ってプログラムを組むチュートリアルとしてもお使いください。 fetch でデータ取ってきて正規表現で検索するサンプルです。

最終的なサイトはここにしばらくアップしておきます。しばらくしたら消します…。
https://wonderful-mahavira-53578c.netlify.app/

まず戦略を考える

バックエンドの準備が手間なのでデータベースは使わない。
インメモリでフロントエンドだけで力技でどうにかしたい。
👉 テキストファイルの英単語一覧から正規表現で検索をかけよう!

インタフェース(UI)を考える

まずインタフェースを考えます。
機能はインタフェースの実装なので機能から考えるのはだいたいのケースで悪手です、インタフェースから考えましょう。

5文字の英単語なのでインプットの箱を5つ用意する。
「緑」と「黄色」を「大文字」「小文字」で使い分けるようにしてみる。
結果を下に出す。

image.png

JavaScriptでの実装を考える

英単語リストを読み込む

こんな感じの英単語が並んだテキストファイルを用意します。
探すと色々なところに置いてあります。

Apple
appleberry
Appleby
appleblossom
:

これをサーバーにおいてJavaScriptで読み込む処理を作ります。
難しいこと考えずに fetch で読み込んで、改行コードで split をして配列に乱暴につっこみます。

    let words = []
    fetch('words.txt')
    .then(response => response.text())
    .then(data => {
        words = data.split(/\n/);
    });

正規表現をつくる

input に文字が入力されたタイミングで単語リストから検索をするための正規表現を作ります。
入力されたタイミングで処理をしたいので addEventListener(input) でイベントを仕掛けておきます。

    document.querySelectorAll('input').forEach( function(target) {
        target.addEventListener('input', function() {
            // ここに正規表現つくって検索する処理
        });
    });

image.png

文字の位置が正しくわかってる場合にはこんな正規表現を作ります。

    '^..P..$'
  • ^ … 文字列の先頭
  • $ … 文字列の末尾
  • . … 何でもいい1文字

実際に正規表現を作るのはベタなテキスト操作で十分です。
toUpperCase() つまり大文字にしたものと元の文字が等しければ、つまり、もともと大文字だったならその文字を使って、それ以外なら . にしてパターンに足してくだけです。

    function getPatternChara(name){
        const tmp = document.getElementById(name).value
        return tmp!=0 && tmp===tmp.toUpperCase()? tmp : '.' 
    }

    let pattern = '^'
    pattern += getPatternChara('c1') // 箱の1つ目
    pattern += getPatternChara('c2') // 箱の2つ目
    pattern += getPatternChara('c3') // 箱の3つ目
    pattern += getPatternChara('c4') // 箱の4つ目
    pattern += getPatternChara('c5') // 箱の5つ目
    pattern += '$'

次に 背景黄色 のパターンです。

image.png

その文字は単語内にあるけど文字の位置は正しくないって場合はこんな2つの正規表現を作ります。

    '^(?=.*p)'
    '^..[^p]..$'
  • .*p … p が含まれている
  • ..[^p].. 3文字目が p ではない

もうす少し複雑なパターンで、例えば、、、

image.png

これだとこんな3つの正規表現を作ります。

    "^..P..$"
    "^(?=.*l)(?=.*a)"
    "^.[^l].[^a]."
  • P が3文字目で、
  • l か a がどこかにあって、
  • 2文字目が l じゃない、4文字目が a じゃない

作った正規表現を使ってフィルターする

        const results = words.filter(word =>
            word.length==5 &&
            word.match(new RegExp(pattern,'i')) &&
            word.match(new RegExp(pattern2,'i')) &&
            word.match(new RegExp(pattern3,'i')));
        const result  = document.getElementById('result');
        result.value = results.join('\n');

RegExp を使って3つのパターンを正規表現として扱い match に与えます。( 'i' は大文字小文字を区別しないためのオプションです )
そういえば単語5文字だったなと思って最初に length==5 の条件も加えています。
これらを英単語の配列の filter に渡して絞り込みを行います。

結果が出たところで、改行でつなぎなおして結果を画面に出力しておしまい。

まとめ

簡単なテキスト操作ならWebサーバーにファイルおいちゃってJavaScriptで読み込ませればサクッとできる。
最近のPCはスペックいいのでこれくらいならインメモリでできちゃう。
・・・とはいえ、5MBくらいの英語辞書をページ起動時にいっきに読み込む迷惑このうえない作りなのであくまでこんな方法もあるよ!くらいで。

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