Vue.jsでゲームを作ろ! - ○×ゲーム - 1
参考サイトです。
・ ○×ゲーム(3目並べ)をVueでつくります。
・ ○は赤文字、×は青文字にする。
・ どちらの番かが分かるように「○(×)プレイヤーさん、マスを選んでください」と表示する(つまり2Pプレイ)
・ ゲームが終了したら「○(×)さんの勝ちです。おめでとうございます!」と表示する
・ 引き分けの場合は「引き分けです!」と表示する
早速ですが基本の形です。上記サイトのコードをVue.js 3.0で書き直します。
<html>
<head>
<style>
css(スタイルシート記述)
</style>
</head>
<body>
<div id="app">
<!-- ここがVueエリア -->
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const App = {
data() {
}
}
Vue.createApp(App).mount('#app')
</script>
</body>
</html>
まずゲーム盤を作ります。"table"タグで組んで行きます。
<table id="table">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
この"table"タグのみではテーブルの枠線が表示されないので、スタイルシート"css"を書いていきます。
#table {
margin:0 auto;
border-collapse: collapse;
border: 3px solid #ccc ;
}
#table td {
border:1px solid #ccc ;
height: 80px;
width: 80px;
text-align: center;
vertical-align: middle;
font-size: 75px;
cursor: pointer;
}
これで無事テーブルが表示されます。
このテーブルを"Vue"で書き換えていきます。
スクリプト部分です。
マス目の状態(3×3の配列) ・・・ status
選択できるプレイヤーのID ・・・ playerId
const App = {
data() {
return{
states: [
[-1, -1, -1],
[-1, -1, -1],
[-1, -1, -1]
],
playerId: 1
}
}
}
HTML部分です。"v-for"で"states"の値を使ってループを回して3×3のマス目を作ります。
"v-if"では"states"の値、
states: [
[-1, -1, -1],
[-1, -1, -1],
[-1, -1, -1]
],
でゲーム版の表示をコントロールするので、この数字によって
-1 ・・・ まだ選択されてない
1 ・・・ ○が選択されている
2 ・・・ ×が選択されている
とします。
<table id="table">
<tr v-for="row in states">
<td v-for="state in row">
<div style="color:#f00;" v-if="state==1">○</div>
<div style="color:#00f;" v-if="state==2">×</div>
</td>
</tr>
</table>
2人のプレイヤーが交互に選んでいきます。その順番を表示で示します。
現在マスを選ぶことができるプレイヤーのIDなので、このIDを使って次の2つの表示を切り替えるようにしてみます。
○ プレイヤーさん、マスを選んでください
× プレイヤーさん、マスを選んでください
ゲーム盤の下に表示させたいので、"table"タグの下にコードを書きます。
<div style="text-align:center;">
<div style="color:#f00;" v-if="playerId==1">「○ プレイヤーさん、マスを選んでください」</div>
<div style="color:#00f;" v-if="playerId==2">「× プレイヤーさん、マスを選んでください」</div>
</div>
" v-if"で"playerId"の数字を確認してプレイヤーが現在どちらであるかを表示します。以下の表示となります。
マス目が選択されたときのコード部分はというと、
<tr v-for="row in states">
<td v-for="state in row">
の部分を選択できるように、
<tr v-for="(row,rowsIndex) in states">
<td v-for="(state,colsIndex) in row" @click="onSelect(rowsIndex, colsIndex)">
として
マス目を押す" @click="onSelect(rowsIndex, colsIndex)"ことで
"(rowsIndex, colsIndex)"の情報を取得します。
そのスクリプト部分です。
const App = {
の部分に書いていくのですが、ここで
data():,
methods:
}
という感じに","で区切ります。
methods: {
onSelect: function(rowsIndex, colsIndex) {
if(this.states[rowsIndex][colsIndex] != -1) {
alert('そのマスは、すでに選択されています!');
} else {
var states = JSON.parse(JSON.stringify(this.states))
states[rowsIndex][colsIndex] = this.playerId;
this.states = states;
this.playerId = (this.playerId == 1) ? 2 : 1;
}
}
}
"methods:"の中身ですが、マス目を押したという
onSelect:
が実行された時引数"rowsIndex, colsIndex"を使った関数が実行されます。
if(this.states[rowsIndex][colsIndex] != -1){
alert('そのマスは、すでに選択されています!');}
"states"が"-1"でない時というのは、"1"または"2"の時なので、アラートを出します。
('そのマスは、すでに選択されています!');
まだ選択されていない場合は
else {
var states = JSON.parse(JSON.stringify(this.states))
states[rowsIndex][colsIndex] = this.playerId;
this.states = states;
this.playerId = (this.playerId == 1) ? 2 : 1;
}
この部分は少しややこしいですね。
ここが重要なのですが、Vueの配列を更新するためには変数自体を書き換える必要があります。つまり、この場合だと
this.states[rowsIndex][colsIndex] = this.playerId;
としても、バインディングされた部分は新しく書き換えられることはありません。
そのため、少しまわりくどいですが、まず元々のデータを一旦JSONにして再度元に戻すことで配列をコピー。そして、選択されたマス目のデータを更新し、最後にthis.states全体を書き換えるという方法をとっています。(お好みでVue.set()を使ってもいいでしょう)
また、選択が済んだあとは、プレイヤーを交代させるためにplayerIdを変更するようにしています。
このコードでプレイヤーの入れ替えをします。
ここまででマス目を選んで○×が入るようになりました。
この記事が気に入ったらサポートをしてみませんか?