리액트 class/hooks로 구현한
숫자야구 게임 입니다.
숫자야구 게임 입니다.
예제는 인프런의 제로초, "조현영"님의 강의를 들으면서 공부한 내용입니다.
구현 순서
순서 | 특이사항 |
컴퓨터가 랜덤 4자리 숫자 문제 제출 | 예시) 4385, 조건)겹치지 않는 4개 |
사용자가 답을 입력 | |
입력한 답의 결과 발표 |
결과 발표: 홈런/스트라이크/볼 홈런) 숫자가 모두 일치할 경우 스트라이크) 자리수가 맞을 경우 볼) 자리수는 맞이 않으나, 숫자가 맞을 경우 답이 맞을때까지 10회 제한을 둠 |
파일 구조
client.jsx >NumberBaseball.jsx >Try.jsx
client.jsx
import React from 'react';
import ReactDom from 'react-dom';
import NumberBaseball from './NumberBaseball';
ReactDom.render(<NumberBaseball />, document.querySelector('#root'));
NumberBaseball.jsx - class 방식
import React, { createRef } from 'react';
import Try from './Try';
function getNumbers() { //숫자4개를 겹치지 않게 뽑는 함수
const candidates = [1,2,3,4,5,6,7,8,9];
const chosenNum = [];
//splice()가 index를 하나씩 빼주기 때문에 뽑을 숫자가 하나씩 줄음
//안했을 경우, 랜덤 숫자가 undefined가 나옴 -> 9-i로 index 수 반영
for (let i=0; i<4; i++) {
const mixedNum = candidates.splice(Math.floor(Math.random() * (9-i)), 1);
chosenNum.push(mixedNum[0]);
}
console.log('정답:' + chosenNum.join(''));
return chosenNum;
}
class NumberBaseball extends React.Component {
state = {
result: '',
value: '',
answer: getNumbers(),
tries: [], //입력한 데이터 기록, push로 데이터 저장하면 안됨
};
onSubmit =(e) => { //property 생성
e.preventDefault();
//숫자야구 로직
if(this.state.value === this.state.answer.join('')) { //정답일 경우,
this.setState ((prevState) => {
return {
result: '홈런!',
value: 'this.state.answer',
tries: [...prevState.tries, {try: this.state.value, result: '홈런'}],
}
})
alert('게임을 다시 시작합니다.'); //초기화
this.setState({ //초기화
value: '',
answer: getNumbers(),
tries: [],
});
this.input.current.focus;
}else{ //틀렸을 경우, strike, ball 안내
//입력한 value값을 to array(split()) map으로 요소 하나씩 확인
//string이므로 parseInt로 number 변환
const answerArray = this.state.value.split('').map(item => parseInt(item));
let strike = 0;
let ball = 0;
if (this.state.tries.length >= 9) { //10번이상 실패시
this.setState({
result: `10번 넘게 틀려서 실패하였습니다. 정답은 ${this.state.answer} 입니다.`
});
alert('게임을 다시 시작합니다.');
this.setState({ //초기화
value: '',
answer: getNumbers(),
tries: [],
});
this.input.current.focus;
} else { //10번 미만 실패시
//몇 스크라이크, 몇 볼인지 확인하는 코드
for(let i=0; i<4; i+=1) { //strike 체크
if(answerArray[i] === this.state.answer[i]) {
strike +=1;
}else if (this.state.answer.includes(answerArray[i])) { //ball 체크
ball+=1;
}
}
this.setState((prevState) => {
return {
tries: [...prevState.tries, {
try: this.state.value, result: `${strike} 스트라이크 ${ball} 볼입니다.`
}],
value :'',
}
})
}
console.log(answerArray);
this.setState({
result: '땡',
value: '',
});
}
}
onChange = (e) => { //property 생성
this.setState({value : e.target.value})
}
inputRef = createRef(); //this.inputRef(=property) 생성
render(){
return (
<>
<h1>{this.state.result}</h1>
<form onSubmit={this.onSubmit}>
<input type="number" maxLength={4} ref={this.inputRef} value={this.state.value}
onChange={this.onChange} />
<button type='submit'>입력</button>
</form>
<div>시도횟수: {this.state.tries.length}</div>
<ul>
{this.state.tries.map((item, i) => {
return (
<Try key={`${i+1}차 시도 :`} value={item.try} result={item.result}
index={i} />
);
})}
</ul>
</>
)
}
}
export default NumberBaseball;
NumberBaseball.jsx - hooks 방식
import React, { useState, useRef }from 'react';
import Try from './Try';
const getNumbers = () => { //숫자4개를 겹치지 않게 뽑는 함수
const candidates = [1,2,3,4,5,6,7,8,9];
const chosenNum = [];
//splice()가 index를 하나씩 빼주기 때문에 뽑을 숫자가 하나씩 줄음
//안했을 경우, 랜덤 숫자가 undefined가 나옴 -> 9-i로 index 수 반영
for (let i=0; i<4; i++) {
const mixedNum = candidates.splice(Math.floor(Math.random() * (9-i)), 1);
chosenNum.push(mixedNum[0]);
}
console.log('정답:' + chosenNum.join(''));
return chosenNum;
}
const NumberBaseball = () => {
//hooks로 state선언
const [result, setResult] = useState('');
const [value, setValue] = useState('');
const [answer, setAnswer] = useState(getNumbers());
const [tries, setTries] = useState([]);
const onRefInput = useRef(null);
const onSubmit =(e) => {
e.preventDefault();
//숫자야구 로직
if(value === answer.join('')) { //정답일 경우,
setResult('홈런!');
setTries((prevTries)=> { //에전 데이터로 새로운 것을 만들때는 함수형
return [...prevTries, {try: value, result: '홈런'}]
});
alert('게임을 다시 시작합니다.'); //초기화
setValue('');
setAnswer(getNumbers());
setTries([]);
}else{ //틀렸을 경우, strike, ball 안내
//입력한 value값을 to array(split()) map으로 요소 하나씩 확인
//string이므로 parseInt로 number 변환
const answerArray = value.split('').map(item => parseInt(item));
let strike = 0;
let ball = 0;
if (tries.length >= 9) { //10번이상 실패시
setResult( `10번 넘게 틀려서 실패하였습니다. 정답은 ${answer} 입니다.`);
alert('게임을 다시 시작합니다.');
setValue('');
setAnswer(getNumbers());
setTries([]);
} else { //10번 미만 실패시
//몇 스크라이크, 몇 볼인지 확인하는 코드
for(let i=0; i<4; i+=1) { //strike 체크
if(answerArray[i] === answer[i]) {
strike +=1;
}else if (answer.includes(answerArray[i])) { //ball 체크
ball+=1;
}
}
setTries((prevTries) => {return [...prevTries,
{try: value, result: `${strike} 스트라이크 ${ball} 볼입니다.`}]}
)
}
setResult('땡');
setValue('');
onRefInput.current.focus();
}
}
const onChange = (e) => {
setValue(e.target.value);
//console.log(e.target.value);
}
return (
<>
<h1>{result}</h1>
<form onSubmit={onSubmit}>
<input type="number" maxLength={4} value={value} onChange={onChange} ref={onRefInput}/>
<button type='submit'>입력</button>
</form>
<div>시도횟수: {tries.length}</div>
<ul>
{tries.map((item, i) => {
return (
<Try key={`${i+1}차 시도 :`} value={item.try} result={item.result}
index={i} />
);
})}
</ul>
</>
);
};
export default NumberBaseball;
Try.jsx
import React, { Component } from 'react';
const Try = ({value, result, index}) => {
return (
<li>
내가 낸 숫자: {value} / 결과: { result} / {index + 1} 번째
</li>
)
}
export default Try;
반응형
'개발 > React' 카테고리의 다른 글
[react] react로 가위바위보 게임 만들기 (0) | 2021.04.01 |
---|---|
[react] react로 반응속도 테스트 게임 만들기(ft. useRef, 조건문, spread 연산자) (0) | 2021.03.24 |
[react] 리액트로 끝말잇기 게임 만들기 (2) | 2021.03.24 |
[react] 리액트 컴포넌트 props로 데이터 전달 (0) | 2021.03.17 |
[react] react의 반복문 map, 컴포넌트 사용법(ft. props) (0) | 2021.03.17 |
댓글