1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MarkdownAIを使って神経衰弱を作成しました!

Last updated at Posted at 2025-02-12

MarkdownAIを使って、子供も大人も楽しめる神経衰弱を作りました!

こちらが作成したゲームになります。

:black_medium_square: ポイント

  • 「AIデザインランダム」 を選択すると、ランダムなトランプ画像が設定されます!
  • 「AIデザイン指定あり」 を選択すると、入力した内容に基づいたトランプ画像が設定されます。
  • 「AIデザイン指定なし」 を選択すると、画像生成を行わず、デフォルトの画像でゲームが開始されます。画像生成には数秒かかるため、すぐにゲームを始めたい方におすすめです!
  • レベル設定は、下記のようにトランプの枚数が増える設定になります。

  ・ レベル1:6×2 = 12枚
  ・ レベル2:12×2 = 24枚
  ・ レベル3:18×2 = 36枚
  ・ レベル4:24×2 = 48枚

Image Script

           ↓

Image Script

作成方法の解説

Create Model

Select Model: dall-e-3 ※画像生成AIを作成する場合は、このモデルを選択します。
Memory: 選択あり
Model Name: イラストレータ絵(任意名)
Prompt:

Prompt
Request:あなたはイラストレータです。
Rules:入力した内容のキャラクターを描いてください。

画像生成AIの設定方法(解説)

上のメニューから[Insert]→[Image Script]をクリックすると書きの画面が表示されます。
作成したAIモデルを[Insert]します。

Image Script

すると、下記のようなソースコードが表示されます。
※ソースを省略して、AI画像生成の部分だけ解説します!

AI画像生成ソースコード
// この処理がAI生成を行っているコードになります。

// AI生成オブジェクトを作成
const serverAi = new ServerAI();
// 指示文の設定:id="text-1739404453"のテキストボックスの値を取得して設定しています。
const prompt = document.getElementById('text-1739404158').value;
// 'xxxx'が「Create Model」作成時に発行される画像生成AIのモデル番号です(自動発行)
// AIに画像生成のリクエストを送信
const answer = await serverAi.getAnswer('xxxx', {
          prompt: prompt,         // ユーザーの入力した指示文
          size: '1024x1024',      // 生成する画像のサイズ
          n: 1,                   // 生成する画像の枚数
          type: 'image'           // 生成するコンテンツの種類(画像)
});
// 作成した画像URLが「answer.imageUrl」に出力されます。
// 下記のように設定することで、出力した画像を画面上に表示することができます。
imageContainer.innerHTML = `<img src="${answer.imageUrl}" alt="${prompt}">`;

全体のソースコード

※よかったら参考に画像生成AIを作って見てください。

