본문 바로가기
Front end/JavaScript

포켓몬 MBTI Test 만들기

by re-hwi 2023. 5. 12.

요즘 과제에 치이고 알바도 하느라 블로그를 안쓴지 오래된 것 같은데 나름 짬짬히 이것저것 만들긴 했다. 한 번에 포스팅하려니 막막해서 그중 하나인 mbti 테스트 먼저 포스팅 하려한다.

 

+ 아직 디자인은 완성되지 않았는데 포켓몬 세상을 컨셉으로 잡았다 ㅋ 

 

mbti 테스트의 기본 알고리즘은 E와 I, N과 S 등 4가지 클래스의 성향을 판단하기 위해 질문이 필요하다. 따라서 각 클래스의 질문은 홀수여야 하고, 어떤 성향이 더 큰지 비교하여 출력한다.

 

완성 사이트 starlit-frangollo-737871.netlify.app

 

이렇게 된다면 결과는 각각 2번씩 선택된 ESTP가 출력된다.

 

여기서 또 문제가 생겼는데 질문을 어떻게 해야할지 문제였다. 그런데 GPT한테 간단히 설명하고 질문지를 만들어달라고 요청했는데 순식간에 만들어줘서 쉽게 해결했다.

 

사용 코드

html

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>MBTI TEST</title>
    <link rel="stylesheet" href="css.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link
        href="https://fonts.googleapis.com/css2?family=Black+Han+Sans&family=Bruno+Ace&family=Unna:ital@1&display=swap"
        rel="stylesheet">
</head>

<body>
    <div id="Title">
        나와 닮은 포켓몬은?
    </div>
    <div id="intro">
        <div id="monsterball">
            <div id="ue" class="soto"></div>
            <div id="shita" class="soto"></div>
            <div id="center">
                <div id="nakanaka">
                </div>
            </div>
        </div>

        <div id="button" onclick="btnClick()">
            <div id="letter">GO!</div>
            <div class="btn_top"></div>
            <div class="btn_bottom"></div>
        </div>
    </div>

    <div id="contant">
        <h2 id="question"></h2>
        <button class="option"></button>
        <button class="option"></button>
    </div>

    <div id="result"></div>
</body>
<script src="app.js">
</script>

</html>

css

* { margin: 0px; padding: 0px;}


body{
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  height: 100vh;
  font-family: 'Black Han Sans', sans-serif;
  /* background: linear-gradient(120deg,#FFFF00,#d7d1ca ); */
}

#Title{
  font-size: 40px;
}

@keyframes yureru {
  0% { transform: translate(0px, 0px) rotateZ(0deg); }
  10% { transform: translate(-20px, 0px) rotateZ(-10deg); }
  20% { transform: translate(0px, 0px) rotateZ(0deg); }
  30% { transform: translate(20px, 0px) rotateZ(10deg); }
  40% { transform: translate(0px, 0px) rotateZ(0deg); }
}


#monsterball {
  margin: 30px auto;
  animation: yureru 1s ease infinite;
  width: 200px;
  height: 200px;
}

.soto {
  width: 200px;
  height: 100px;
  border: 5px solid black;
}

#center {
  border: 5px solid black;
  width: 50px;
  height: 50px;
  border-radius: 50px;
  background-color: white;
  position: absolute;
  top: 80px;
  left: 75px;
  cursor: pointer;
}

#nakanaka:hover{
  transition: .5s;
  box-shadow: 2px 2px 2px
}

#nakanaka{
  border: 2px solid black;
  width: 40px;
  height: 40px;
  border-radius: 50px;
  position: absolute;
  top: 3.25px;
  left: 3.25px;
}

#ue {
  background-color: red;
  border-radius: 200px 200px 0px 0px;
}

#shita {
  background-color: white;
  border-radius: 0px 0px 200px 200px;
  position: relative;
  top: -5px;
}

.question{
  display: inline-block;
  font-weight: lighter;
}

#button{
  margin-top: 20px;
  margin-left: 8px;
  width: 180px;
  height: 60px;
  font-size: large;
  font-weight: bold;
  text-align: center;
  line-height: 60px;
  cursor: pointer;
  
}

