【JavaScript】ひたすらサザエとじゃんけんできるの作った

プログラミング初心者の勉強ブログ #117

G’sのじゃんけんアルゴリズムの課題として、ひたすらサザエとじゃんけんできるの作ったので紹介する。特に実用性はない。

 

目次

[toc]

 

sazae janken

sazae_janken_thumbnail

sazae janken

 

概要

特に実用性はない。動画をJSで操作してあーだこーだしている。PCでしか上手いこといかなかった。

クリックすると動画が再生され、

 

sazae_janken_2

 

サザエが手を繰り出す直前で動画が停止。こっちも自分の手を選ぶ。

 

szae_janken_3

 

自分の手を選ぶと再び動画が再生され、決着がつく。僕の実力不足でサザエが早着替えしてしまう。

 

sazae_janken_4

 

勝つと左上に連勝数を表示する。負けるとリセットされる。

 

sazae_janken_5

 

イカサマプロパティをいじることでサザエの手を内部で操作できるので、上のようにひたすら連勝できる。

 

コード

sazae_janken.js

class sazaeJanken {
  constructor() {
    const userAgrent = this.checkUserAent();
    this.body = document.getElementById('sazaeJanken');
    this.rootPath = 'https://gslab0707.bob-pop.com/sazae_janken';
    this._ikasama = null;
    
    if (userAgrent === true) {
      this.setPreloader();
      this.setParams(); 
      this.setId();
      this.setVideo();
      this.createImg();
    } else {
      this.body.innerHTML = userAgrent;
      this.body.style.textAlign = 'center';
    }
  }

  get ikasama() {
    return this._ikasama;
  }

  set ikasama(params) {
    if (params === 'gu') {
      this._ikasama = 0;
    } else if (params === 'cho') {
      this._ikasama = 1;
    } else if (params === 'par') {
      this._ikasama = 2;
    }
  }

  checkUserAent() {
    const ua = navigator.userAgent;
    if (ua.indexOf('iPhone') > 0 || ua.indexOf('Android') > 0 && ua.indexOf('Mobile') > 0) {
      return 'このデバイスでは対応しておりません。';  
    } else if (ua.indexOf('iPad') > 0 || ua.indexOf('Android') > 0) {
      return 'このデバイスでは対応しておりません。';
    } else {
      return true;
    }
  }

  setPreloader() {
    this.createPreloader();
    this.createPreloaderEvent();
    this.body.appendChild(this.preloaderBg);
  }

  createPreloader() {
    const loaderGif = document.createElement('img');
    this.preloaderBg = document.createElement('div');
    this.preloader = document.createElement('div');
    this.preloader.setAttribute('id', 'preloader');
    this.preloaderBg.setAttribute('id', 'preloaderBg');
    loaderGif.src = `${this.rootPath}/img/preloader.gif`;
    loaderGif.alt = 'preloader';
    this.preloader.appendChild(loaderGif);
    this.preloaderBg.appendChild(this.preloader);
  }

  createPreloaderEvent() {
    window.addEventListener('load', () => {
      this.preloaderBg.className = 'fadeOut';
      this.preloader.className = 'fadeOut';
      setTimeout(() => {
        this.preloaderBg.remove();
      }, 800);
    });
  }

  setParams() {
    this.hands = {
      0: 'gu',
      1: 'cho',
      2: 'par'
    };
    this.results = {
      0: 'あいこ',
      1: 'まけ',
      2: 'かち'
    };
    this.videoSrc = `${this.rootPath}/mov/sazae_janken.mp4`;
    this.titleTxt = 'サザエと<br>じゃんけん';
    this.strageCountName = 'winCount';
    this.timerSec = 4300;
  }

  setId() {
    this.titleId = 'title';
    this.videoId = 'video';
    this.videoContainerId = 'videoContainer';
    this.videoImgId = 'videoImg';
    this.counterId = 'counter';
    this.btnWrapId = 'btnWrap';
    this.guBtnId = 'guBtn';
    this.choBtnId = 'choBtn';
    this.parBtnId = 'parBtn';
    this.judgmentId = 'judgment';
  }

  setVideo() {
    this.createVideo();
    this.body.appendChild(this.videoContainer);
    if (sessionStorage.winCount) {
      this.setCounter();
      this.body.appendChild(this.counter);
    }
  }

  createVideo() {
    const container = document.createElement('div');
    this.title = document.createElement('div');
    this.video = document.createElement('video');
    this.video.setAttribute('id', this.videoId);
    this.video.src = this.videoSrc;
    this.title.setAttribute('id', this.titleId);
    this.title.innerHTML = this.titleTxt;
    container.setAttribute('id', this.videoContainerId);
    container.appendChild(this.video);
    container.appendChild(this.title);
    this.videoContainer = container;
    window.addEventListener('load', () => {
      this.setVideoEvent(this.video);
    });
  }

