院卒新人サラリーマンのメモ代わり

備忘としてのメモを記載

vue.jsでオセロ

<template lang="pug">
.osero
    #app
        p 白:{{ w_point }}, 黒:{{ b_point }}
        p {{turn}}の手番
        .container(v-for="(i,idx) in 8" :key='idx')
            .waku(v-for="(j,idx2) in 8" :key='idx2')
                div(:class="{ 'white': cell[i][j]==true, 'black': cell[i][j]==false }" @click="oku(i, j)")
        p: button(@click="pass") pass
</template>


<script>
const [WHITE, BLACK, EMPTY, WALL] = [true, false, 2, 3];
export default {
  data() {
    return {
      turnPlayer: BLACK,
      cell: [
        [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 2, 2, 2, WHITE, BLACK, 2, 2, 2, 3],
        [3, 2, 2, 2, BLACK, WHITE, 2, 2, 2, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 2, 2, 2, 2, 2, 2, 2, 2, 3],
        [3, 3, 3, 3, 3, 3, 3, 3, 3, 3]
      ]
    };
  },
  computed: {
    w_point() {
      return (this.cell.join("").match(/true/g) || []).length;
    },
    b_point() {
      return (this.cell.join("").match(/false/g) || []).length;
    },
    turn() {
      return this.turnPlayer == BLACK ? "黒" : "白";
    }
  },
  methods: {
    oku(x, y) {
      if (this.cell[x][y] != EMPTY) return;
      if (this.isEnablePut(x, y) == false) return;
      this.cell[x].splice(y, 1, this.turnPlayer);
      this.changeTurn();
    },
    pass() {
      this.changeTurn();
    },
    changeTurn() {
      this.turnPlayer = !this.turnPlayer;
    },
    isEnablePut(x, y) {
      const AROUND = [
        { x: -1, y: -1 },
        { x: -1, y: 0 },
        { x: -1, y: 1 },
        { x: 0, y: -1 },
        { x: 0, y: 1 },
        { x: 1, y: -1 },
        { x: 1, y: 0 },
        { x: 1, y: 1 }
      ];
      return AROUND.some(ar => {
        //dtマス離れたところを調べる
        for (let dt = 1; ; dt++) {
          let [dx, dy] = [x + dt * ar.x, y + dt * ar.y];
          switch (this.cell[dx][dy]) {
            case EMPTY: //石が置かれてない
            case WALL: //番外
              return false;
            case !this.turnPlayer: //違う色の石があったらもう1マス先を調べる
              continue;

            case this.turnPlayer: //同じ色の石があったら間を調べる
              if (dt == 1) return false;
              for (let dd = 1; dd <= dt; dd++) {
                let [dx2, dy2] = [x + dd * ar.x, y + dd * ar.y];
                this.cell[dx2].splice(dy2, 1, this.turnPlayer);
              }
              return true;
          }
        }
      });
    }
  }
};
</script>


<style lang="scss" scoped>
p {
  text-align: center;
}
div {
  min-width: 35px;
  min-height: 35px;
}
.container {
  display: flex;
  justify-content: center;
}
.waku {
  border: 1px solid black;
  background-color: green;
}
.white {
  border-radius: 35px;
  background-color: white;
}
.black {
  border-radius: 35px;
  background-color: black;
}
</style>

参考
vue.jsでcsvファイルのデータ抽出表示とオセロ - Qiita