Vue.jsで超簡単なタイピングゲームを作ります

#完成品
![demo](https://gyazo.com/2e09cc6dde50f09281f932e12dd48a57/raw) 
***

```vuejs:App.vue
<template>
  <div id="app">
    <div v-if="playing">
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
    <div v-else>Spaceでスタート</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
      playing: false,
    };
  },
  created() {
    addEventListener('keydown', (e) => {
      if (e.key !== ' ' || this.playing) {
        return;
      }
      this.playing = true;
      this.setWord();
      this.keyDown();
    });
  },
  methods: {
    setWord() {
      this.word = this.words.splice(Math.floor(Math.random() * this.words.length), 1)[0];
    },
    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          if (this.words.length === 0) {
            this.word = 'おしまい';
            return;
          }
          this.setWord();
        }
      });
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

span {
  opacity: 0.5;
}
</style>
```

# 配列からランダムな値を取り出す

`setWord`メソッドを作り、`created`で呼び出しています。
その際`words`の中からランダムな値を`word`に格納。

```vuejs:App.vue
<template>
  <div id="app">
    <div>
      {{ word }}
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
    }
  },
  created() {
    this.setWord();
  },
  methods: {
    setWord() {
      this.word = this.words[Math.floor(Math.random() * this.words.length)];
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
```

#タイピングの処理
`keyDown`メソッドを作り、`created`で呼び出しています。
入力されたKeyと現在の`word`の頭文字が一致しない場合は`miss`が加算。

`pressed`には入力されたkeyを格納。
`word`にはkeyが押されるごとに頭文字を削除し再代入します。
これで入力した文字と未入力の文字を仕分けしています。
`word`が全て無くなったら`pressed`をリセットし、新しい`word`を表示させます。

```vuejs:App.vue
<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
    }
  },
  created() {
    this.setWord();
    this.keyDown()
  },
  methods: {
    setWord() {
      this.word = this.words[Math.floor(Math.random() * this.words.length)];
    },
    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          this.setWord();
        }
      });
    },
  }
}
</script>
```
***
Viewで`pressed`と`word`連結させます。
入力されていることが分かりやすいように`pressed`を`span`タグで囲みスタイルをつけます。

あと`miss`のカウントをここで表示させます。

```vuejs:App.vue
<template>
  <div id="app">
    <div>
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
  </div>
</template>

<style>
span {
  opacity: 0.5;
}
</style>
```
![スクリーンショット 2020-12-01 22.33.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635852/4b442204-97e2-c6a2-26ad-786b90a021c0.png)

***

# 単語の重複を防ぐ
現時点だと単語が重複して無限に遊べるので一度出た単語は消してしまいます。

```vuejs:App.vue
<script>

    setWord() {
      this.word = this.words.splice(Math.floor(Math.random() * this.words.length), 1)[0];
    },

</script>
```

# ゲームの開始と終了の処理

`data`に`playing`を追加しSpaceキーを押すことで`false`から`true`にします。

```vuejs:App.vue
<template>
  <div id="app">
    <div v-if="playing">
      <span>{{ pressed }}</span>{{ word }}
      <br>
      <br>
      miss:{{ miss }}
    </div>
    <div v-else>Spaceでスタート</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      words: ['apple', 'banana', 'grape'],
      word: '',
      pressed: '',
      miss: 0,
      playing: false,
    }

</script>
```
***
Spaceキーが押されたら`playing`が`true`になり、ゲームスタートです。
`|| this.playing`で再スタートを防ぎます。

```vuejs:App.vue


<script>

  created() {
    addEventListener('keydown', (e) => {
      if (e.key !== ' ' || this.playing) {
        return;
      }
      this.playing = true;
      this.setWord();
      this.keyDown();
    });
  },

</script>
```

***

`words`が空になったら`おしまい`と表示させゲーム終了です。

```vuejs:App.vue
<script>

    keyDown() {
      addEventListener('keydown', (e) => {
        if (e.key !== this.word[0]) {
          this.miss++;
          return;
        }
        this.pressed += e.key;
        this.word = this.word.slice(1);
        if (this.word.length === 0) {
          this.pressed = '';
          if (this.words.length === 0) {
            this.word = 'おしまい';
            return;
          }
          this.setWord();
        }
      });
    },
  }
}
</script>
```

# おしまい
以上となります。
もっとこうした方が良いんじゃない？
というのがあれば是非教えて下さいm(_ _)m