Vue комбинационная игра переворачивает все матчи на один клик

Vue комбинационная игра переворачивает все матчи на один клик

19.10.2019 11:51:25 Просмотров 58 Источник

Я учусь Ву.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

tony19

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>

https://stackoverflow.com/questions/58467887/vue-matching-game-turns-over-all-matches-on-single-click/58468408#comment103282937_58468408
Спасибо большое, это сработало отлично. Мне все еще немного сложно обернуть голову вокруг этого, и я уже несколько лет программирую на PHP и использую немного JavaScript.
Закрыть X