.btn_top{
  background-color: red;
  width: 100%;
  height: 30px;
  border: black 3px solid;
  border-bottom: 0px;
  border-radius: 5px 5px 0px 0px;
}

.btn_bottom{
  background-color: white;
  width: 100%;
  height: 30px;
  border : black 3px solid;
  border-top: 0px;
  border-radius: 0px 0px 5px 5px;
}

#letter{
  position: absolute;
  margin-top: 5px;
  z-index: 2;
  display: block;
  width: 180px;
  height: 60px;
  font-weight: bold;
  font-size: 30px;
  font-family: 'Bruno Ace';
}

#contant{
  position: absolute;
  visibility: hidden;
  margin-top: -50px;
  font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif;
  text-align: center;
}

.option{
  display: inline-block;
  margin: 15px;
  width: 300px;
  height: 150px;
  border-radius: 10px;
  border: 2px solid black;
  cursor: pointer;
  font-size: large;
  font-weight: bold;
  text-align: center;
  line-height: 60px;
  /* From https://css.glass */
background: rgba(255, 255, 255, 0.2);
border-radius: 16px;
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(5px);
-webkit-backdrop-filter: blur(5px);
border: 1px solid rgba(255, 255, 255, 0.3);
}

.option_top{
  background-color: red;
  width: 100%;
  height: 30px;
  border: black 3px solid;
  border-bottom: 0px;
  border-radius: 5px 5px 0px 0px;
  z-index: 2;
}

.option:hover{
  box-shadow: 2px 2px 2px #ccc
}

JS

let I_count = 0;
let E_count = 0;
let S_count = 0;
let N_count = 0;
let F_count = 0;
let T_count = 0;
let P_count = 0;
let J_count = 0;


function btnClick() {
  var intro = document.getElementById("intro");
  var contant = document.getElementById("contant");

  intro.style.visibility = "hidden";
  contant.style.visibility = "visible";
}

const questions = [
  {
    // 여기부터 I~E 테스트
    question: "당신은 포켓몬 센터에서 주로 어떤 편?",
    options: [
      {text: "포켓몬을 치료하고 다음 전투를 준비한다", value: "I"},
      {text: "다른 트레이너들과 수다를 떨며 이야기를 나눈다", value: "E"},
    ],
  },
  {
    question: "포켓몬 배틀을 할 때 나는?",
    options: [
      {text: "이기기 위해 전략적인 장소로 간다", value: "I"},
      {text: "모두들 나 싸우는것좀 봐 많은 사람들 앞으로!", value: "E"},
    ],
  },

  {
    question: "포켓몬을 트레이닝할때 나는?",
    options: [
      {text: "다양한 트레이너와 만나며 배틀을 한다.", value: "E"},
      {text: "포켓몬과 둘이서 훈련을하며 친밀도를 높인다.", value: "I"},
    ],
  },
    // 여기부터 S~N 테스트
  {
    question: "새로운 포켓몬을 발견했을 때 나는?",
    options: [
      {text: "무슨 포켓몬인지 몰라도 일단 잡고본다.", value: "S"},
      {text: "저 포켓몬은 진화하면 어떻게 될까? 내 팀과 잘 어울릴까? 하며 생각해본다.", value: "N"},
    ],
  },

  {
    question: "포켓몬 전투 전략을 세울 때, 나는?",
    options: [
      {text: "새로운 아이디어와 창의적인 전략을 시도해 본다.", value: "N"},
      {text: "실제 전투에서 효과적이었던 전략을 바탕으로 계획한다", value: "S"},
    ],
  },

  {
    question: "포켓몬을 선택할 때, 나는?",
    options: [
      {text: "타입, 스탯 등 구체적인 정보를 기반으로 선택", value: "S"},
      {text: "성격과 포켓몬의 특징을 고려하여 선택", value: "N"},
    ],
  },
  // 여기부터 F~T 테스트
  {
    question: "팀의 포켓몬을 선택할 때 우선 순위",
    options: [
      {text: "타입, 스탯 등 구체적인 정보를 기반으로 선택", value: "T"},
      {text: "개인적으로 친한 포켓몬 우선!", value: "F"},
    ],
  },
  
  {
    question: "포켓몬 배틀에서 졌을 때 나는?",
    options: [
      {text: "같이 열심히 싸워준 포켓몬에게 위로를 한다.", value: "F"},
      {text: "왜 졌는지 진 이유에 대해 분석한다.", value: "T"},
    ],
  },
  
  {
    question: "쓰러져있는 야생 포켓몬을 발견했다!",
    options: [
      {text: "현재 포켓몬의 상황을 판단하고 바로 포켓몬 센터로 간다.", value: "T"},
      {text: "시간이 조금 걸리더라도 불안해하는 포켓몬을 안심시킨 후에 포켓몬 센터로 간다.", value: "F"},
    ],
  },
    // 여기부터 P~J 테스트
  {
    question: "포켓몬 마스터가 되기 위한 여행을 떠날 때 나는?",
    options: [
      {text: "경로를 먼저 짜고 출발!", value: "J"},
      {text: "일단 출발!", value: "P"},
    ],
  },

  {
    question: "포켓몬을 키울 때 나는?",
    options: [
      {text: "필요할 때 부르면 되지!", value: "P"},
      {text: "어떤 식으로 기를지 미리 생각한다.", value: "J"},
    ],
  },

  {
    question: "배틀을 하기 전 나는?",
    options: [
      {text: "일단 제일 쌘 애부터 내보낸다!", value: "P"},
      {text: "상대가 내는거 보고 생각할까?", value: "J"},
    ],
  },
];

