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

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

ただいまの
回答率

87.59%

Javascript 配列から除外

解決済

回答 1

投稿

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

score 46

今現在Javascriptを用いて、タイピングゲームらしきものを作ろうとしています。
1)重複を避けたランダム処理として、指定した配列から単語を引っ張ってくる。
2)打ち終わったら、自動で次の問題に移る。
3)すでに打ち込んだ文字は何らかの印をつける(ここでは便宜上@にしています)。

色々調べてspliceなどで配列を削れるかな、とか考えましたが、どうも上の3つがうまくいきません。
ただし、正しいボタンを押すと、ポイントは加算されているので、ボタンは認識されているはずです。アドバイスいただけると助かります。
HTML

<!DOCTYPE html>
<html lang="ja">
<head>
 <meta charset="utf-8">
 <title>Typing Game</title>
 <link rel="stylesheet" href="css/styles.css">
</head>
<body>
  <p id="target">word</p>
  <p class="info">
    あなたの点数: <span id="score">0</span>
    間違えた回数: <span id="miss">0</span>
  </p>

<script src="js/main.js"></script>
</body>
</html>

CSS

body {
  padding-top: 40px;
  font-family: 'Courier-new', sans-serif;
  text-align: center;
}

#target {
  font-size: 48px;
  letter-spacing: 3px;
}

.info {
  color: #ccc;
}

JS

'use strict';
{

 const words = [
   'ball',
   'trip',
   'summer',
   'orange',
 ];
 let word;
 let loc = 0;
 let score = 0;
 let miss = 0;
 let i, j, temp;
 let question;


 const target = document.getElementById('target');
 const scoreLabel = document.getElementById('score');
 const missLabel = document.getElementById('miss');

 function shuffle(arr){
   i = words.length;
   // if(i === 0){
   //   return arr;
   // }
   while(i > 0){
     j = Math.floor(Math.random() * i);
     i--;
     temp = arr[i];
     arr[i] = arr[j];
     arr[j] = temp;
   }
   return arr;
 }

  word = shuffle(words);
  question = word[i];
  target.textContent = question;
 //
 function updateTarget(){
   let placeholder = '';
   for( let s = 0; s < loc; s++){
     placeholder += '@';
   }
   target.textContent = placeholder + word.substring(loc); ///ここをどうしたらいいかわからなくなりました。
 }

 window.addEventListener('keyup', e => {
   if (e.key === question[loc]) {
     loc++;
   if(loc === question.length){
     word.splice(word.length -1, 1);
    target.textContent = word[i];
    loc = 0;
   }
     score++;
     scoreLabel.textContent = score;
     // updateTarget();
   } else {
     miss++;
     missLabel.textContent = miss;
   }
 });
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+1

codepenで簡単に修正して動かしてみました。
やりたいことはこのようなことですよね?
(だたし、問題が尽きたときにエラーになるので、配列がオーバーしないように
https://codepen.io/fujinaka/pen/mgxqmx

>///ここをどうしたらいいかわからなくなりました。
の部分ですが、wordをスライスで削っていくのではなく、添字で進めていくほうがキレイだと思います。

:
:
   target.textContent = placeholder + word[i].slice(loc,);
:
:
   if(loc === question.length){
    if (word.length <= i) {
      return;
    }
    target.textContent = word[++i];
    question = word[i];
    loc = 0;
   }
:
:


ちなみに掲載のプログラムはsliceの使い方が間違ってます。
sliceそのものは配列を変更しないので、返却した配列を受け取る必要があります。
つまり、

word.splice(word.length -1, 1);


ではなく下記のように返却した配列を受け取る必要がありますし、引数も逆転してます。

word = word.splice(1, word.length -1);

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2019/04/19 01:51

    詳細な回答ありがとうございました。確かにspliceなどはまだまだ基本がなってなかったですね。助かりました。
    また、これもかなり基本だとは思いますが、
    i = 0; として正解のたびにi++;する代わりに、i = word.length - 1として、i--にしてもいいんでしょうかね。

    キャンセル

  • 2019/04/19 07:56

    問題ありません。
    その場合は、iが0未満にならないように、i<=0になったらカウントダウンを終了するような条件を付ける必要があります。
    また、インクリメント(--、++)は前に置くか(--i、++i)後ろに置くか(i--、i++)でカウントアップするタイミングが変わるのでご注意ください。
    i--にする場合は、「target.textContent = word[i]」この行の前に実行する必要があります。

    キャンセル

  • 2019/04/19 22:43

    最後まで詳しくありがとうございました。大変助かりました。

    キャンセル

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

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

関連した質問

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