  setVideoEvent(element) {
    let timerId;
    element.addEventListener('click', () => {
      clearTimeout(timerId);
      if (this.imgArray) {
        this.imgArray.forEach(img => {
          img.style.display = 'none';
        });
      }
      if (this.judgment) {
        this.judgment.remove();
      }
      this.video.currentTime = 0;
      this.video.play();
      timerId = setTimeout(() => {
        this.video.pause();
        this.setBtn();
      }, this.timerSec);
    });
  }

  setCounter() {
    this.counter = document.createElement('div');
    this.counter.setAttribute('id', this.counterId);
    this.counter.innerHTML = sessionStorage.winCount;
  }

  setBtn() {
    if (!this.btnWrap) {
      this.createBtn();
      this.btnArray.forEach(btn => {
        this.btnWrap.appendChild(btn);
      });
    }
    this.body.appendChild(this.btnWrap);
  }

  createBtn() {
    const wrap = document.createElement('div');
    const gu = document.createElement('div');
    const cho = document.createElement('div');
    const par = document.createElement('div');
    wrap.setAttribute('id', this.btnWrapId);
    gu.setAttribute('id', this.guBtnId);
    cho.setAttribute('id', this.choBtnId);
    par.setAttribute('id', this.parBtnId);
    gu.setAttribute('value', Object.keys(this.hands)[0]);
    cho.setAttribute('value', Object.keys(this.hands)[1]);
    par.setAttribute('value', Object.keys(this.hands)[2]);
    gu.innerHTML = this.hands[0];
    cho.innerHTML = this.hands[1];
    par.innerHTML = this.hands[2];
    this.btnWrap = wrap;
    this.btnArray = [gu, cho, par];
    this.setBtnEvent();
  }

  setBtnEvent() {
    this.btnArray.forEach(btn => {
      btn.addEventListener('click', (e) => {
        const userHands = Number(e.target.attributes.value.value);
        const pcHands = this.setPcHands();
        const result = this.battle(userHands, pcHands);
        this.btnWrap.remove();
        this.video.play();
        this.renderPcHands(pcHands);
        this.renderResult(result);
      });
    });
  }

  setPcHands() {
    if (this.ikasama != null) {
      return this._ikasama;
    } else {
      return Math.floor(Math.random() * 3);
    }
  }

  battle(userHands, pcHands) {
    const num = (userHands - pcHands + 3) % 3;
    if (num === 2) {
      this.winCount();
      if (this.counter) {
        this.counter.remove();
      }
      this.setCounter();
      this.body.appendChild(this.counter);
    } else if (num === 1 && this.counter) {
      this.resetCount();
      this.counter.remove();
    }
    return this.results[num];
  }

  winCount() {
    if (sessionStorage.winCount) {
      sessionStorage.winCount = Number(sessionStorage.winCount) + 1;
    } else {
      sessionStorage.setItem(this.strageCountName, 1);
    }
  }

  resetCount() {
    sessionStorage.removeItem(this.strageCountName);
  }

  createImg() {
    const guImg = document.createElement('img');
    const choImg = document.createElement('img');
    const parImg = document.createElement('img');
    this.imgArray = [guImg, choImg, parImg];
    this.imgArray.forEach((img, index) => {
      img.src = `${this.rootPath}/img/${this.hands[index]}.png`;
      img.alt = `${this.hands[index]}_img`;
      img.setAttribute('id', this.videoImgId);
      this.setVideoEvent(img);
    });
  }
  
  renderPcHands(pcHands) {
    this.videoContainer.appendChild(this.imgArray[pcHands]);
    this.imgArray[pcHands].style.display = 'block';
  }
  
  renderResult(result) {
    this.judgment = document.createElement('div');
    this.judgment.setAttribute('id', this.judgmentId);
    this.judgment.innerHTML = result;
    this.body.appendChild(this.judgment);
  };
};

 

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <link rel="stylesheet" href="https://gslab0707.bob-pop.com/sazae_janken/css/sazaeJanken.css">
    <title>sazae janken</title>
  </head>
<body>
  <div id="sazaeJanken"></div>
  <script src="https://gslab0707.bob-pop.com/sazae_janken/js/sazaeJanken.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const trigger = new sazaeJanken();

      // ここでイカサマプロパティを変更可能
      trigger.ikasama = 'par';
    });
  </script>
</body>
</html>

 

CDN的な使い方もできる

僕の使ってるVPSは別に高速なものではないのでなんとも言えないが、とりあえずjQueryとかGooglefontsのようなCDN的な感じでlinkタグとscriptタグを読み込めば誰でも使えるようにした。と言ってもサーバーに置いたcssとjsのファイルまでのパスを書いてもらうだけ。HTMLをjsである程度書いたのと、ディレクトリのパスだけ少し気にした。

Git Hub – sazae janken

それっぽくGitHubに載せた。

 

まとめ

ジーズの雰囲気もあり、今までとは毛色が違う物を作ることとなった。いかにヘンだけど凝ったもの作るかみたいな風潮がある。他の同期のみなさんがどんなもの作ったかまだ知らないが、やばいもん作ってくる人も出てくるんだろうなと思う。

以上ありがとうございました。

返信を残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA