Vue实现翻动卡片小游戏

在这里插入图片描述在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Card Game</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
        integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.15/lodash.min.js"></script>

    <style>
        body {
            background-image: linear-gradient(to bottom right, rgb(114, 135, 254), rgb(130, 88, 186));
            height: 100%;
            width: 100%;
        }
        .flip-container {
            -webkit-perspective: 1000;
            -moz-perspective: 1000;
            -o-perspective: 1000;
            perspective: 1000;
            min-height: 120px;
            cursor: pointer;
        }

        .front,
        .back {
            -webkit-backface-visibility: hidden;
            -moz-backface-visibility: hidden;
            -o-backface-visibility: hidden;
            backface-visibility: hidden;
            -webkit-transition: 0.6s;
            -webkit-transform-style: preserve-3d;
            -moz-transition: 0.6s;
            -moz-transform-style: preserve-3d;
            -o-transition: 0.6s;
            -o-transform-style: preserve-3d;
            -ms-transition: 0.6s;
            -ms-transform-style: preserve-3d;
            transition: 0.6s;
            transform-style: preserve-3d;
            top: 0;
            left: 0;
            width: 100%;
        }

        .back {
            -webkit-transform: rotateY(-180deg);
            -moz-transform: rotateY(-180deg);
            -o-transform: rotateY(-180deg);
            -ms-transform: rotateY(-180deg);
            transform: rotateY(-180deg);
            position: absolute;
        }

        .flip-container.flipped .back {
            -webkit-transform: rotateY(0deg);
            -moz-transform: rotateY(0deg);
            -o-transform: rotateY(0deg);
            -ms-transform: rotateY(0deg);
            transform: rotateY(0deg);
        }

        .flip-container.flipped .front {
            -webkit-transform: rotateY(180deg);
            -moz-transform: rotateY(180deg);
            -o-transform: rotateY(180deg);
            -ms-transform: rotateY(180deg);
            transform: rotateY(180deg);
        }

        .matched {
            opacity: 0;
        }
    </style>
</head>