let currentQuestionIndex = 0;

function showQuestion() {
  const questionElement = document.getElementById("question");
  const optionElements = document.querySelectorAll(".option");

  questionElement.textContent = questions[currentQuestionIndex].question;
  optionElements[0].textContent =
    questions[currentQuestionIndex].options[0].text;
  optionElements[0].value = questions[currentQuestionIndex].options[0].value;
  optionElements[1].textContent =
    questions[currentQuestionIndex].options[1].text;
  optionElements[1].value = questions[currentQuestionIndex].options[1].value;
}


document.addEventListener("DOMContentLoaded", () => {
  const optionButtons = document.querySelectorAll(".option");
  optionButtons.forEach((button) => {
    button.addEventListener("click", () => {
      // I_count 또는 E_count를 증가시킵니다.
      if (button.value === "I") {
        I_count += 1;
        console.log('I_count: ',I_count);
        console.log('E_count: ',E_count);
      } 
      else if (button.value === "E") {
        E_count += 1;
        console.log('I_count: ',I_count);
        console.log('E_count: ',E_count);
      }

      else if (button.value === "S") {
        S_count += 1;
        console.log('S_count: ',S_count);
        console.log('N_count: ',N_count);
      }

      else if (button.value === "N") {
        N_count += 1;
        console.log('S_count: ',S_count);
        console.log('N_count: ',N_count);
      }

      else if (button.value === "T") {
        T_count += 1;
        console.log('T_count: ',T_count);
        console.log('F_count: ',F_count);
      }

      else if (button.value === "F") {
        F_count += 1;
        console.log('T_count: ',T_count);
        console.log('F_count: ',F_count);
      }

      else if (button.value === "P") {
        P_count += 1;
        console.log('P_count: ',P_count);
        console.log('J_count: ',J_count);
      }

      else if (button.value === "J") {
        J_count += 1;
        console.log('I_count: ',P_count);
        console.log('E_count: ',J_count);
      }

      // 다음 질문으로 이동
      currentQuestionIndex += 1;
      if (currentQuestionIndex < questions.length) {
        showQuestion();
      } else {
        let result = "";
        if (I_count > E_count) {
          result += "I";
        } else {
          result += "E";
        }

        if (S_count > N_count) {
          result += "S";
        } else {
          result += "N";
        }

        if (T_count > F_count) {
          result += "T";
        } else {
          result += "F";
        }

        if (P_count > J_count) {
          result += "P";
        } else {
          result += "J";
        }
        const resultElement = document.getElementById("result");
        resultElement.textContent = result
      }
    });
  });

  

  // 첫 번째 질문을 표시합니다.
  showQuestion();
});

html에 있는 contant 부분이 버튼을 누르면 바뀌도록 JS 코드를 만들었다

반응형

댓글