<!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>
关注公众号:大明贵妇,无套路获取前端学习资料,期待各位客官来临