下記が神経衰弱のソースコードになります。※クリックすると表示されます
ソースコード※モデルIDを上記で作成したIDに変更して使ってください!
<style>
    @charset "UTF-8";
    /* 基本設定 */
    body {
      background-image: url("https://storage.googleapis.com/topdowncom/content/OxTss0BvZQODZHRpcD5laT2E1n42/57e8d828-a903-4564-8c81-7433895ef27f/a4a22115-5560-4953-a22c-ad4dbbda46e2");
  min-height: 100vh;
  margin: 0;
  padding: 0;
      background-size: cover;
      background-position: center;
      background-repeat: no-repeat;
      font-family: sans-serif;
    }
    /* タイトル */
    .heading {
      font-size: 32px;
      text-align: center;
      color: #fff;
      text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.5);
      font-weight: bold;
      margin-top: 7vh;
      margin-bottom: 14px;
    }
    /* 全体コンテナ */
    .con {
      padding: 3vh;
      background-color: #FFF;
      border-radius: 20px;
      max-width: 1000px;
      margin: 0 auto;
    }
    /* レベル・AIデザイン設定部分 */
    #level_set label {
      font-weight: bold;
      font-size: 14px;
    }
    #level_set select {
      width: 100px;
      margin: auto;
    }
    #level_set input[type="text"] {
      margin: 4px 0 4px 18px;
      width: 400px;
      border-radius: 4px;
    }
    .hidden {
      display: none;
    }
    /* スタートボタン */
    .start-button {
      background-color: #070707;
      color: white;
      font-size: 18px;
      font-weight: bold;
      padding: 10px;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      margin-top: 40px;
      display: block;
      width: 100%;
    }
    .start-button:hover {
      background-color: #393939;
      animation: anime 1.5s infinite;
    }
    .start-button:disabled,
    .start-button:disabled:hover {
      background-color: #ccc;
      cursor: not-allowed;
      animation: none;
    }
    @keyframes anime {
      0% { box-shadow: 0 0 0 0 #616161; }
      70% { box-shadow: 0 0 0 10px rgba(132, 132, 132, 0); }
      100% { box-shadow: 0 0 0 0 rgba(219, 219, 219, 0); }
    }
    /* 経過時間表示 */
    #result {
      margin: 0 0 0 10px;
      font-size: 20px;
      font-weight: bold;
      color: #000000c1;
    }
    /* リトライ用 */
    .retry {
      text-align: center;
    }
    .retryClass {
      width: 100%;
      font-size: 60px;
      font-weight: bold;
      color: rgb(255, 208, 0);
      text-shadow: 3px 3px 10px rgba(255, 215, 0, 0.8);
      margin: 80px 0 50px 0;
    }
    .retry-button {
      background-color: #070707;
      border: none;
      color: white;
      font-size: 24px;
      font-weight: bold;
      padding: 15px 30px;
      border-radius: 10px;
      cursor: pointer;
      margin-top: 20px;
      box-shadow: 2px 2px 10px rgba(42, 42, 42, 0.3);
      transition: 0.3s;
    }
    .retry-button:hover {
      background-color: #393939;
      animation: anime 1.5s infinite;
    }
    /* ゲームフィールド */
    #field {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-wrap: wrap;
      gap: 10px;
      margin-top: 20px;
    }
    /* カード */
    .card {
      background-color: #fff;
      width: 85px;
      height: 120px;
      margin: 4px;
      border: 1px solid;
      border-radius: 7px;
      text-align: center;
      font-size: 25px;
      font-weight: bold;
      line-height: 90px;
      box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
      cursor: pointer;
    }
    /* カード裏面 */
    .cardback {
      background-image: url("https://storage.googleapis.com/topdowncom/content/OxTss0BvZQODZHRpcD5laT2E1n42/2fb66b7d-d89b-44f0-ac1e-4fccb2d2b5d9/card.png");
      background-size: cover;
    }
    /* マッチ済み */
    .comp {
      opacity: 0;
    }
  </style>
  <h2 class="heading">Markdown AI 神経衰弱</h2>
  <div class="con">
    <div id="level_set">
      <label>レベル</label>
      <br>
      <select id="level">
        <option value="6">1</option>
        <option value="12">2</option>
        <option value="18">3</option>
        <option value="24">4</option>
      </select>
      <br><br>
      <label>AIデザイン</label>
      <br>
      <input type="radio" name="aiDesign" value="1" checked> AIデザインランダム<br>
      <input type="radio" name="aiDesign" value="2"> AIデザイン指定あり<br>
      <div id="specifiedDesignInput" class="hidden">
        <input type="text" id="designText">
      </div>
      <input type="radio" name="aiDesign" value="3"> AIデザイン指定なし
      <button class="start-button" id="startButton">スタート</button>
      <div id="imageCreate"></div>
    </div>
    <div id="result"></div>
    <div id="retry" class="retry"></div>
    <div id="field"></div>
  </div>

  <script>
    // 注意:'xxxxxxxxxxx'を作成したAIモデルのIDに置き換えてください
    const model_id = 'xxxxxxxxxxx';
    // 背景設定(bodyにすでにCSSで設定していますが、念のためこちらでも指定)
    document.body.style.backgroundImage = "url('https://storage.googleapis.com/topdowncom/content/OxTss0BvZQODZHRpcD5laT2E1n42/57e8d828-a903-4564-8c81-7433895ef27f/a4a22115-5560-4953-a22c-ad4dbbda46e2')";
    document.body.style.backgroundSize = "cover";
    document.body.style.backgroundPosition = "center";
    const startButton = document.getElementById("startButton");
    const designText = document.getElementById("designText");
    const radios = document.querySelectorAll('input[name="aiDesign"]');
    const specifiedDesignInput = document.getElementById("specifiedDesignInput");
    const levelSelect = document.getElementById("level");
    const imageContainer = document.getElementById('imageCreate');
    // ランダムな言葉のリスト
    const words = ["カブトムシ", "クワガタムシ", "ホタル", "テントウムシ", "カマキリ", "セミ", "チョウ", "バッタ", "アリ", "カミキリムシ", "ミツバチ", "クモ", "ハエ", "トンボ", "ゲンゴロウ","桜", "ひまわり", "チューリップ", "バラ", "コスモス","犬", "猫", "ウサギ", "ゾウ", "ライオン", "キリン", "クマ", "パンダ", "カンガルー", "ペンギン","オオカミ", "タカ", "シカ", "コアラ", "イルカ"];
    let startTime;
    let timer, setTimer;
    let tryCount = 0;
    let firstClick = true;
    let firstCard;
    let compUnit = 0;
    let setCardNo = 6;

