0
0

More than 1 year has passed since last update.

Vue.jsでHit-And-Blowを作ってみる

Posted at

前置き

急に話は変わりますが、皆さんSwitchの世界の遊び大全51というゲームは知ってますでしょうか。
その中の一つにヒットアンドブローっていうゲームがあって、それがめっちゃ頭を使って楽しいんですよ。そこで、Vue.jsのチュートリアルが終わった今、作ってみることにしました。
あと、TypeScriptで書きます。
スタイルには、BootStrapを使用します。

環境

Windows11/22H2
Node v16.13.1
Vue v3.2.45

アプリケーション作成

Vue.js公式のcreate-vueをインストールして実行し、Vueのアプリケーションを作成します。

Add TypeScript? … No / Yes

と聞かれるので、Yesと答えます。
ほかはNoです。
参考:https://ja.vuejs.org/guide/quick-start.html#creating-a-vue-application

できたら、srcのなかに色々ファイルが入っていると思います。
今回やるのは1ページで済ますので、App.vue以外を削除し、App.vueの一番上のimportしている部分も削除します。
これで、準備は完了です。

作成開始

最終完成形はこれになります。
finaly.png
では、HTMLから書いていきます
ボタンをまずは作ります

<button class="btn btn-outline-dark " @click="select_color('blue')"></button>

これは、赤ボタンだけなのでこれを残り5個作り、全色揃えます。

for文でやる方法も考えられますが、まだチュートリアルやったばっかりなので許してください;;

@clickselect_color()の引数には、それぞれの色を入れておいてください。

また、枠を選択するためのボタンを作成します。

<button @click="select_color('right')"></button>

これは右用なので、左も作ります。

では、次に表を作ります。

<tr>
    <th>1</th>
        <td ref="1-1"></td>
        <td ref="1-2"></td>
        <td ref="1-3"></td>
        <td ref="1-4"></td>
        <td ref="1-result"></td>
</tr>

これも1ターン目だけなので、8ターン分作ります。

for文でやる方法(ry

構成としては、JSのIDみたいに、要素を選択するためにあるVueのref=""を指定して、JS上からここを変えていきます。

JSを書いていく

まずは、data()で、どこからでもいじれる変数を作っていきます

data() {
    return {
      turn:1,
      block:[[],[],[],[],[],[],[],[]],
      com:["null"],
      color:["red", "blue", "yellow-green", "yellow", "pink", "white"],
      selection:1,
      old_selection:0
    }
  }

turn:現在のターン
block:選択してきた色をすべてのターンでこの配列に入れる
com:コンピューターの色の組み合わせ
color:6色の羅列
selection:現在どの枠を選択しているか
old_selection:前、どの枠を選択していたか(枠のCSSを変えるために使う)
って感じです。

ページがロードされた時

コンポーネントがマウントされた時、Vue.jsでは、mounted()が呼び出されます。
参考:https://ja.vuejs.org/api/options-lifecycle.html#mounted

mounted() {
    window.onload = ()=>{
      for (let i = 0; i < 4; i++) {
    this.com[i] = this.color[Math.floor(Math.random() * 6)];
  }
  (this.$refs[`1-1`] as any).className = "selection"
    }
}

ここでは、CPUの色の組み合わせを決めています。

ボタンが押された時

色のボタンが押された時、@click=""で書いた、select_color()の関数が実行されるようになります。

select_color(tmp:string){
      switch (tmp) {
        case "right":
          if(this.selection !== 4){
            this.old_selection = this.selection;
          this.selection++;
          break;
          }else{
            break;
          }
        case "left":
          if(this.selection !==1){
            this.old_selection = this.selection;
        this.selection--;
          break;
          }else{
            break;
          }
        default:
          (this.block[this.turn-1][this.selection-1] as any) = tmp;
          console.log(this.turn);
          console.log(this.selection);
          ((this.$refs[`${this.turn}-${this.selection}`]) as any ).innerHTML = `<img src="/${tmp}.svg"/>`
          if(this.selection !== 4){
            this.old_selection = this.selection;
          this.selection++;
          }
      }
    }

ここでは、switch構文を使っています。
rightleftが引数の時、枠移動になるのでそのコードを。
その他は色が引数になるので、色が押されたときを処理します。

watchで、枠移動

ここが、Vueで書いてていいなって思った点です。
さっきどこからでもいじれる変数を作ったんですが、それの値が変わったときに関数を実行できるようにできるんですね。

watch: {
    selection(new_select){
      (this.$refs[`${this.turn}-${this.old_selection}`] as any).className = "";
      (this.$refs[`${this.turn}-${new_select}`] as any).className = "selection";
    }
  }

watchを使うと、関数名を変数の名前にして引数に更新された値で、変数の値が変わったときに関数を実行できるようになります。
ここがいいなと思った点でもあります。

ヒットかブローか

ヒットかブローかを判定するコードを書いていきます。

if(this.block[this.turn-1].length ==4){
        let hit = 0;
        let blow = 0;
        let alreadyhit = [];
        for (let index = 0; index < 4; index++) {
      if (this.com[index] == this.block[this.turn-1][index]) {
        hit++
        console.log(hit)
        alreadyhit.push(index)
      }
    }
    for (let index = 0; index < 4; index++) {
      if (this.com.includes(this.block[this.turn-1][index])) {
        if (!alreadyhit.includes(index)) {
          blow++;
          console.log(blow)
        }
      }
    }
    this.old_selection = this.selection;
    (this.$refs[`${this.turn}-result`] as any).textContent = `${hit}ヒット/${blow}ブロー`;
    this.turn++;
    (this.$refs[`${this.turn-1}-${this.old_selection}`] as any).className = "";
      (this.$refs[`${this.turn}-1`] as any).className = "selection"
    this.selection=1;
      }

上から、まず4つのすべてが選択されているかをifでチェックします。

次に、ヒットかどうか
ヒットというのは、場所も色もあたっているということなので、for文で、コンピュータの[]番目 == 選んだ[]番目かどうかを調べます。

そして、ブローかどうか
ブローというのは、色があたっていればいいので
これもfor文で選んだ[]番目がcomに含まれているかをチェックします

if (this.com.includes(this.block[this.turn-1][index]))

includesで、配列に含まれているか調べます。
そして、ここが注意なんですが、ヒットのときの色もブローの中に含まれてしまうので、すでに色として含まれているのかを調べます。

Github

ここまで書いて、めちゃくちゃわかりにくい説明だったとも思います。
ぜひ、ぐちゃぐちゃなのも承知の上で、ソースコードを見てほしいです。
https://github.com/Skota11/hit-and-blow
デプロイしたものもNetlifyで作ったので、どうぞ
https://hit-a-blow.netlify.app

0
0
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
0
0