vue制作3*3拼图

546 阅读4分钟

自从上次发布了vue制作抓娃娃机经验之后,好多朋友来私信我让我多分享一些小游戏的经验。(看来友友们对这种小游戏还是挺感兴趣哦~捂脸笑~) 好了,回归正题。今天给大家带来一个比较简单的小游戏——拼图。想必大家平时或多或少都玩过拼图游戏吧,我记得小时候经常偷偷用我爸爸的手机玩上面的拼图小游戏,简单的有2×2,3×3甚至有4×4、5×5等等复杂的难关。作为玩者我们是在研究如何过关,而对于我们程序猿来说,我们是不是应该研究研究这些游戏怎么做出来的呢。今天它来啦~~ 老样子,先看效果图。

gif1.gif
首先介绍规则:3×3的方格中,有一处是空白,点击空白周围的卡片,使其移动,直至拼成最终效果图(页面下方有成品图,这里录gif的时候没带上)。 第一步,上样式:

      <div class="game">
        <ul class="puzzle-wrap">
          <li
            v-for="(puzzle, index) in puzzles"
            :key="puzzle.id"
            :class="{'puzzle': true, 'puzzle-empty': !puzzle}"
            @click="move(puzzle,index)"
          >
            <img :src="puzzle.url" alt="error" width="100%" height="100%" />
          </li>
        </ul>
      </div>
.game {
      width: 560px;
      height: 560px;
      margin-top: 30px;
      background-image: url("./../assets/img/bgsmall.png");
      background-size: 100%;
      .puzzle-wrap {
        background-image: url("./../assets/img/dot1.png");
        width: 560px;
        height: 560px;
        overflow: hidden;
        background-size: 100%;
        list-style: none;
        padding: 19px 20px 0 21px;
        border-radius: 40px;
        animation: puzzle-wrap infinite 0.6s;
        .puzzle {
          float: left;
          width: 173px;
          height: 173px;
          font-size: 20px;
          background: #f90;
          text-align: center;
          line-height: 100px;
          border: 1px solid #ccc;
          box-shadow: 1px 1px 4px;
          text-shadow: 1px 1px 1px #b9b4b4;
          cursor: pointer;
          img {
            height: 100%;
            width: 100%;
          }
          &.puzzle-empty {
            background: #ccc;
            box-shadow: inset 2px 2px 18px;
          }
        }
      }
      @keyframes puzzle-wrap {    // 此动画是用来装饰游戏边框的动画(可忽略)
        form {
          background-image: url("./../assets/img/dot1.png");
        }
        to {
          background-image: url("./../assets/img/dot2.png");
        }
      }
    }

样式没什么问题,咱来看如何实现点击拼图。 首先准备好卡片资源,并随机设置生成卡片序列

data() {
    return {
        puzzles: [    // 可以在data中向这样引入,也可单独写个js文件来引入,看自己习惯。(其中有一张空白图片,并将其多设置一个参数,如:empty。用来后面判断是否拼图成功)
        {
          id: 0,
          url: require("./../assets/img/pintu/pintu_01.png")
        },
        {
          id: 1,
          url: require("./../assets/img/pintu/pintu_02.png")
        },
        {
          id: 2,
          url: require("./../assets/img/pintu/pintu_03.png")
        },
        {
          id: 3,
          url: require("./../assets/img/pintu/pintu_04.png")
        },
        {
          id: 4,
          url: require("./../assets/img/pintu/pintu_05.png")
        },
        {
          id: 5,
          url: require("./../assets/img/pintu/pintu_06.png")
        },
        {
          id: 6,
          url: require("./../assets/img/pintu/pintu_07.png")
        },
        {
          id: 7,
          url: require("./../assets/img/pintu/pintu_08.png")
        },
        {
          empty: true,
          id: 8,
          url: require("./../assets/img/pintu/pintu_09.jpg")
        }
      ],
    };
 },
mounted() {
    this.randomRender();
  },
methods: {
 // 随机生成方块序列
    randomRender() {
      let puzzles = this.puzzles,
        results = [];                     // 用拿到的卡片数据随机排序生成新的数组赋值,
      results = puzzles.sort(() => {
        return Math.random() > 0.5 ? -1 : 1;
      });
      this.puzzles = results;
    },
}

这样卡片的随机排序就生成好了,在页面初始mouted去调用以及拼图成功或失败之后再次调用来初始数据。 接下来就是点击卡片让其移动并判断是否达到最终效果图。

// 点击方块
    move(puzzle, index) {
        let puzzles = this.puzzles;
        // 获取点击位置及其上下左右的值
        let curNum = puzzles[index],
          leftNum = puzzles[index - 1],
          rightNum = puzzles[index + 1],
          topNum = puzzles[index - 3],
          bottomNum = puzzles[index + 3];

        let emptyObj = {
          empty: true,
          id: 8,
          url: require("./../assets/img/pintu/pintu_09.jpg")
        };

        // 和为空的位置交换数值
        if (leftNum && leftNum.empty && index % 3) {
          this.$set(puzzles, index - 1, curNum);
          this.$set(puzzles, index, emptyObj);
        } else if (rightNum && rightNum.empty && 2 !== index % 3) {
          this.$set(puzzles, index + 1, curNum);
          this.$set(puzzles, index, emptyObj);
        } else if (topNum && topNum.empty) {
          this.$set(puzzles, index - 3, curNum);
          this.$set(puzzles, index, emptyObj);
        } else if (bottomNum && bottomNum.empty) {
          this.$set(puzzles, index + 3, curNum);
          this.$set(puzzles, index, emptyObj);
        }
        this.$nextTick(() => {
          this.passChecked();
        });
    },
  passChecked() {
      const puzzles = this.puzzles;
      if (puzzles[8]["empty"]) {
        const isPass = puzzles.every((x, y) => x.id === y);  该方法的用法
        if (isPass) {
            console.log('成功啦~~');
          // return true;
        }
      }
      return false;
    },

当每次点击卡片时,获取该卡片的位置以及其上下左右四张卡片的值。然后定义空卡片的值,判断空卡片在点击卡片的方位,然后进行交换数值替换位置。 接下来用刚开始定义空卡片的empty值去判断当前数组的最后一张卡片该值是否存在,若存在再使用every()依次去判断当前数组每个数据的id是否等于对应的索引值。若返回为true则证明拼图成功。

这样再看游戏是不是觉得很简单呢,玩着自己制作的小游戏是不是有点小成就感呢~~ 有不懂的或者我的讲解哪里存在问题的可以在下方评论交流哦O(∩_∩)O

进来的朋友点点赞点点关注哦~以后会分享更多的小游戏制作经验哦 (●ˇ∀ˇ●)

您的点赞和关注,是我创作的动力之源哦(●'◡'●)