LoginSignup
3
5

More than 3 years have passed since last update.

Vue.jsとDjango-Rest-Frameworkで神経衰弱アプリを作ってみる【その3】~神経衰弱の実装編~

Last updated at Posted at 2020-01-26

<< その2 | その4 >>

トランプの画像を用意する。

スクレイピングで「いらすとや」からトランプの画像を取得

ここ参照
なんのこっちゃって人は手作業で54枚ダウンロードするか、vueでコーディングするなりしてください。

トランプ52枚を表示してみる。(Joker抜き)

PlayScreen.vue
<template>
  <div>
    <span v-for="(card, index) in cards" :key="index">
      <img
        v-bind:src="card"
        alt=""
        width="110"
        height="135"
      />
    </span>
  </div>
</template>

<script>
export default {
  name: 'TopPage',
  data: function () {
    return {
      cards: [],
    }
  },
  methods: {
    setCardImage: function(type) {
      for (let i = 1; i < 14; i++) {
        let number = ('00' + i).slice(-2)
        this.cards.push(require('@/assets/images/card_' + type + '_' + number + '.png'))
      }
    }
  },
  mounted () {
    this.setCardImage('club');
    this.setCardImage('diamond');
    this.setCardImage('heart');
    this.setCardImage('spade');
  }
}
</script>

image.png

トランプをシャッフルする

PlayScreen.vue
<template>
  ...
  ..
  .
</template>

<script>
export default {
  ...
  ..
  .
  methods: {
    // 追加
    shuffle: function () {
      for (let i = this.cards.length - 1; i > 0; i--){
        let r = Math.floor(Math.random() * (i + 1));
        let tmp = this.cards[i];
        this.cards[i] = this.cards[r];
        this.cards[r] = tmp;
      }
    },
    ...
    ..
    .
  },
  mounted () {
    this.setCardImage('club');
    this.setCardImage('diamond');
    this.setCardImage('heart');
    this.setCardImage('spade');
    this.shuffle(); // 追加
  }
}
</script>

シャッフルされるようになりました。
image.png

カードに表裏のオプションを追加する

PlayScreen.vue
<template>
  <div>
    <span v-for="(card, index) in cards" :key="index">
      <!-- スタイルバインディングで画像のURLを設定する -->
      <img
        v-bind:src="card.isOpen ? card.cardInfo.front : card.cardInfo.back"
        alt=""
        width="110"
        height="135"
      />
    </span>
  </div>
</template>

<script>
export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    // このメソッドを編集
    setCardImage: function(type) {
      for (let i = 1; i < 14; i++) {
        let number = ("00" + i).slice(-2);
        let card = {
          isOpen: false, // 初期状態は裏で表示されるようにする。
          cardInfo: {
            number: i,
            front: require(`@/assets/images/card_${type}_${number}.png`), // 表
            back: require("@/assets/images/card_back.png") // 裏
          }
        };
        this.cards.push(card);
      }
    }
  },
  mounted () {
    ...
    ..
    .
  }
}
</script>

image.png

画像クリックでカードを表表示にできるようにする。

PlayScreen.vue
<template>
  <div>
    <span v-for="(card, index) in cards" :key="index">
      <!-- clickイベントを付与し、追加したメソッドを設定する -->
      <img
        v-bind:src="card.isOpen ? card.cardInfo.front : card.cardInfo.back"
        alt=""
        width="110"
        height="135"
        @click="open(index)"
      />
    </span>
  </div>
</template>

<script>
export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    // このメソッドを追加
    open: function(index) {
      // カードを表向きにする
      this.cards[index].isOpen = true;
    }
  },
  mounted () {
    ...
    ..
    .
  }
}
</script>

image.png

神経衰弱を実装していく

2枚めくったらカードが全て裏向きに戻るようにする

PlayScreen.vue
<template>
  ...
  ..
  .
</template>

<script>
let openCountByPlayer = 0; // プレイヤーが何枚めくったか