<body>

    <div id="app">
        <div class="d-flex flex-row justify-content-center py-3">
            <div class="turns p-3"><span class="btn btn-info">翻动次数 : <span class="badge"
                        :class="finish ? 'badge-success' : 'badge-light'">{{turns}}</span> </span></div>
            <div class="totalTime p-3"><span class="btn btn-info">花费时间 : <span class="badge"
                        :class="finish ? 'badge-success' : 'badge-light'">{{min}} : {{sec}}</span></span></div>
            <div class="totalTime p-3"><button class="btn btn-info" @click="reset" :disabled="!start">重置</button></div>
        </div>

        <div class="row">
            <div class="col-md-6 col-lg-6 col-xl-5 mx-auto">
                <div class="row justify-content-md-center">
                    <div v-for="card in memoryCards" class="col-auto mb-3 flip-container"
                        :class="{ 'flipped': card.isFlipped, 'matched' : card.isMatched }" @click="flipCard(card)">
                        <div class="memorycard">
                            <div class="front border rounded shadow"><img width="100" height="150"
                                    src="./011a235e36b104a801216518a0bbab.jpg@1280w_1l_2o_100sh.jpg"></div>
                            <div class="back rounded border" style="width: 100px; height: 150px;">
                                <img width="100" height="150" :src="card.img">
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        let app = new Vue({
            el: '#app',
            data: {
                // 存储相同的卡片
                memoryCards: [],
                // 存储翻动的卡片
                flippedCards: [],
                // 结束
                finish: false,
                // 是否显示
                show: true,
                // 初识卡片
                cards: [
                    {
                        name: 'Apple',
                        img: './apple.jpeg',

                    },
                    {
                        name: 'Banana',
                        img: './banana.jpeg',

                    },
                    {
                        name: 'Orange',
                        img: './orange.jpeg',

                    },
                    {
                        name: 'Pineapple',
                        img: './pineapple.jpeg',

                    },
                    {
                        name: 'Strawberry',
                        img: './strawberry.jpeg',

                    },
                    {
                        name: 'watermelon',
                        img: './watermelon.jpeg',

                    },
                ],
                // 是否开始游戏
                start: false,
                // 记录翻转次数
                turns: 0,
                // 花费时间
                totalTime: {
                    minutes: 0,
                    seconds: 0,
                },
            },
            created() {
                // 在最开始的时候,给卡片的每一个项都加上是否翻动和匹配的属性
                this.cards.forEach((card) => {
                    Vue.set(card, 'isFlipped', false);
                    Vue.set(card, 'isMatched', false);
                });
                // 每次开始游戏打乱数组的顺序
                this.memoryCards = _.shuffle(this.memoryCards.concat(_.cloneDeep(this.cards), _.cloneDeep(this.cards)));
            },

            methods: {
                // 重置游戏
                reset() {
                    // 清除定时器
                    clearInterval(this.interval);

                    this.cards.forEach((card) => {
                        Vue.set(card, 'isFlipped', false);
                        Vue.set(card, 'isMatched', false);
                    });

                    setTimeout(() => {
                        this.memoryCards = [];
                        this.memoryCards = _.shuffle(this.memoryCards.concat(_.cloneDeep(this.cards), _.cloneDeep(this.cards)));
                        this.totalTime.minutes = 0;
                        this.totalTime.seconds = 0;
                        this.start = false;
                        this.finish = false;
                        this.turns = 0;
                        this.flippedCards = [];

                    }, 600);

                },
                // 翻转卡片
                flipCard(card) {

                    // 如果卡片已经匹配,翻转,且翻转的数组中已经有两张,就直接返回
                    if (card.isMatched || card.isFlipped || this.flippedCards.length === 2)
                        return;

                    card.isFlipped = true;

                    // 否则,向数组中添加被点击的卡片
                    if (this.flippedCards.length < 2)
                        this.flippedCards.push(card);
                    if (this.flippedCards.length === 2)
                        // 已经点击两张卡片,则进行两张卡片的相等验证
                        this._match(card);

                    if (!this.start) {
                        this._startGame();
                    }

                },


                // 卡片相等验证
                _match(card) {
                    // 记录翻转次数
                    this.turns++;

                    // 如果两张卡片的 name 属性相等,则认为两张卡片匹配成功
                    if (this.flippedCards[0].name === this.flippedCards[1].name) {
                        setTimeout(() => {
                            // 改变两张卡片的匹配属性
                            this.flippedCards.forEach(card => card.isMatched = true);
                            // 将数组置空
                            this.flippedCards = [];

                            // 隐藏两张匹配的卡片包
                            this.show = false

                            // 判断游戏结束
                            if (this.memoryCards.every(card => card.isMatched === true)) {
                                clearInterval(this.interval);
                                this.finish = true;
                            }
                        }, 400);
                    }
                    else {
                        setTimeout(() => {
                            this.flippedCards.forEach(card => { card.isFlipped = false });
                            this.flippedCards = [];

                        }, 800);
                    }
                },
                // 开始游戏
                _startGame() {
                    this._tick();
                    this.interval = setInterval(this._tick, 1000);
                    this.start = true;
                },
                // 记录游戏
                _tick() {
                    if (this.totalTime.seconds !== 59) {
                        this.totalTime.seconds++;
                        return
                    }

                    this.totalTime.minutes++;
                    this.totalTime.seconds = 0;
                },

            },

            computed: {
                // 设置时间格式
                sec() {
                    if (this.totalTime.seconds < 10) {
                        return '0' + this.totalTime.seconds;
                    }
                    return this.totalTime.seconds;
                },
                min() {
                    if (this.totalTime.minutes < 10) {
                        return '0' + this.totalTime.minutes;
                    }
                    return this.totalTime.minutes;
                }
            }
        });

    </script>
</body>

</html>

关注公众号:大明贵妇,无套路获取前端学习资料,期待各位客官来临
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值