The combination of object-oriented and vue

Separation of operations and implementation

Convert functional to object-oriented

Only call methods of objects in the view layer

Then remount to achieve the effect of refreshing the view

Maze

class Maze {
  constructor(size) {
    this.size = size
    this.blank = size * size
    this.items = Array.from(Array(size * size)).map((_, index) => index + 1)
    this.initCnt = 1000
  }

  // 是否完成
  isPass() {
    return this.items.every((item, index) => item == index + 1)
  }

  // 空白块所在位置0....1....
  blankPos() {
    return this.items.indexOf(this.blank)
  }

  // 移动
  move(dir) {
    // console.log(dir)
    if (dir == 0 && this.blankPos() >= this.size) {
      this.swap(this.blankPos(), this.blankPos() - this.size)
    } else if (dir == 1 && this.blankPos() % this.size != (this.size - 1)) {
      this.swap(this.blankPos(), this.blankPos() + 1)
    } else if (dir == 2 && this.blankPos() < (this.size - 1) * this.size) {
      this.swap(this.blankPos(), this.blankPos() + this.size)
    } else if (dir == 3 && this.blankPos() % this.size != 0) {
      this.swap(this.blankPos(), this.blankPos() - 1)
    }
  }

  // 交换
  swap(x, y) {
    // console.log(x, y)
    let t = this.items[x]
    this.items[x] = this.items[y]
    this.items[y] = t
  }

  shuffle() {
    for (let i = 0; i < this.initCnt; i++)
      this.move(
        Math.floor(Math.random() * 1000) % 4
      )
  }

  toString() {
    return this.items.toString()
  }
}

 

Game

<template>
  <div class="main">

    <select v-model="size">
      <option value="3"> 3</option>
      <option value="4">4</option>
      <option value="5">5</option>
    </select>
    <p>选择:{{size}}</p>
    <transition-group name="cells" tag="div" class="game" ref="game">

      <div v-for="i,index in maze.items" class="cell"
           :key="i"
           @click="click(i,index)"
      >
        {{i==size*size?'':i}}
      </div>
    </transition-group>


    <button @click="shuffle">reset</button>
    <button @click="autoplay">autoplay</button>

  </div>

</template>

<script>
  import Maze from './Maze'

  export default {
    name: "game",
    data() {
      return {
        size: 4,
        maze: null
      }
    },
    computed: {
      blank() {

      }
    },
    watch: {
      size: {
        handler: 'init',
      },

    },
    methods: {
      init() {
        console.log('init')
        this.maze = new Maze(this.size)
        this.$refs.game.$el.style.width = this.size * 80 + 'px'
        this.$refs.game.$el.style.height = this.size * 80 + 'px'
        this.$refs.game.$el.style.gridTemplateColumns = `repeat(${this.size},1fr)`
      },
      shuffle() {
        this.maze.shuffle()
        this.$mount()
      },
      autoplay() {

      },
      click(item, index) {
        console.log('click', item, index)
        if (item == 16)
          return
        if (index + 1 < 16 && this.maze.items[index + 1] == 16) {
          // console.log('click move', 3)
          this.maze.move(3)
        } else if (index - 1 >= 0 && this.maze.items[index - 1] == 16) {
          this.maze.move(1)
          // console.log('click move', 1)

        } else if (index + 4 < 16 && this.maze.items[index + 4] == 16) {
          this.maze.move(0)
          // console.log('click move', 0)

        } else if (index - 4 >= 0 && this.maze.items[index - 4] == 16) {
          this.maze.move(2)
          // console.log('click move', 2)
        }

        // this.maze.shuffle()
        this.$mount()
        // console.log(this.$mount())
      }
    },
    created() {
      this.maze = new Maze(this.size)
    },
    mounted() {
      console.log('mounted', this.$refs)

      this.init()
    }
  }
</script>

<style scoped>
  .main {
    width: 100vw;
    height: 100vh;
    display: flex;
    flex-direction: column;
  }

  .game {
    display: grid;
    grid-gap: 5px;
    background: rgb(233, 233, 233);
    border: 5px solid rgb(233, 233, 233);
    grid-template-columns: repeat(4, 1fr);
  }

  .cell {
    display: flex;
    width: 100%;
    height: 100%;
    background: lightskyblue;
    justify-content: center;
    align-items: center;
  }

  .cells-enter-active, .cells-leave-active {
    transition: all 0.5s;
  }

  /*效果*/
  .cells-enter, .cells-leave-to {
    opacity: 0;
    transform: translateY(30px);
  }

  /*过渡时间*/
  .cells-move {
    transition: transform 0.5s;
  }
</style>

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325114193&siteId=291194637