씨네
공부하는 개발자 강씨네
씨네
  • 분류 전체보기 (460)
    • Web (21)
      • HTML (11)
      • CSS (10)
    • JS 관련 (49)
      • JavaScript (27)
      • JQuery (22)
    • TS 관련 (15)
      • TypeScript (15)
    • NodeJS (7)
      • NodeJS (7)
    • 따라하며 배우는 시리즈 (23)
      • NodeJS & ReactJS Basic (23)
      • NodeJS & ReactJS Movie (0)
      • NodeJS & ReactJS Youtube (0)
      • NodeJS & ReactJS ChatBot (0)
    • SPA (14)
      • React (14)
      • Vue (0)
      • Anguler (0)
    • Java 관련 (118)
      • Java (52)
      • JDBC (6)
      • JSP & Servlet (18)
      • Spring Legecy (38)
      • SpringBoot (4)
    • Python (26)
      • Python (20)
      • PyMongo (1)
      • Django (5)
    • Git (24)
      • Github (24)
    • RDB (22)
      • Oracle (21)
      • MySQL (1)
    • NoSQL (5)
      • MongoDB (5)
    • OS (4)
      • Linux (4)
    • 빅데이터 (2)
      • hadoop (2)
    • IDE (20)
      • eclipse (11)
      • VSCODE (4)
      • VisualStudio (1)
      • IntelliJ (1)
      • PyCharm (1)
      • DBeaver (2)
    • Install (3)
      • Tomcat (1)
      • Docker (1)
      • Anaconda (1)
    • 오류&에러 (28)
      • TS (2)
      • NodeJS (7)
      • SQL (8)
      • Java (1)
      • Spring (4)
      • Git (6)
      • 기타 (0)
    • 알고리즘 (67)
      • 수열 (1)
      • 백준(backjoon) (39)
      • Programmers (27)
    • 자격증 (5)
      • SQLD (5)
    • 기타 (2)
    • IT유튜브로 지식쌓기 (2)

공지사항

인기 글

최근 글

티스토리

250x250
hELLO · Designed By 정상우.
씨네

공부하는 개발자 강씨네

[React] 게임으로 배우는 리액트 - 숫자야구
SPA/React

[React] 게임으로 배우는 리액트 - 숫자야구

2022. 6. 4. 16:55
728x90

NumberBaseball.jsx

import React, { Component, createRef } from 'react';
import Try from './Try';

// 숫자 네 개를 겹치지 않고 랜덤하게 뽑는 함수
function getNumbers() {
  const candidate = [1,2,3,4,5,6,7,8,9];
  const array = [];
  for (let i = 0; i < 4; i += 1) {
    const chosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
    array.push(chosen);
  }
  return array;
}

class NumberBaseball extends Component {
  state = {
    result: '',
    value: '',
    answer: getNumbers(), // ex: [1,3,5,7]
    tries: [], 
  };

  onSubmitForm = (e) => {
    const { value, tries, answer } = this.state;
    e.preventDefault();
    if (value === answer.join('')) {
      this.setState((prevState) => {
        return {
          result: '홈런!',
          tries: [...prevState.tries, { try: value, result: '홈런!' }],
        }
      });
      alert('게임을 다시 시작합니다!');
      this.setState({
        value: '',
        answer: getNumbers(),
        tries: [],
      });
      this.inputRef.current.focus();
    } else { // 답 틀렸으면
      const answerArray = value.split('').map((v) => parseInt(v));
      let strike = 0;
      let ball = 0;
      if (tries.length >= 9) { // 10번 이상 틀렸을 때
        this.setState({
          result: `10번 넘게 틀려서 실패! 답은 ${answer.join(',')}였습니다!`,
        });
        alert('게임을 다시 시작합니다!');
        this.setState({
          value: '',
          answer: getNumbers(),
          tries: [],
        });
        this.inputRef.current.focus();
      } else {
        for (let i = 0; i < 4; i += 1) {
          if (answerArray[i] === answer[i]) {
            strike += 1;
          } else if (answer.includes(answerArray[i])) {
            ball += 1;
          }
        }
        this.setState((prevState) => {
          return {
            tries: [...prevState.tries, { try: value, result: `${strike} 스트라이크, ${ball} 볼입니다`}],
            value: '',
          };
        });
        this.inputRef.current.focus();
      }
    }
  };

  onChangeInput = (e) => {
    console.log(this.state.answer);
    this.setState({
      value: e.target.value,
    });
  };

  inputRef = createRef(); // this.inputRef

