##はじめに
本日は12月4日❗️
チノちゃん誕生日おめでとう👏😸🎊
##本題
オセロ盤はビットボードというデータ構造で実装するのが良いらしい⚪️⚫️✨
Vue.jsで石を並べるところまでやるぞ❗️😺
※この記事では、ビットボードの難しい説明を省略します😿
ビットボードで石を返す処理はサーバー側で行い、その結果の石情報が渡ってくるところからやります✊😸❗️
あらかじめ仕込んでおく3分クッキングスタイルですね😽🍳✨
早速実装
残念ながらJavaScriptの数値は32bitなので、1つの変数で64マス表すことができません❗️😾
ゆるせねぇ...
というわけで、サーバー側で1次元配列に変換してフロント側に渡ってくるってことにしました✊😸❗️
最初に思い付いたやつ
<template>
<div class="board">
<div v-for="i in 8" class="row">
<div v-for="j in 8" class="cell">
<div v-if="blackStones[i * 8 + j]" class="stone black"></div>
<div v-else-if="whiteStones[i * 8 + j]" class="stone white"></div>
</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
blackStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
],
whiteStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
]
}
}
}
</script>
二重ループで回して 1
が立ってたらそれぞれの石の要素を追加する感じ
しかしここで問題が…
v-for="i in 8"
のindexが1始まりなのです😿
[i * 8 + j]
を [(i -1) * 8 + j - 1]
と書かなければならないのでわかりづらい❗️😾
改良
<template>
<div class="board">
<div v-for="i in Array(boardSize).keys()" class="row">
<div v-for="j in Array(boardSize).keys()" class="cell">
<div v-if="blackStones[i * boardSize + j]" class="stone black"></div>
<div v-else-if="whiteStones[i * boardSize + j]" class="stone white"></div>
</div>
</div>
</div>
</template>
<script>
export default {
data: function() {
return {
boardSize: 8,
blackStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
],
whiteStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
]
}
}
}
</script>
いろんな方法がありそうだけど、一番短そうな Array(8).keys()
で動いたのでこれでいいや❗️😸
完成版
<template>
<div class="board">
<div class="logo rot">Othello</div>
<div class="board-main">
<div v-for="i in Array(boardSize).keys()" class="row">
<div v-for="j in Array(boardSize).keys()" class="cell">
<div v-if="blackStones[i * boardSize + j]" class="stone black"></div>
<div v-else-if="whiteStones[i * boardSize + j]" class="stone white"></div>
</div>
</div>
</div>
<div class="logo">Othello</div>
</div>
</template>
<script>
export default {
data: function () {
return {
boardSize: 8,
blackStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
],
whiteStones: [
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
]
}
}
}
</script>
<style lang="scss" scoped>
.board-frame {
display: flex;
flex-direction: column;
justify-content: space-around;
margin: auto;
width: 430px;
height: 470px;
background: #333;
border-top: 3px solid rgba(255, 255, 255, 0.2);
border-right: 5px solid rgba(0, 0, 0, 0.2);
border-bottom: 5px solid rgba(0, 0, 0, 0.2);
border-left: 3px solid rgba(255, 255, 255, 0.2);
border-radius: 8px;
.logo {
color: gold;
text-align: center;
}
.rot {
transform: scale(-1,-1);
}
.board {
display: flex;
flex-direction: column;
margin: auto;
width: 408px;
height: 408px;
background: darkgreen;
border-left: 1px solid #000;
border-top: 1px solid #000;
.row {
display: flex;
}
.cell {
display: flex;
justify-content: center;
align-items: center;
border-bottom: 1px solid #000;
border-right: 1px solid #000;
width: 50px;
height: 50px;
.stone {
border-radius: 50%;
width: 85%;
height: 85%;
}
.black {
background: #333;
}
.white {
background: #eee;
}
}
}
}
</style>
あとは、なんらかのイベントと紐付けて、 blackStones
whiteStones
の値が変わったら盤面を差分レンダリングする感じですね❗️😸
おしまい😽
※気が向いたらPHP版のビットボード実装の記事書きます