(() => {
  let dots = 0;
  let loadingInterval;
  const updateLoadingText = () => {
      dots = (dots + 1) % 4;
      const dotsText = '.'.repeat(dots);
      imageContainer.innerText = `Generating...${dotsText}`;
  };
  startButton.addEventListener('click', async event => {
  startButton.classList.add('is-loading');
  startButton.disabled = true;
  imageContainer.innerText = 'Generating...';
  loadingInterval = setInterval(updateLoadingText, 500);
  const selectedValue = document.querySelector('input[name="aiDesign"]:checked').value;
  const specifiedDesignInput = document.getElementById("specifiedDesignInput");
  try {
      if (selectedValue === "1") {
      // ラジオボタン「1: AIデザインランダム」
          const serverAi = new ServerAI();
          const prompt = getRandomWord();
          const answer = await serverAi.getAnswer(model_id, {
            prompt: prompt,
            size: '256x256',
            n: 1,
            type: 'image'
          });
          clearInterval(loadingInterval);
          changeCardBackImage(answer.imageUrl);
          document.getElementById("level_set").innerHTML = "";
          firstScript(levelSelect.value);
      } else if (selectedValue === "2") {
            // ラジオボタン「2: AIデザイン指定あり」
          const serverAi = new ServerAI();
          const prompt = document.getElementById('designText').value;
          const answer = await serverAi.getAnswer(model_id, {
            prompt: prompt,
            size: '256x256',
            n: 1,
            type: 'image'
          });
          clearInterval(loadingInterval);
          changeCardBackImage(answer.imageUrl);
          document.getElementById("level_set").innerHTML = "";
          firstScript(levelSelect.value);
      } else if (selectedValue === "3") {
        document.getElementById("level_set").innerHTML = "";
        firstScript(levelSelect.value);
      }
  } catch (error) {
    clearInterval(loadingInterval);
    console.error('An error has occurred.:', error);
    alert(error.message || 'An error has occurred.');
    imageContainer.innerText = 'An error has occurred.';
    location.reload();
  } finally {
    startButton.classList.remove('is-loading');
    startButton.disabled = false;
  }
});
})();



function getRandomWord() {
  return words[Math.floor(Math.random() * words.length)];
}

