質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.64%

【JavaScript】タイピングゲームで空白文字をスキップしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 891

umauman

score 55

実現したいこと

JavaScriptでクイズを作成しています。
答えを英語でタイピングしてもらうものです。

【問題】りんごは英語で何と言いますか?
【答え】apple ←タイピングする

■仕様
・予め単語の文字数分アンダーバーを表示
・タイプした文字があっていればアンダーバーが消えていく

こんな感じです
※アンダーバーと文字の間は実際はくっつていますが、
スタイルシートで間を空けています。

_ _ _ _ _

a p _ _ _

a p p l e

試行錯誤しながら下記コードで実現できました。

単語に空白が無い場合にうまくいくコード

var word = 'apple'; //答え
var charPosition = 0; //現在何文字目か
var englishField = document.getElementById('english');
var underbar = ''; //アンダーバー

//答えの文字数だけアンダーバーを表示する
for(var i = 0; i < word.length; i++){
    underbar += '_';
}
englishField.textContent += underbar;

//タイピングした文字を表示して、アンダーバーを消していく
window.addEventListener('keyup', function(e){
    if(String.fromCharCode(e.keyCode) === word[charPosition].toUpperCase()){
        charPosition++;
        englishField.textContent = word.substring(0, charPosition) + underbar.slice(charPosition);
    }
});
<p>りんごは英語で何と言いますか?</p>
<div id="english"></div>
#english{
    letter-spacing: 5px;
}


ただ、単語の間に空白がある場合はアンダーバーを表示せず、タイピングした際もスキップさせたいです。

例えば「green apple」が答えだった場合、下記のようにしたいです。

①最初は下記のように表示

_ _ _ _ _   _ _ _ _ _

②「greenapple」と連続で入力したら自動で間が空く

g r e e n   a p p l e

下記ソースで①の「空白の場合はアンダーバーをスペースにする」ところまではなんとかできました。
ただ、「green」の「n」をタイプしたら自動的にスペースをスキップして「a」に移動してくれる、という処理がうまくいきません。
現在の単語の文字の次が空白だった場合にスキップ処理をする、というようにしたいので
if(word[charPosition + 1] === ' ')という条件でいいのかなとも思っているのですがその先に進むことができません。

単語に空白がある場合うまくいかないコード

var word = 'green apple'; //答え
var charPosition = 0; //現在何文字目か
var englishField = document.getElementById('english');
var underbar = ''; //アンダーバー
var placehorder = ''; //アンダーバーとスペースを合算したもの

//答えの文字数だけアンダーバーを表示するスペースは空白にする
for(var i = 0; i < word.length; i++){
    if(word[i] === ' '){
        underbar = ' ';
    } else {
        underbar = '_';
    }
    placehorder += underbar;
    englishField.textContent = placehorder;
}

//タイピングした文字を表示して、アンダーバーを消していく
window.addEventListener('keyup', function(e){
    if(word[charPosition + 1] === ' '){
        //ここで何等かの処理?
        //例えば
        //charPosition += 2;
        //としてみたところgreenの「n」が表示されずappleの「a」を押したら表示されます。
    } else if (String.fromCharCode(e.keyCode) === word[charPosition].toUpperCase()){
        charPosition++;
        englishField.textContent = word.substring(0, charPosition) + placehorder.slice(charPosition);
    }
});
<p>青りんごは英語で何と言いますか?</p>
<div id="english"></div>

どのように記述をしたら良いでしょうか?
質問がわかり辛い場合は補足しますのでおっしゃってください。

また、そもそも全体的にもっと簡素に記述できる方法や間違いがありましたらアドバイスいただけますととても助かります。
どうぞよろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

これで動いた。

window.addEventListener('keyup', function(e){
    if (word[charPosition] && String.fromCharCode(e.keyCode) === word[charPosition].toUpperCase()){
        charPosition++;
        englishField.textContent = word.substring(0, charPosition) + placehorder.slice(charPosition);
    }
    if(word[charPosition] && word[charPosition] === ' '){
        charPosition++;
    }
});

動くサンプル:https://jsfiddle.net/4n1y41z3/1/

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/07/22 01:46

    サンプルわざわざありがとうございます。
    こちらで動作することを確認しました。

    if...else ifにしてしまうと最初の判定で処理が終わってしまうから、というのを何となく理解したつもりですが何故ダメなのかもうちょっと考えてみることにします。

    両方の条件に追加いただいた
    if(word[charPosition] && …)
    は"word[charPosition」が存在している"という判定であっていますか?
    こちらは無くても動作しますが、単語の最後は判定する文字が存在しなくなってしまうためちゃんと入れておいた方がいい、という認識で間違いないでしょうか?

    後は下記のように順番を変更しても動作するのですが、
    もしこの順番に意味がある場合は教えていただけないでしょうか?
    (質問時点では下記の順番にしていたため…)

    if(word[charPosition] && word[charPosition] === ' '){
    //処理
    }
    if (word[charPosition] && String.fromCharCode(e.keyCode) === word[charPosition].toUpperCase()){
    //処理
    }

    お答えいただける範囲で大丈夫です。
    何度も申し訳ございません。

    キャンセル

  • 2017/07/22 02:06

    > ちゃんと入れておいた方がいい
    無い数字を入れてもエラーになりませんが、癖でそうしているだけなので気にしないでください。

    > 後は下記のように順番を変更しても動作するのですが、
    そうですね。
    すみませんが正直具体的にコードを追っていないのです。「String.fromCharCode」のifの処理に「何文字目」が深くかかわっていたら処理が面倒(になるかもしれない)なので、後に回しました。

    端的に言うと「「 === ' '」のときに処理をしていないから問題なのでそこをとりあえず置き換えた」コードになります。

    キャンセル

  • 2017/07/22 02:16

    何度もお答えいただきすみません。
    普段から癖にしているものがあるのですね。無くても恐らく大丈夫だけど経験上、しておくと安心というものがあるのかな…と思いました。
    この度はありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る