Vue комбинационная игра переворачивает все матчи на один клик
Я учусь Ву.js и я строим простую маленькую карточную комбинационную игру на тему Марио для практики. Игра создает массив из 18 случайно перетасованных карт, и игрок должен нажать на карты, чтобы перевернуть их и попытаться получить матч. Проблема в том, что когда карта нажата, она и все ее совпадения также переворачиваются. Но я хочу только карту, которая была нажата, чтобы перевернуть.
Вот элемент, к которому привязано мое приложение Vue:
<div class="container" id="matchGame">
<div class="col-6 mx-auto bg-dark" style="margin-top:230px;">
<h3 class="text-light text-center pt-3">Mario Bros Matching Game</h>
<button v-on:click="start" v-show="!started" class="btn btn-lg btn-success mb-2">Start</button>
<ul v-if="started" class="d-flex flex-sm-wrap justify-content-between mt-5 pb-5">
<li class="mb-3 ml-2" v-for="(card, index) in cards" v-on:click="flipCard(card)">
<transition name="flip">
<span v-on:click="flipCard(index)" v-if="!card.flipped"><img class="card" v-bind:src="cards[index].front" /></span>
<span v-on:click="flipCard(index)" v-else><img class="card" v-bind:src="cards[index].back" /></span>
</transition>
</li>
</ul>
<button v-on:click="stop" v-show="started" class="btn btn-danger mb-3">Stop</button>
</div>
</div>
И вот мой JavaScript:
// This is all the data for each card
const items = [
{
front: 'images/cardfront.png',
back: 'images/coin10.png',
name: 'coin10',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/coin20.png',
name: 'coin20',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/flower.png',
name: 'flower',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/mushroom.png',
name: 'mushroom',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/oneup.png',
name: 'oneup',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/star.png',
name: 'star',
flipped: false
}
];
// This is a function to create an array of 18 randomly shuffled cards
// Previously I had a function like it in the methods section of the Vue app but I changed
// it while trying to solve the issue
function createGameCardsArray() {
const cards = [];
for (let i = 0; i <= 17; i++) {
cards[i] = items[Math.floor(Math.random() * 6)];
}
return cards;
}
// Vue app
const app = new Vue({
el: '#matchGame',
data: {
// This holds the array of randomly shuffled cards
cards: createGameCardsArray(),
gameSounds: audio,
started: false
},
methods: {
// When this method is called, all matches are flipped
flipCard: function(card) {
card.flipped = !card.flipped;
},
start: function() {
// this.shuffle();
console.log(this.cards);
this.started = true;
this.gameSounds.background.play();
this.gameSounds.background.loop = true;
},
stop: function() {
this.started = false;
this.gameSounds.background.pause();
this.gameSounds.background.currentTime = 0
this.gameSounds.background.loop = false;
},
// shuffle: function() {
// const shuffledCards = [];
// for (let i = 0; i <= 17; i++) {
// shuffledCards.push(gameCards[Math.floor(Math.random() * 6)]);
// }
// this.cards = shuffledCards;
// }
}
});
Это невероятно неприятная проблема, так как с моей точки зрения карты должны быть перевернуты на основе их уникального индекса в массиве, но это явно не то, что происходит. Вместо этого все карты, которые соответствуют переворачиваются, и я не могу прогрессировать в создании этой игры с этой проблемой. Любая помощь в выявлении и устранении источника проблемы будет чрезвычайно оценена!!
Ответы - Vue комбинационная игра переворачивает все матчи на один клик / Vue matching game turns over all matches on single click

20.10.2019 01:06:23
createGameCardsArray
создает массив ссылок на один и тот же экземпляр items[random index]
, поэтому редактирование карты из одной ссылки будет отражать изменение всех ссылок на одну и ту же карту. Решение состоит в том, чтобы клонировать каждую карту с оператором распространения (или Object.assign
):
function createGameCardsArray() {
const cards = [];
for (let i = 0; i <= 17; i++) {
cards[i] = { ...items[Math.floor(Math.random() * 6)] };
}
return cards;
}
// This is all the data for each card
const items = [
{
front: 'images/cardfront.png',
back: 'images/coin10.png',
name: 'coin10',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/coin20.png',
name: 'coin20',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/flower.png',
name: 'flower',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/mushroom.png',
name: 'mushroom',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/oneup.png',
name: 'oneup',
flipped: false
},
{
front: 'images/cardfront.png',
back: 'images/star.png',
name: 'star',
flipped: false
}
];
// This is a function to create an array of 18 randomly shuffled cards
function createGameCardsArray() {
const cards = [];
for (let i = 0; i <= 17; i++) {
cards[i] = { ...items[Math.floor(Math.random() * 6)] };
}
return cards;
}
new Vue({
el: '#app',
data: {
// This holds the array of randomly shuffled cards
cards: createGameCardsArray(),
// gameSounds: audio,
started: false
},
methods: {
// When this method is called, all matches are flipped
flipCard: function(card) {
card.flipped = !card.flipped;
},
start: function() {
console.log(this.cards);
this.started = true;
//this.gameSounds.background.play();
//this.gameSounds.background.loop = true;
},
stop: function() {
this.started = false;
this.gameSounds.background.pause();
this.gameSounds.background.currentTime = 0
this.gameSounds.background.loop = false;
}
}
})
<script src="https://unpkg.com/vue@2.6.10/dist/vue.min.js"></script>
<div id="app">
<div class="container" id="matchGame">
<div class="col-6 mx-auto bg-dark" style="margin-top:230px;">
<h3 class="text-light text-center pt-3">Mario Bros Matching Game</h>
<button v-on:click="start" v-show="!started" class="btn btn-lg btn-success mb-2">Start</button>
<ul v-if="started" class="d-flex flex-sm-wrap justify-content-between mt-5 pb-5">
<li class="mb-3 ml-2" v-for="(card, index) in cards" v-on:click="flipCard(card)">
<transition name="flip">
<span v-on:click="flipCard(index)" v-if="!card.flipped">FRONT: {{ card.front }}</span>
<span v-on:click="flipCard(index)" v-else>BACK: {{ card.back }}</span>
</transition>
</li>
</ul>
<button v-on:click="stop" v-show="started" class="btn btn-danger mb-3">Stop</button>
</div>
</div>
</div>