function changeCardBackImage(newImageUrl) {
  let styleSheets = document.styleSheets;
  for (let sheet of styleSheets) {
      for (let rule of sheet.cssRules) {
          if (rule.selectorText === ".cardback") {
              rule.style.backgroundImage = `url("${newImageUrl}")`;
              return;
          }
      }
  }
}

    function toggleSpecifiedInput() {
      const selectedValue = document.querySelector('input[name="aiDesign"]:checked').value;
      if (selectedValue === "2") {
        specifiedDesignInput.classList.remove("hidden");
        checkDesignText();
      } else {
        specifiedDesignInput.classList.add("hidden");
        startButton.disabled = false;
      }
    }

    function checkDesignText() {
      if (document.querySelector('input[name="aiDesign"]:checked').value === "2") {
        startButton.disabled = designText.value.trim() === "";
      }
    }

    radios.forEach(radio => {
      radio.addEventListener("change", toggleSpecifiedInput);
    });
    designText.addEventListener("input", checkDesignText);
    toggleSpecifiedInput();

  const updateLoadingText = () => {
    dots = (dots + 1) % 4;
    const dotsText = '.'.repeat(dots);
    imageContainer.innerText = `Generating...${dotsText}`;
  };
  function updateCardBackImage(newImageUrl) {
      let cards = document.querySelectorAll(".cardback");
      cards.forEach(card => {
          card.style.backgroundImage = `url("${newImageUrl}")`;
      });
  }

    // ゲーム初期化(カードの生成・配置・シャッフル)
    function firstScript(cardNo) {
      let beforeArray = [];
      let afterArray = [];
      setCardNo = cardNo;
      const cardValues = ['A','2','3','4','5','6','7','8','9','10','J','Q','K','A','2','3','4','5','6','7','8','9','10','J','Q','K'];
      for (let i = 0; i < cardNo; i++) {
        if (i % 2) {
          beforeArray.push('♣' + cardValues[i]);
          beforeArray.push('<span style="color:red">♦</span>' + cardValues[i]);
        } else {
          beforeArray.push('♠' + cardValues[i]);
          beforeArray.push('<span style="color:red">♥</span>' + cardValues[i]);
        }
      }
      // シャッフル処理
      for (let i = 0; i < cardNo * 2; i++) {
        let r = Math.floor(Math.random() * beforeArray.length);
        afterArray.push(beforeArray[r]);
        beforeArray.splice(r, 1);
      }
      // カード要素の生成と配置
      const field = document.getElementById('field');
      field.innerHTML = "";
      for (let i = 0; i < cardNo * 2; i++) {
        const cardDiv = document.createElement('div');
        cardDiv.className = 'card cardback';
        cardDiv.cardFace = afterArray[i]; // カードの表面(HTML文字列)
        cardDiv.innerHTML = '';
        cardDiv.onclick = turn;
        field.appendChild(cardDiv);
      }
      startTime = new Date();
      timer = setInterval(drawResult, 1000);
    }

    // 経過時間・試行回数の表示更新
    function drawResult() {
      const nowTime = new Date();
      const elapsedTime = Math.floor((nowTime - startTime) / 1000);
      document.getElementById('result').innerHTML =
        '経過時間: ' + elapsedTime + '秒 チャレンジ回数: ' + tryCount + '回';
    }

    // カードがクリックされたときの処理
    function turn(e) {
      if (setTimer) return;
      const clickedCard = e.target;
      if (clickedCard.innerHTML === '') {
        clickedCard.className = 'card';
        clickedCard.innerHTML = clickedCard.cardFace;
      } else {
        return;
      }
      if (firstClick === true) {
        firstCard = clickedCard;
        firstClick = false;
      } else {
        tryCount++;
        // カードの末尾文字で一致判定(例:"♠A" と "<span style='color:red'>♥</span>A" の末尾は "A")
        if (firstCard.cardFace.substr(-1) === clickedCard.cardFace.substr(-1)) {
          compUnit++;
          setTimer = setTimeout(function() {
            clickedCard.className = 'card comp';
            firstCard.className = 'card comp';
            if (compUnit >= setCardNo) {
              clearInterval(timer);
              // クリア時のメッセージ&リトライボタン生成
              document.getElementById("field").innerHTML = "";
              const retryContainer = document.getElementById('retry');
              const messageDiv = document.createElement('div');
              messageDiv.className = 'retryClass';
              messageDiv.innerHTML = 'クリアおめでとう!';
              retryContainer.appendChild(messageDiv);
              const retryBtn = document.createElement('button');
              retryBtn.className = 'retry-button';
              retryBtn.id = 'retryButton';
              retryBtn.innerHTML = 'もう一回遊ぶ';
              retryContainer.appendChild(retryBtn);
              retryBtn.addEventListener('click', function() {
                location.reload();
              });
            }
            setTimer = null;
          }, 500);
        } else {
          setTimer = setTimeout(function() {
            clickedCard.className = 'card cardback';
            firstCard.className = 'card cardback';
            clickedCard.innerHTML = '';
            firstCard.innerHTML = '';
            setTimer = null;
          }, 500);
        }
        firstClick = true;
      }
    }
  </script>

最後に

Markdown AI を使えば、簡単にWebサイトを作成できます。
また、AIモデルや画像生成AIも手軽に設定できるため、発想次第でユニークなサイトを作ることができます。

面白いので!
ぜひ、皆さんもMarkdown AI を試してみてください。

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?