  render() {
    const { result, value, tries } = this.state;
    return (
      <>
        <h1>{result}</h1>
        <form onSubmit={this.onSubmitForm}>
          <input ref={this.inputRef} maxLength={4} value={value} onChange={this.onChangeInput} />
        </form>
        <div>시도: {tries.length}</div>
        <ul>
          {tries.map((v, i) => {
            return (
              <Try key={`${i + 1}차 시도 :`} tryInfo={v} />
            );
          })}
        </ul>
      </>
    );
  }
}

export default NumberBaseball; // import NumberBaseball;

​

​

Try.jsx

import React, { memo } from 'react';

const Try = memo(({tryInfo}) => {
  return (
    <li>
      <div>{tryInfo.try}</div>
      <div>{tryInfo.result}</div>
    </li>
  );
});

export default Try;

function getNumbers() {
  const candidate = [1,2,3,4,5,6,7,8,9];
  const array = [];
  for (let i = 0; i < 4; i += 1) {
    const chosen = candidate.splice(Math.floor(Math.random() * (9 - i)), 1)[0];
    array.push(chosen);
  }
  return array;
}

NumberBaseball.jsx파일에서 getNumbers()함수는 숫자 4개를 겹치지 않게 생성하는 함수입니다.

숫자야구 게임에서 정답을 생성하는 함수라고 할수 있습니다.

​

onSubmitForm = (e) => {
  const { value, tries, answer } = this.state;
  e.preventDefault();
  if (value === answer.join('')) {
    this.setState((prevState) => {
      return {
        result: '홈런!',
        tries: [...prevState.tries, { try: value, result: '홈런!' }],
      }
    });
    alert('게임을 다시 시작합니다!');
    this.setState({
      value: '',
      answer: getNumbers(),
      tries: [],
    });
    this.inputRef.current.focus();
  } else { // 답 틀렸으면
    const answerArray = value.split('').map((v) => parseInt(v));
    let strike = 0;
    let ball = 0;
    if (tries.length >= 9) { // 10번 이상 틀렸을 때
      this.setState({
        result: `10번 넘게 틀려서 실패! 답은 ${answer.join(',')}였습니다!`,
      });
      alert('게임을 다시 시작합니다!');
      this.setState({
        value: '',
        answer: getNumbers(),
        tries: [],
      });
      this.inputRef.current.focus();
    } else {
      for (let i = 0; i < 4; i += 1) {
        if (answerArray[i] === answer[i]) {
          strike += 1;
        } else if (answer.includes(answerArray[i])) {
          ball += 1;
        }
      }
      this.setState((prevState) => {
        return {
          tries: [...prevState.tries, { try: value, result: `${strike} 스트라이크, ${ball} 볼입니다`}],
          value: '',
        };
      });
      this.inputRef.current.focus();
    }
  }
};

onSubmitForm함수의 경우 랜덤으로 생성한 숫자를 맞추었을 경우 게임을 새롭게 시작하고 틀렸을 경우에는 자리수와 숫자를 모두 맞춘 숫자만큼은 Strike로 계산하고 자리수는 틀리고 숫자만 맞았을 경우 ball로 계산하여 출력해줍니다.

...prevState.tries

또 중간에 이런부분이 있는데 배열의 [ ]를 없애고 값들을 다시 넣어준다고 보시면 됩니다.

예를들어 let arr = [1, 2, 3];

let arr2 = [...arr, 4, 5];

라고 친다면 arr2에는 [1, 2, 3, 4, 5]가 들어가있다고 보시면됩니다.

​

render부분에서 const { result, value, tries } = this.state;는 아래쪽에서 result, value, tries를 사용할떄 this.state.result 이런 식으로 쓰면 번거로워서 구조분해를 해준 것입니다.

728x90

'SPA > React' 카테고리의 다른 글

[React] 게임으로 배우는 리액트 - JSX에서 주석  (0) 2022.06.03
[React] 게임으로 배우는 리액트 - 컴포넌트 분리와 props  (0) 2022.06.02
[React] 게임으로 배우는 리액트 - 반복문 (map, key)  (0) 2022.06.01
[React] 게임으로 배우는 리액트 - import와 require 비교  (0) 2022.05.31
[React] 게임으로 배우는 리액트 - Webpack(웹팩)  (0) 2022.05.30
    'SPA/React' 카테고리의 다른 글
    • [React] 게임으로 배우는 리액트 - JSX에서 주석
    • [React] 게임으로 배우는 리액트 - 컴포넌트 분리와 props
    • [React] 게임으로 배우는 리액트 - 반복문 (map, key)
    • [React] 게임으로 배우는 리액트 - import와 require 비교
    씨네
    씨네
    개발자 씨네가 공부하는 내용을 기록 겸 공유하는 블로그입니다!

    티스토리툴바