Node.js
๋ฒ์ 18.17.1
์ด์์ด ํ์ํ๋ค.npm install
npm test
๊ธฐ๋ณธ์ ์ผ๋ก 1๋ถํฐ 9๊น์ง ์๋ก ๋ค๋ฅธ ์๋ก ์ด๋ฃจ์ด์ง 3์๋ฆฌ์ ์๋ฅผ ๋ง์ถ๋ ๊ฒ์์ด๋ค.
throw
๋ฌธ์ ์ฌ์ฉํด ์์ธ๋ฅผ ๋ฐ์์ํจํ ์ ํ๋ฆฌ์ผ์ด์
์ ์ข
๋ฃ๋์ด์ผ ํ๋ค.1๋ณผ 1์คํธ๋ผ์ดํฌ
๋ซ์ฑ
3์คํธ๋ผ์ดํฌ
3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ
์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.
์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 123
1๋ณผ 1์คํธ๋ผ์ดํฌ
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 145
1๋ณผ
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 671
2๋ณผ
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 216
1์คํธ๋ผ์ดํฌ
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 713
3์คํธ๋ผ์ดํฌ
3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ
๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.
1
์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : 123
1๋ณผ
...
App.js
์ play
๋ฉ์๋์ด๋ค. ์๋์ ๊ฐ์ด ํ๋ก๊ทธ๋จ์ ์คํ์ํฌ ์ ์์ด์ผ ํ๋ค.์์
const app = new App();
app.play();
package.json
์ ๋ณ๊ฒฝํ ์ ์๊ณ ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ(jQuery, Lodash ๋ฑ)๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค. ์์ Vanilla JS๋ก๋ง ๊ตฌํํ๋ค.process.exit()
๋ฅผ ํธ์ถํ์ง ์๋๋ค.ApplicationTest
์ ๋ชจ๋ ํ
์คํธ๊ฐ ์ฑ๊ณตํด์ผ ํ๋ค. ํ
์คํธ๊ฐ ์คํจํ ๊ฒฝ์ฐ 0์ ์ฒ๋ฆฌํ๋ค.@woowacourse/mission-utils
์ Random
๋ฐ Console
API๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํด์ผ ํ๋ค.Random.pickNumberInRange()
๋ฅผ ํ์ฉํ๋ค.Console.readLineAsync
, Console.print
๋ฅผ ํ์ฉํ๋ค.const computer = [];
while (computer.length < 3) {
const number = MissionUtils.Random.pickNumberInRange(1, 9);
if (!computer.includes(number)) {
computer.push(number);
}
}
docs/README.md
์ ๊ตฌํํ ๊ธฐ๋ฅ ๋ชฉ๋ก์ ์ ๋ฆฌํด ์ถ๊ฐํ๋ค.๊ฒ์ ์ง์ ์ฌ๋ถ
์ ๋๋ค ์ซ์
๋ฅผ ๊ฐ์ง ์์ฑ์๋๋ค ์ซ์ ์์ฑ
๋ฉ์๋์
๋ ฅ๊ฐ ์ ํจ์ฑ ๊ฒ์ฌ
๋ฉ์๋์คํธ๋ผ์ดํฌ ๊ฐ์ ๊ณ์ฐ
๋ฉ์๋๋ณผ ๊ฐ์ ๊ณ์ฐ
๋ฉ์๋play
๋ฉ์๋ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
@woowacourse/mission-utils
์ Random API๋ฅผ ์ฌ์ฉํ์ฌ ๊ตฌํํด์ผ ํ๋ค.- Random ๊ฐ ์ถ์ถ์
Random.pickNumberInRange()
๋ฅผ ํ์ฉํ๋ค.- 1์์ 9๊น์ง ์๋ก ๋ค๋ฅธ ์์์ ์ 3๊ฐ๋ฅผ ์ ํํ๋ค.
Random.pickNumberInRange()
๋ฅผ ํ์ฉํด 1~9๊น์ง ๋๋ค ์ซ์๋ฅผ ๋ฝ๋๋ค. randomNumberGenerator() {
const answer = [];
while (answer.length < 3) {
const number = MissionUtils.Random.pickNumberInRange(1, 9);
if (!answer.includes(number)) {
answer.push(number);
}
}
return answer;
}
ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
- ์ฌ์ฉ์๊ฐ ์๋ชป๋ ๊ฐ์ ์ ๋ ฅํ ๊ฒฝ์ฐ throw๋ฌธ์ ์ฌ์ฉํด ์์ธ๋ฅผ ๋ฐ์์ํจํ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ข ๋ฃ๋์ด์ผ ํ๋ค.
- ์์ธ ์ํฉ ์ ์๋ฌ ๋ฌธ๊ตฌ๋ฅผ ์ถ๋ ฅํด์ผ ํ๋ค. ๋จ, ์๋ฌ ๋ฌธ๊ตฌ๋ โ[ERROR]โ๋ก ์์ํด์ผ ํ๋ค.
- ex. [ERROR] ์ซ์๊ฐ ์๋ชป๋ ํ์์ ๋๋ค.
โ ์ด๋, throw Error
๋ฅผ ํ์ง ์๊ณ Console์ ์๋ฌ ๋ฉ์ธ์ง ์ถ๋ ฅ๋ง ํ๋ฉด test์ ํต๊ณผ๋์ง ์์ผ๋ฏ๋ก ์ ์ํ๋ค!
validateInput(userInput) {
if (Number.isNaN(Number(userInput))) {
throw new Error("[ERROR] ์ซ์ ํ์์ด ์๋ชป๋์์ต๋๋ค.");
} else if (userInput.length !== 3) {
throw new Error("[ERROR] ์ซ์ ๊ธธ์ด๊ฐ ์๋ชป๋์์ต๋๋ค.");
} else if (userInput.includes(0)) {
throw new Error("[ERROR] 0์ ํฌํจํ๊ณ ์์ต๋๋ค.");
} else {
return true;
}
}
ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
- ๊ฐ์ ์๊ฐ ๊ฐ์ ์๋ฆฌ์ ์์ผ๋ฉด ์คํธ๋ผ์ดํฌ์ด๋ค.
- ์คํธ๋ผ์ดํฌ ๊ฐ์๋ฅผ ์ธ์ ๋ฐํํ๋ค.
- ์) ์๋๋ฐฉ(์ปดํจํฐ)์ ์๊ฐ 425์ผ ๋, 123์ ์ ์ํ ๊ฒฝ์ฐ : 1์คํธ๋ผ์ดํฌ
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์์ ์ปดํจํฐ๊ฐ ์์ฑํ ๊ฐ๊ณผ ์์น์ ๊ฐ์ด ๋ชจ๋ ์ผ์นํ๋ ๊ฒฝ์ฐ๋ง filterํ๊ณ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
calcStrike(userInput, computerInput) {
return userInput.filter((el, i) => computerInput[i] === el).length;
}
ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
- ๊ฐ์ ์๊ฐ ๋ค๋ฅธ ์๋ฆฌ์ ์์ผ๋ฉด ๋ณผ์ด๋ค.
- ๋ณผ์ ๊ฐ์๋ฅผ ์ธ์ ๋ฐํํ๋ค.
- ๋ณผ๊ณผ ์คํธ๋ผ์ดํฌ๊ฐ ๊ฐ์ด ์์ ๊ฒฝ์ฐ ๊ฐ์ด ์ถ๋ ฅํ๋ค.
- ์) ์๋๋ฐฉ(์ปดํจํฐ)์ ์๊ฐ 425์ผ ๋, 456์ ์ ์ํ ๊ฒฝ์ฐ : 1๋ณผ 1์คํธ๋ผ์ดํฌ
์ฌ์ฉ์๊ฐ ์ ๋ ฅํ ๊ฐ์ด ์ปดํจํฐ๊ฐ ์์ฑํ ๊ฐ์ ์กด์ฌํ์ง๋ง ์์น๊น์ง๋ ์ผ์นํ์ง ์์ ๊ฒฝ์ฐ๋ฅผ filterํ๊ณ ๊ฐ์๋ฅผ ๋ฐํํ๋ค.
calcBall(userInput, computerInput) {
return userInput.filter(
(el, i) => computerInput.includes(el) && computerInput[i] !== el
).length;
}
ํ๋ก๊ทธ๋๋ฐ ์๊ตฌ์ฌํญ
- ๊ฒ์ ํ๋ ์ด์ด๋ ์ปดํจํฐ๊ฐ ์๊ฐํ๊ณ ์๋ ์๋ก ๋ค๋ฅธ 3๊ฐ์ ์ซ์๋ฅผ ์ ๋ ฅํ๋ค.
- ์ปดํจํฐ๋ ์ ๋ ฅํ ์ซ์์ ๋ํ ๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ค.
- ์ด ๊ฐ์ ๊ณผ์ ์ ๋ฐ๋ณตํด ์ปดํจํฐ๊ฐ ์ ํํ 3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ๋ฉด ๊ฒ์์ด ์ข ๋ฃ๋๋ค.
- ๊ฒ์์ ์ข ๋ฃํ ํ ๊ฒ์์ ๋ค์ ์์ํ๊ฑฐ๋ ์์ ํ ์ข ๋ฃํ ์ ์๋ค.
- ์ฌ์ฉ์์ ๊ฐ์ ์ ๋ ฅ ๋ฐ๊ณ ์ถ๋ ฅํ๊ธฐ ์ํด์๋
Console.readLineAsync
,Console.print
๋ฅผ ํ์ฉํ๋ค.
Console.readLineAsync
ํ์ฉConsole.print
ํ์ฉ async play() {
MissionUtils.Console.print("์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.");
while (this.isContinue) {
let userInput =
await MissionUtils.Console.readLineAsync("์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : ");
let isValid = this.validateInput(userInput);
if (isValid) {
const INPUT_ARR = userInput.toString().split("").map(Number);
const STRIKE = this.calcStrike(INPUT_ARR, this.computerInput);
const BALL = this.calcBall(INPUT_ARR, this.computerInput);
if (STRIKE === 0 && BALL === 0) {
MissionUtils.Console.print("๋ซ์ฑ");
} else if (STRIKE === 3) {
MissionUtils.Console.print("3์คํธ๋ผ์ดํฌ");
MissionUtils.Console.print(
"3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ"
);
MissionUtils.Console.print(
"๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์."
);
const CHOICE = await MissionUtils.Console.readLineAsync("");
if (CHOICE === "1") {
this.computerInput = this.randomNumberGenerator();
} else if (CHOICE === "2") {
this.isContinue = false;
} else {
throw new Error("[ERROR] ์๋ชป ์
๋ ฅํ์์ต๋๋ค.");
}
} else if (STRIKE > 0 && BALL > 0) {
MissionUtils.Console.print(`${BALL}๋ณผ ${STRIKE}์คํธ๋ผ์ดํฌ`);
} else if (STRIKE > 0) {
MissionUtils.Console.print(`${STRIKE}์คํธ๋ผ์ดํฌ`);
} else if (BALL > 0) {
MissionUtils.Console.print(`${BALL}๋ณผ`);
}
}
}
}
const app = new App();
app.play();
: ์์๋ช ๋๋ฌธ์ ๋ณ๊ฒฝ
const answer = [];
const ANSWER = [];
randomNumberGenerator
๋ค๋ฅธ ๋ฉ์๋๋ค(validateInput, calcStrike, calcBall)์ ๋ชจ๋ ๋์ฌ๋ก ์์ํ๋๋ก ๋ค์ด๋ฐํ๊ธฐ ๋๋ฌธ์ ๋ค์ด๋ฐ ๋ฐฉ์์ ํต์ผํ๋ค.
randomNumberGenerator
->generateRandomNum
์ค๋ณต๋๋ ์ถ๋ ฅ ์ฝ๋๋ฅผ ์ค๋ฐ๊ฟ \n
์ ์ด์ฉํด ๋จ์ถํ๋ค.
MissionUtils.Console.print("3์คํธ๋ผ์ดํฌ");
MissionUtils.Console.print("3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ");
MissionUtils.Console.print("๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.");
MissionUtils.Console.print("3์คํธ๋ผ์ดํฌ\n3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ\n๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.");
๋ํ, utils๋ฅผ importํ๋ ๋ถ๋ถ์ ๋ฐ๊พธ์ด ์ฝ๋๋ฅผ ๋จ์ถ์์ผฐ๋ค.
MissionUtils
๋ฅผ importํ ๋MissionUtils.Console.print
MissionUtils.Random.pickNumberInRange
import { MissionUtils } from "@woowacourse/mission-utils";
MissionUtils.Console.print("3์คํธ๋ผ์ดํฌ\n3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ\n๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.");
Random
, Console
๋ฅผ importํ ๋Console.print
Random.pickNumberInRange
import { Random, Console } from "@woowacourse/mission-utils";
Console.print("3์คํธ๋ผ์ดํฌ\n3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ\n๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์.");
์ด๋ ๊ฒ ํ๋ฉด MissionUtils ๋ถ๋ถ์ ์๋ตํ๊ณ ์ธ ์ ์๋ค.(์ฝ๋ ๋จ์ถ)
๋ฉ์๋ ๊ธธ์ด๊ฐ 10์ ๋์ด๊ฐ๋ฉด ๋ถ๋ฆฌํ๊ธฐ
play ๋ฉ์๋์ ๊ธธ์ด๊ฐ ๋๋ฌด ๊ธธ์ด์ ์ด๋ฅผ ๋ถ๋ฆฌํ๊ธฐ๋ก ํ๋ค.
async play() {
Console.print("์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.");
while (this.isContinue) {
const USERINPUT = await Console.readLineAsync("์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : ");
const IS_VALID = this.validateInput(USERINPUT);
if (IS_VALID) {
const INPUT_ARR = USERINPUT.toString().split("").map(Number);
const STRIKE = this.calcStrike(INPUT_ARR, this.computerInput);
const BALL = this.calcBall(INPUT_ARR, this.computerInput);
if (STRIKE === 3) {
Console.print(
"3์คํธ๋ผ์ดํฌ\n3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ\n๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์."
);
const CHOICE = await Console.readLineAsync("");
if (CHOICE === "1") {
this.computerInput = this.generateRandomNum();
} else if (CHOICE === "2") {
this.isContinue = false;
} else {
throw new Error("[ERROR] ์๋ชป ์
๋ ฅํ์์ต๋๋ค.");
}
} else if (STRIKE === 0 && BALL === 0) {
Console.print("๋ซ์ฑ");
} else if (STRIKE > 0 && BALL > 0) {
Console.print(`${BALL}๋ณผ ${STRIKE}์คํธ๋ผ์ดํฌ`);
} else if (STRIKE > 0) {
Console.print(`${STRIKE}์คํธ๋ผ์ดํฌ`);
} else if (BALL > 0) {
Console.print(`${BALL}๋ณผ`);
}
}
}
}
๊ฒฐ๊ณผ๋ฅผ ์ถ๋ ฅํ๋ printResult
๋ฉ์๋์ ๊ฒ์ ์ฌ์์/์ข
๋ฃ๋ฅผ ์ ํํ๋ selectOption
๋ฉ์๋๋ฅผ ๋ง๋ค์๋ค.
async selectOption() {
Console.print(
"3์คํธ๋ผ์ดํฌ\n3๊ฐ์ ์ซ์๋ฅผ ๋ชจ๋ ๋งํ์
จ์ต๋๋ค! ๊ฒ์ ์ข
๋ฃ\n๊ฒ์์ ์๋ก ์์ํ๋ ค๋ฉด 1, ์ข
๋ฃํ๋ ค๋ฉด 2๋ฅผ ์
๋ ฅํ์ธ์."
);
const CHOICE = await Console.readLineAsync("");
if (CHOICE === "1") {
this.computerInput = this.generateRandomNum();
} else if (CHOICE === "2") {
this.isContinue = false;
} else {
throw new Error("[ERROR] ์๋ชป ์
๋ ฅํ์์ต๋๋ค.");
}
}
async printResult(strike, ball) {
if (strike === 3) {
await this.selectOption();
} else if (strike === 0 && ball === 0) {
Console.print("๋ซ์ฑ");
} else if (strike > 0 && ball > 0) {
Console.print(`${ball}๋ณผ ${strike}์คํธ๋ผ์ดํฌ`);
} else if (strike > 0) {
Console.print(`${strike}์คํธ๋ผ์ดํฌ`);
} else if (ball > 0) {
Console.print(`${ball}๋ณผ`);
}
}
async play() {
Console.print("์ซ์ ์ผ๊ตฌ ๊ฒ์์ ์์ํฉ๋๋ค.");
while (this.isContinue) {
const USERINPUT = await Console.readLineAsync("์ซ์๋ฅผ ์
๋ ฅํด์ฃผ์ธ์ : ");
const IS_VALID = this.validateInput(USERINPUT);
if (IS_VALID) {
const INPUT_ARR = USERINPUT.toString().split("").map(Number);
const STRIKE = this.calcStrike(INPUT_ARR, this.computerInput);
const BALL = this.calcBall(INPUT_ARR, this.computerInput);
await this.printResult(STRIKE, BALL);
}
}
}
ํด๋ฆฐ์ฝ๋ ์ฐธ๊ณ ๋ธ๋ก๊ทธ
Airbnb ์คํ์ผ ๊ฐ์ด๋
๊ณผ์ ์ ์ถ ๋ฐฉ๋ฒ ์๋ด
ํ๋ฆฌ์ฝ์ค ์คํฐ ์ ๋ฆฌ ๋ธ๋ก๊ทธ
ํ๋ก ํธ์๋๋ฅผ ์ํ ๊ฐ์ฒด์งํฅ
๋ณ์๋ช ์ฝ๊ฒ ์ง๋ ์ฌ์ดํธ
๋ชฐ์ ์๊ฐ ๋ณผ ์ ์๋ ํ๋ฌ๊ทธ์ธ
ํด๋ฆฐ์ฝ๋ ์์ฑํ