export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    // このメソッドを編集する
    open: function(index) {
      // 2枚以上はめくれないようにする
      if (openCountByPlayer + 1 > 2) return;

      // カードを表向きにする
      this.cards[index].isOpen = true;

      openCountByPlayer++;

      if (openCountByPlayer == 2) {
        // 2枚めくったらカードが裏向きになるようにする
        this.reset();
      }
    },
    // このメソッドを追加
    reset: function() {
      setTimeout(() => {
        this.cards.forEach((card, index) => {
          if (card.isOpen) {
            this.cards[index].isOpen = false;
          }
        });
        openCountByPlayer = 0;
      }, 2000);
    },
  },
  ...
  ..
  .
}
</script>

めくった2枚の数字が一致している場合は表向きになったままにする

PlayScreen.vue
<template>
  <div>
    <span v-for="(card, index) in cards" :key="index">
      <!-- 既に取得されたカード(isGet != null)は表向き表示になるようにする。 -->
      <img
        v-bind:src="(card.isOpen || card.isGet != null) ? card.cardInfo.front : card.cardInfo.back"
        alt=""
        width="110"
        height="135"
        @click="open(index)"
      />
    </span>
  </div>
</template>

<script>
let openCountByPlayer = 0; // プレイヤーが何枚めくったか
const PLAYER = "player";
const COMPUTER = "computer";

export default {
  ...
  ..
  .
  methods: {
    ...
    ..
    .
    // このメソッドを編集
    setCardImage: function(type) {
      for (let i = 1; i < 14; i++) {
        let number = ("00" + i).slice(-2);
        let card = {
          isOpen: false,
          isGet: null, // isGetプロパティを追加
          cardInfo: {
            number: i,
            front: require(`@/assets/images/card_${type}_${number}.png`),
            back: require("@/assets/images/card_back.png")
          }
        };
        this.cards.push(card);
      }
    },
    // このメソッドを編集する
    open: function(index) {
      // 2枚以上はめくれないようにする
      if (openCountByPlayer + 1 > 2) return;

      // カードを表向きにする
      this.cards[index].isOpen = true;

      openCountByPlayer++;

      if (openCountByPlayer == 2) {
        this.isNumbersMatch();

        // 2枚めくったらカードが裏向きになるようにする
        this.reset();
      }
    },
    // このメソッドを編集
    reset: function() {
      setTimeout(() => {
        // 取得されているカード以外を裏向きに戻す
        this.cards.forEach((card, index) => {
          if (card.isOpen && card.isGet == null) {
            this.cards[index].isOpen = false;
          }
        });
        openCountByPlayer = 0;
      }, 2000);
    },
    isNumbersMatch: function() {
      // 表向きの画像を取得する(既に数字が一致しているカード(isGet != null)は除外)
      let openCards = [];
      this.cards.forEach((card, index) => {
        if (card.isOpen && card.isGet == null) {
          openCards.push({ index, card });
        }
      });

      // 数字が一致している場合は取得
      let firstCard = openCards[0];
      let secondCard = openCards[1];
      if (firstCard.card.cardInfo.number == secondCard.card.cardInfo.number) {
        this.cards[firstCard.index].isGet = PLAYER;
        this.cards[secondCard.index].isGet = PLAYER;
      }
    }
  },
  ...
  ..
  .
}
</script>

獲得した組数を表示する

PlayScreen.vue
<template>
  <div>
    <v-card>
      <!-- 追加した算出プロパティを使用 -->
      <v-row no-gutters>
        <v-col>あなたがゲットした組数:{{ getPlayerPairs }}</v-col>
      </v-row>

      <v-divider class="mb-4"></v-divider>

      ...
      ..
      .
    </v-card>
  </div>
</template>

<script>
let openCountByPlayer = 0; // プレイヤーが何枚めくったか
const PLAYER = "player";
const COMPUTER = "computer";

export default {
  ...
  ..
  .
  // 算出プロパティを追加
  computed: {
    getPlayerPairs: function() {
      if (!this.cards || this.cards.length === 0) return;

      return (
        this.cards.filter(card => { return card.isGet === PLAYER; }).length / 2
      );
    }
  },
  ...
  ..
  .
}
</script>

image.png

<< その2 | その4 >>

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5