react web game : 로또추첨기 Hooks
This commit is contained in:
23
react_webgame/6. 로또추첨기/Ball.jsx
Normal file
23
react_webgame/6. 로또추첨기/Ball.jsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import React, { memo } from "react";
|
||||||
|
|
||||||
|
const Ball = memo(({ number }) => {
|
||||||
|
let background;
|
||||||
|
if (number <= 10) {
|
||||||
|
background = "red";
|
||||||
|
} else if (number <= 20) {
|
||||||
|
background = "orange";
|
||||||
|
} else if (number <= 30) {
|
||||||
|
background = "yellow";
|
||||||
|
} else if (number <= 40) {
|
||||||
|
background = "blue";
|
||||||
|
} else {
|
||||||
|
background = "green";
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="ball" style={{ background }}>
|
||||||
|
{number}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default Ball;
|
||||||
93
react_webgame/6. 로또추첨기/Lotto-class.jsx
Normal file
93
react_webgame/6. 로또추첨기/Lotto-class.jsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import React, { Component } from "react";
|
||||||
|
import Ball from "./Ball";
|
||||||
|
|
||||||
|
function getWinNumbers() {
|
||||||
|
console.log("getWinNumbers");
|
||||||
|
const candidate = Array(45)
|
||||||
|
.fill()
|
||||||
|
.map((v, i) => i + 1);
|
||||||
|
const shuffle = [];
|
||||||
|
while (candidate.length > 0) {
|
||||||
|
shuffle.push(
|
||||||
|
candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const bonusNumber = shuffle[shuffle.length - 1];
|
||||||
|
const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
|
||||||
|
return [...winNumbers, bonusNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
class Lotto extends Component {
|
||||||
|
state = {
|
||||||
|
winNumbers: getWinNumbers(),
|
||||||
|
winBalls: [],
|
||||||
|
bonus: null,
|
||||||
|
redo: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
timeouts = [];
|
||||||
|
|
||||||
|
runTimeouts = () => {
|
||||||
|
const { winNumbers } = this.state;
|
||||||
|
for (let i = 0; i < this.state.winNumbers.length - 1; i++) {
|
||||||
|
this.timeouts[i] = setTimeout(() => {
|
||||||
|
this.setState((prevState) => {
|
||||||
|
return {
|
||||||
|
winBalls: [...prevState.winBalls, winNumbers[i]],
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, (i + 1) * 1000);
|
||||||
|
}
|
||||||
|
this.timeouts[6] = setTimeout(() => {
|
||||||
|
this.setState({
|
||||||
|
bonus: winNumbers[6],
|
||||||
|
redo: true,
|
||||||
|
});
|
||||||
|
}, 7000);
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.runTimeouts();
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.timeouts.forEach((v) => {
|
||||||
|
clearTimeout(v);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
if (this.timeouts.length === 0) {
|
||||||
|
this.runTimeouts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickRedo = () => {
|
||||||
|
this.setState({
|
||||||
|
winNumbers: getWinNumbers(),
|
||||||
|
winBalls: [],
|
||||||
|
bonus: null,
|
||||||
|
redo: false,
|
||||||
|
});
|
||||||
|
this.timeouts = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { winBalls, bonus, redo } = this.state;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>당첨 숫자</div>
|
||||||
|
<div id="결과창">
|
||||||
|
{winBalls.map((v) => (
|
||||||
|
<Ball key={v} number={v} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div>보너스</div>
|
||||||
|
{bonus && <Ball number={bonus} />}
|
||||||
|
{redo && <button onClick={this.onClickRedo}>한 번 더!</button>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Lotto;
|
||||||
78
react_webgame/6. 로또추첨기/Lotto.jsx
Normal file
78
react_webgame/6. 로또추첨기/Lotto.jsx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
import React, {
|
||||||
|
useState,
|
||||||
|
useRef,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useCallback,
|
||||||
|
} from "react";
|
||||||
|
import Ball from "./Ball";
|
||||||
|
|
||||||
|
function getWinNumbers() {
|
||||||
|
console.log("getWinNumbers");
|
||||||
|
const candidate = Array(45)
|
||||||
|
.fill()
|
||||||
|
.map((v, i) => i + 1);
|
||||||
|
const shuffle = [];
|
||||||
|
while (candidate.length > 0) {
|
||||||
|
shuffle.push(
|
||||||
|
candidate.splice(Math.floor(Math.random() * candidate.length), 1)[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const bonusNumber = shuffle[shuffle.length - 1];
|
||||||
|
const winNumbers = shuffle.slice(0, 6).sort((p, c) => p - c);
|
||||||
|
return [...winNumbers, bonusNumber];
|
||||||
|
}
|
||||||
|
|
||||||
|
const Lotto = () => {
|
||||||
|
const lottoNumbers = useMemo(() => getWinNumbers(), []);
|
||||||
|
const [winNumbers, setWinNumbers] = useState(lottoNumbers);
|
||||||
|
const [winBalls, setWinBalls] = useState([]);
|
||||||
|
const [bonus, setBonus] = useState(null);
|
||||||
|
const [redo, setRedo] = useState(false);
|
||||||
|
const timeouts = useRef([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
runTimeouts();
|
||||||
|
return () => {
|
||||||
|
timeouts.current.forEach((v) => {
|
||||||
|
clearTimeout(v);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}, [timeouts.current]);
|
||||||
|
|
||||||
|
const runTimeouts = () => {
|
||||||
|
for (let i = 0; i < winNumbers.length - 1; i++) {
|
||||||
|
timeouts.current[i] = setTimeout(() => {
|
||||||
|
setWinBalls((prevBalls) => [...prevBalls, winNumbers[i]]);
|
||||||
|
}, (i + 1) * 1000);
|
||||||
|
}
|
||||||
|
timeouts.current[6] = setTimeout(() => {
|
||||||
|
setBonus(winNumbers[6]);
|
||||||
|
setRedo(true);
|
||||||
|
}, 7000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onClickRedo = useCallback(() => {
|
||||||
|
setWinNumbers(getWinNumbers());
|
||||||
|
setWinBalls([]);
|
||||||
|
setBonus(null);
|
||||||
|
setRedo(false);
|
||||||
|
timeouts.current = [];
|
||||||
|
}, [winNumbers]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div>당첨 숫자</div>
|
||||||
|
<div id="결과창">
|
||||||
|
{winBalls.map((v) => (
|
||||||
|
<Ball key={v} number={v} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<div>보너스</div>
|
||||||
|
{bonus && <Ball number={bonus} />}
|
||||||
|
{redo && <button onClick={onClickRedo}>한 번 더!</button>}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Lotto;
|
||||||
6
react_webgame/6. 로또추첨기/client.jsx
Normal file
6
react_webgame/6. 로또추첨기/client.jsx
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import React from "react";
|
||||||
|
import ReactDom from "react-dom";
|
||||||
|
|
||||||
|
import Lotto from "./Lotto";
|
||||||
|
|
||||||
|
ReactDom.render(<Lotto />, document.querySelector("#root"));
|
||||||
23
react_webgame/6. 로또추첨기/index.html
Normal file
23
react_webgame/6. 로또추첨기/index.html
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<title>로또 추첨기</title>
|
||||||
|
<style>
|
||||||
|
.ball {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 20px;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
font-size: 20px;
|
||||||
|
text-align: center;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="root"></div>
|
||||||
|
<script src="./dist/app.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user