๐Ÿ“ ์šฐํ…Œ์ฝ” ํ”„๋ฆฌ์ฝ”์Šค ํ”„๋ก ํŠธ์—”๋“œ ๊ณผ์ œ 2์ฃผ์ฐจ

Doozuuยท2023๋…„ 10์›” 31์ผ
0

ํšŒ๊ณ 

๋ชฉ๋ก ๋ณด๊ธฐ
10/13
post-thumbnail

๋ฏธ์…˜ - ์ž๋™์ฐจ ๊ฒฝ์ฃผ

๐Ÿ” ์ง„ํ–‰ ๋ฐฉ์‹

  • ๋ฏธ์…˜์€ ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ, ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์š”๊ตฌ ์‚ฌํ•ญ, ๊ณผ์ œ ์ง„ํ–‰ ์š”๊ตฌ ์‚ฌํ•ญ ์„ธ ๊ฐ€์ง€๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ๋‹ค.
  • ์„ธ ๊ฐœ์˜ ์š”๊ตฌ ์‚ฌํ•ญ์„ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด ๋…ธ๋ ฅํ•œ๋‹ค. ํŠนํžˆ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „์— ๊ธฐ๋Šฅ ๋ชฉ๋ก์„ ๋งŒ๋“ค๊ณ , ๊ธฐ๋Šฅ ๋‹จ์œ„๋กœ ์ปค๋ฐ‹ ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•œ๋‹ค.
  • ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ์— ๊ธฐ์žฌ๋˜์ง€ ์•Š์€ ๋‚ด์šฉ์€ ์Šค์Šค๋กœ ํŒ๋‹จํ•˜์—ฌ ๊ตฌํ˜„ํ•œ๋‹ค.

๐Ÿ“ฎ ๋ฏธ์…˜ ์ œ์ถœ ๋ฐฉ๋ฒ•

  • ๋ฏธ์…˜ ๊ตฌํ˜„์„ ์™„๋ฃŒํ•œ ํ›„ GitHub์„ ํ†ตํ•ด ์ œ์ถœํ•ด์•ผ ํ•œ๋‹ค.
  • GitHub์— ๋ฏธ์…˜์„ ์ œ์ถœํ•œ ํ›„ ์šฐ์•„ํ•œํ…Œํฌ์ฝ”์Šค ์ง€์› ์‚ฌ์ดํŠธ์— ์ ‘์†ํ•˜์—ฌ ํ”„๋ฆฌ์ฝ”์Šค ๊ณผ์ œ๋ฅผ ์ œ์ถœํ•œ๋‹ค.
    • ์ž์„ธํ•œ ๋ฐฉ๋ฒ•์€ ์ œ์ถœ ๊ฐ€์ด๋“œ ์ฐธ๊ณ 
    • Pull Request๋งŒ ๋ณด๋‚ด๊ณ  ์ง€์› ํ”Œ๋žซํผ์—์„œ ๊ณผ์ œ๋ฅผ ์ œ์ถœํ•˜์ง€ ์•Š์œผ๋ฉด ์ตœ์ข… ์ œ์ถœํ•˜์ง€ ์•Š์€ ๊ฒƒ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋‹ˆ ์ฃผ์˜ํ•œ๋‹ค.

๐Ÿšจ ๊ณผ์ œ ์ œ์ถœ ์ „ ์ฒดํฌ ๋ฆฌ์ŠคํŠธ - 0์  ๋ฐฉ์ง€

  • ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ๋ชจ๋‘ ์ •์ƒ์ ์œผ๋กœ ํ–ˆ๋”๋ผ๋„ ์š”๊ตฌ ์‚ฌํ•ญ์— ๋ช…์‹œ๋œ ์ถœ๋ ฅ๊ฐ’ ํ˜•์‹์„ ์ง€ํ‚ค์ง€ ์•Š์„ ๊ฒฝ์šฐ 0์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ๊ธฐ๋Šฅ ๊ตฌํ˜„์„ ์™„๋ฃŒํ•œ ๋’ค ์•„๋ž˜ ๊ฐ€์ด๋“œ์— ๋”ฐ๋ผ ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ–ˆ์„ ๋•Œ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ•˜๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  • ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•  ๊ฒฝ์šฐ 0์ ์œผ๋กœ ์ฒ˜๋ฆฌ๋˜๋ฏ€๋กœ, ๋ฐ˜๋“œ์‹œ ํ™•์ธ ํ›„ ์ œ์ถœํ•œ๋‹ค.

ํ…Œ์ŠคํŠธ ์‹คํ–‰ ๊ฐ€์ด๋“œ

  • ํ…Œ์ŠคํŠธ ํŒจํ‚ค์ง€ ์„ค์น˜๋ฅผ ์œ„ํ•ด Node.js ๋ฒ„์ „ 18.17.1 ์ด์ƒ์ด ํ•„์š”ํ•˜๋‹ค.
  • ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ด ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•œ๋‹ค.
npm install
  • ์„ค์น˜๊ฐ€ ์™„๋ฃŒ๋˜์—ˆ๋‹ค๋ฉด, ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•ด ํ…Œ์ŠคํŠธ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
npm test

๐Ÿš€ ๊ธฐ๋Šฅ ์š”๊ตฌ ์‚ฌํ•ญ

์ดˆ๊ฐ„๋‹จ ์ž๋™์ฐจ ๊ฒฝ์ฃผ ๊ฒŒ์ž„์„ ๊ตฌํ˜„ํ•œ๋‹ค.

  • ์ฃผ์–ด์ง„ ํšŸ์ˆ˜ ๋™์•ˆ n๋Œ€์˜ ์ž๋™์ฐจ๋Š” ์ „์ง„ ๋˜๋Š” ๋ฉˆ์ถœ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ฐ ์ž๋™์ฐจ์— ์ด๋ฆ„์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ „์ง„ํ•˜๋Š” ์ž๋™์ฐจ๋ฅผ ์ถœ๋ ฅํ•  ๋•Œ ์ž๋™์ฐจ ์ด๋ฆ„์„ ๊ฐ™์ด ์ถœ๋ ฅํ•œ๋‹ค.
  • ์ž๋™์ฐจ ์ด๋ฆ„์€ ์‰ผํ‘œ(,)๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๋ฉฐ ์ด๋ฆ„์€ 5์ž ์ดํ•˜๋งŒ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์‚ฌ์šฉ์ž๋Š” ๋ช‡ ๋ฒˆ์˜ ์ด๋™์„ ํ•  ๊ฒƒ์ธ์ง€๋ฅผ ์ž…๋ ฅํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.
  • ์ „์ง„ํ•˜๋Š” ์กฐ๊ฑด์€ 0์—์„œ 9 ์‚ฌ์ด์—์„œ ๋ฌด์ž‘์œ„ ๊ฐ’์„ ๊ตฌํ•œ ํ›„ ๋ฌด์ž‘์œ„ ๊ฐ’์ด 4 ์ด์ƒ์ผ ๊ฒฝ์šฐ์ด๋‹ค.
  • ์ž๋™์ฐจ ๊ฒฝ์ฃผ ๊ฒŒ์ž„์„ ์™„๋ฃŒํ•œ ํ›„ ๋ˆ„๊ฐ€ ์šฐ์Šนํ–ˆ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ค€๋‹ค. ์šฐ์Šน์ž๋Š” ํ•œ ๋ช… ์ด์ƒ์ผ ์ˆ˜ ์žˆ๋‹ค.
  • ์šฐ์Šน์ž๊ฐ€ ์—ฌ๋Ÿฌ ๋ช…์ผ ๊ฒฝ์šฐ ์‰ผํ‘œ(,)๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌ๋ถ„ํ•œ๋‹ค.
  • ์‚ฌ์šฉ์ž๊ฐ€ ์ž˜๋ชป๋œ ๊ฐ’์„ ์ž…๋ ฅํ•œ ๊ฒฝ์šฐ throw๋ฌธ์„ ์‚ฌ์šฉํ•ด "[ERROR]"๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ๊ฐ€์ง€๋Š” ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ ํ›„, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ์ข…๋ฃŒ๋˜์–ด์•ผ ํ•œ๋‹ค.
    ์˜ˆ์‹œ) [ERROR] ์ˆซ์ž๊ฐ€ ์ž˜๋ชป๋œ ํ˜•์‹์ž…๋‹ˆ๋‹ค.

์ž…์ถœ๋ ฅ ์š”๊ตฌ ์‚ฌํ•ญ

์ž…๋ ฅ

  • ๊ฒฝ์ฃผ ํ•  ์ž๋™์ฐจ ์ด๋ฆ„(์ด๋ฆ„์€ ์‰ผํ‘œ(,) ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„)
pobi,woni,jun
  • ์‹œ๋„ํ•  ํšŸ์ˆ˜
5

์ถœ๋ ฅ

  • ๊ฐ ์ฐจ์ˆ˜๋ณ„ ์‹คํ–‰ ๊ฒฐ๊ณผ
pobi : --
woni : ----
jun : ---
  • ๋‹จ๋… ์šฐ์Šน์ž ์•ˆ๋‚ด ๋ฌธ๊ตฌ
์ตœ์ข… ์šฐ์Šน์ž : pobi
  • ๊ณต๋™ ์šฐ์Šน์ž ์•ˆ๋‚ด ๋ฌธ๊ตฌ
์ตœ์ข… ์šฐ์Šน์ž : pobi, jun

์‹คํ–‰ ๊ฒฐ๊ณผ ์˜ˆ์‹œ

๊ฒฝ์ฃผํ•  ์ž๋™์ฐจ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.(์ด๋ฆ„์€ ์‰ผํ‘œ(,) ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„)
pobi,woni,jun
์‹œ๋„ํ•  ํšŸ์ˆ˜๋Š” ๋ช‡ ํšŒ์ธ๊ฐ€์š”?
5

์‹คํ–‰ ๊ฒฐ๊ณผ
pobi : -
woni :
jun : -

pobi : --
woni : -
jun : --

pobi : ---
woni : --
jun : ---

pobi : ----
woni : ---
jun : ----

pobi : -----
woni : ----
jun : -----

์ตœ์ข… ์šฐ์Šน์ž : pobi, jun

๐ŸŽฏ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์š”๊ตฌ ์‚ฌํ•ญ

  • Node.js 18.17.1 ๋ฒ„์ „์—์„œ ์‹คํ–‰ ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค. Node.js 18.17.1์—์„œ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ 0์  ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์˜ ์‹œ์ž‘์ ์€ App.js์˜ play ๋ฉ”์„œ๋“œ์ด๋‹ค. ์•„๋ž˜์™€ ๊ฐ™์ด ํ”„๋กœ๊ทธ๋žจ์„ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ์–ด์•ผ ํ•œ๋‹ค.

์˜ˆ์‹œ

const app = new App();
app.play();
  • package.json์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๊ณ  ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(jQuery, Lodash ๋“ฑ)๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ์ˆœ์ˆ˜ Vanilla JS๋กœ๋งŒ ๊ตฌํ˜„ํ•œ๋‹ค.
  • JavaScript ์ฝ”๋“œ ์ปจ๋ฒค์…˜์„ ์ง€ํ‚ค๋ฉด์„œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ•œ๋‹ค
  • ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์‹œ process.exit()๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • ํ”„๋กœ๊ทธ๋žจ ๊ตฌํ˜„์ด ์™„๋ฃŒ๋˜๋ฉด ApplicationTest์˜ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ์„ฑ๊ณตํ•ด์•ผ ํ•œ๋‹ค. ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•  ๊ฒฝ์šฐ 0์  ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์š”๊ตฌ ์‚ฌํ•ญ์—์„œ ๋‹ฌ๋ฆฌ ๋ช…์‹œํ•˜์ง€ ์•Š๋Š” ํ•œ ํŒŒ์ผ, ํŒจํ‚ค์ง€ ์ด๋ฆ„์„ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ ์ด๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ถ”๊ฐ€๋œ ์š”๊ตฌ ์‚ฌํ•ญ

  • indent(์ธ๋ดํŠธ, ๋“ค์—ฌ์“ฐ๊ธฐ) depth๋ฅผ 3์ด ๋„˜์ง€ ์•Š๋„๋ก ๊ตฌํ˜„ํ•œ๋‹ค. 2๊นŒ์ง€๋งŒ ํ—ˆ์šฉํ•œ๋‹ค.
    • ์˜ˆ๋ฅผ ๋“ค์–ด while๋ฌธ ์•ˆ์— if๋ฌธ์ด ์žˆ์œผ๋ฉด ๋“ค์—ฌ์“ฐ๊ธฐ๋Š” 2์ด๋‹ค.
    • ํžŒํŠธ: indent(์ธ๋ดํŠธ, ๋“ค์—ฌ์“ฐ๊ธฐ) depth๋ฅผ ์ค„์ด๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์€ ํ•จ์ˆ˜(๋˜๋Š” ๋ฉ”์†Œ๋“œ)๋ฅผ ๋ถ„๋ฆฌํ•˜๋ฉด ๋œ๋‹ค.
  • Jest๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ณธ์ธ์ด ์ •๋ฆฌํ•œ ๊ธฐ๋Šฅ ๋ชฉ๋ก์ด ์ •์ƒ ๋™์ž‘ํ•จ์„ ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋กœ ํ™•์ธํ•œ๋‹ค.
    • ํ…Œ์ŠคํŠธ ๋„๊ตฌ ์‚ฌ์šฉ๋ฒ•์ด ์ต์ˆ™ํ•˜์ง€ ์•Š๋‹ค๋ฉด __tests__/StringTest.js๋ฅผ ์ฐธ๊ณ ํ•˜์—ฌ ํ•™์Šตํ•œ ํ›„ ํ…Œ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•œ๋‹ค.

๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

  • @woowacourse/mission-utils์—์„œ ์ œ๊ณตํ•˜๋Š” Random ๋ฐ Console API๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
    • Random ๊ฐ’ ์ถ”์ถœ์€ Random.pickNumberInRange()๋ฅผ ํ™œ์šฉํ•œ๋‹ค.
    • ์‚ฌ์šฉ์ž์˜ ๊ฐ’์„ ์ž…๋ ฅ ๋ฐ›๊ณ  ์ถœ๋ ฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Console.readLineAsync, Console.print๋ฅผ ํ™œ์šฉํ•œ๋‹ค.

์‚ฌ์šฉ ์˜ˆ์‹œ

  • 0์—์„œ 9๊นŒ์ง€์˜ ์ •์ˆ˜ ์ค‘ ํ•œ ๊ฐœ์˜ ์ •์ˆ˜ ๋ฐ˜ํ™˜
MissionUtils.Random.pickNumberInRange(0, 9);

โœ๏ธ ๊ณผ์ œ ์ง„ํ–‰ ์š”๊ตฌ ์‚ฌํ•ญ

  • ๋ฏธ์…˜์€ javascript-racingcar-6 ์ €์žฅ์†Œ๋ฅผ Fork & Cloneํ•ด ์‹œ์ž‘ํ•œ๋‹ค.
  • ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๊ธฐ ์ „ docs/README.md์— ๊ตฌํ˜„ํ•  ๊ธฐ๋Šฅ ๋ชฉ๋ก์„ ์ •๋ฆฌํ•ด ์ถ”๊ฐ€ํ•œ๋‹ค.
  • Git์˜ ์ปค๋ฐ‹ ๋‹จ์œ„๋Š” ์•ž ๋‹จ๊ณ„์—์„œ docs/README.md์— ์ •๋ฆฌํ•œ ๊ธฐ๋Šฅ ๋ชฉ๋ก ๋‹จ์œ„๋กœ ์ถ”๊ฐ€ํ•œ๋‹ค.
  • ๊ณผ์ œ ์ง„ํ–‰ ๋ฐ ์ œ์ถœ ๋ฐฉ๋ฒ•์€ ํ”„๋ฆฌ์ฝ”์Šค ๊ณผ์ œ ์ œ์ถœ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•œ๋‹ค.



๐Ÿ“ย ๊ธฐ๋Šฅ ๋ชฉ๋ก

  1. ์ž๋™์ฐจ ์ด๋ฆ„ ์ž…๋ ฅ๋ฐ›๊ธฐ
    • ์ž๋™์ฐจ ์ด๋ฆ„์€ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.
    • ์ž๋™์ฐจ ์ด๋ฆ„์€ 5์ž ์ดํ•˜์—ฌ์•ผ ํ•œ๋‹ค.
    • ์ด๋ฆ„์€ ์ค‘๋ณต๋˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
    • ์ž˜๋ชป๋œ ๊ฐ’์„ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
  2. ์ด๋™ ํšŸ์ˆ˜ ์ž…๋ ฅ๋ฐ›๊ธฐ
    • ์ด๋™ ํšŸ์ˆ˜๋Š” ์ˆซ์ž์—ฌ์•ผ ํ•œ๋‹ค.
    • ์ด๋™ ํšŸ์ˆ˜๋Š” 0๋ณด๋‹ค ์ปค์•ผ ํ•œ๋‹ค.
    • ์ž˜๋ชป๋œ ๊ฐ’์„ ์ž…๋ ฅํ•  ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์„ธ์ง€๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.
  3. ์ž๋™์ฐจ ์ด๋™์‹œํ‚ค๊ธฐ
    • ์ด๋™ ํšŸ์ˆ˜๋งŒํผ ์‹œํ–‰์„ ๋ฐ˜๋ณตํ•œ๋‹ค.
    • ๊ฐ ์ž๋™์ฐจ์—์„œ 0~9 ์‚ฌ์ด์˜ ๋ฌด์ž‘์œ„ ๊ฐ’์„ ๋ฝ‘๋Š”๋‹ค.
    • ๋ฝ‘์€ ๊ฐ’์ด 4 ์ด์ƒ์ด๋ฉด ์ „์ง„ํ•œ๋‹ค.
    • ๋ฝ‘์€ ๊ฐ’์ด 4 ๋ฏธ๋งŒ์ด๋ฉด ์ „์ง„ํ•˜์ง€ ์•Š๋Š”๋‹ค.
    • ๋ชจ๋“  ์‹คํ–‰ ๊ณผ์ •์„ ์ถœ๋ ฅํ•œ๋‹ค.
  4. ๊ฒฐ๊ณผ ์ถœ๋ ฅํ•˜๊ธฐ
    • ์ „์ง„์„ ๊ฐ€์žฅ ๋งŽ์ด ํ•œ ์ž๋™์ฐจ๊ฐ€ ์ตœ์ข… ์šฐ์Šน์ž๊ฐ€ ๋œ๋‹ค.
    • ์ตœ์ข… ์šฐ์Šนํ•œ ์ž๋™์ฐจ์˜ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•œ๋‹ค.
    • ์šฐ์Šน์ž๊ฐ€ ๋‹ค์ˆ˜์ผ ๊ฒฝ์šฐ ์‰ผํ‘œ๋ฅผ ์ด์šฉํ•˜์—ฌ ๊ตฌ๋ถ„ํ•œ๋‹ค.



์ฒ˜์Œ ์ง  ์ฝ”๋“œ

import { Console, Random } from "@woowacourse/mission-utils";

class App {
  constructor() {
    this.carList = [];
    this.tryNum = 0;
  }

  async getInput() {
    Console.print(
      "๊ฒฝ์ฃผํ•  ์ž๋™์ฐจ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.(์ด๋ฆ„์€ ์‰ผํ‘œ(,) ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„)"
    );
    const input = await Console.readLineAsync("");
    if (!input.split(",")) {
      throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค.");
    } else if (input.split(",").filter((el) => el.length > 5).length > 0) {
      throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ๊ธธ์ด๊ฐ€ 5๋ณด๋‹ค ํฝ๋‹ˆ๋‹ค.");
    } else if (input.split(",").filter((el) => !isNaN(+el)).length > 0) {
      throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ํ˜•์‹์ด ์ž˜๋ชป ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
    }
    // ์ด๋ฆ„ ์ค‘๋ณต๋˜๋Š” ๊ฒฝ์šฐ๋„ ์˜ˆ์™ธ์ฒ˜๋ฆฌํ•˜๊ธฐ
    input.split(",").map((el) => this.carList.push({ name: el, score: 0 }));
    await this.getTryNum();
  }

  async getTryNum() {
    Console.print("์‹œ๋„ํ•  ํšŸ์ˆ˜๋Š” ๋ช‡ ํšŒ์ธ๊ฐ€์š”?");
    const input = await Console.readLineAsync("");
    if (!isNaN(input)) {
      Console.print("\n์‹คํ–‰ ๊ฒฐ๊ณผ");
      while (this.tryNum < input) {
        this.action();
        this.tryNum++;
      }
      this.calcWinner();
    } else {
      throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ํ˜•์‹์ด ์ž˜๋ชป ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
    }
  }

  action() {
    this.carList = this.carList.map(({ name, score }) => ({
      name: name,
      score: score + +this.randomNumGenerator(),
    }));
    this.carList.map(({ name, score }) =>
      Console.print(`${name} : ${"-".repeat(score)}`)
    );
    Console.print("\n");
  }

  randomNumGenerator() {
    const num = Random.pickNumberInRange(0, 9);
    return num >= 4 ? true : false;
  }

  calcWinner() {
    const scoreList = this.carList.map((el) => el.score);
    const max = Math.max(...scoreList);
    const maxList = this.carList.filter((el) => el.score === max);

    Console.print(`์ตœ์†ก ์šฐ์Šน์ž : ${maxList.map((el) => el.name).join(", ")}`);
  }

  async play() {
    await this.getInput();
  }
}

export default App;



โ™ป๏ธ ๋ฆฌํŒฉํ† ๋ง

App.js

import { Console } from "@woowacourse/mission-utils";
import { validateCarNames } from "./ValidateCarNames";
import { addCarNames } from "./AddCarNames";
import { validateTrialNumbers } from "./ValidateTrialNumbers";
import { playGame } from "./PlayGame";
class App {
  constructor() {
    this.carNames = [];
    this.trialNumbers = 0;
  }

  async getCarNames() {
    Console.print(
      "๊ฒฝ์ฃผํ•  ์ž๋™์ฐจ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜์„ธ์š”.(์ด๋ฆ„์€์ž— ์‰ผํ‘œ(,) ๊ธฐ์ค€์œผ๋กœ ๊ตฌ๋ถ„)"
    );
    const INPUT = await Console.readLineAsync("");
    const IS_VALID = validateCarNames(INPUT);

    if (IS_VALID) {
      addCarNames(INPUT, this.carNames);
      await this.getTrialNumbers();
    }
  }

  async getTrialNumbers() {
    Console.print("์‹œ๋„ํ•  ํšŸ์ˆ˜๋Š” ๋ช‡ ํšŒ์ธ๊ฐ€์š”?");
    const INPUT = await Console.readLineAsync("");
    const IS_VALID = validateTrialNumbers(INPUT);

    if (IS_VALID) {
      playGame(this.trialNumbers, INPUT, this.carNames);
      this.printWinner();
    }
  }

  printWinner() {
    const SCORE_LIST = this.carNames.map((el) => el.score);
    const MAX_SCORE = Math.max(...SCORE_LIST);
    const MAX_SCORE_LIST = this.carNames.filter((el) => el.score === MAX_SCORE);

    Console.print(
      `์ตœ์†ก ์šฐ์Šน์ž : ${MAX_SCORE_LIST.map((el) => el.name).join(", ")}`
    );
  }

  async play() {
    await this.getCarNames();
  }
}

export default App;

AddCarNames

export const addCarNames = (input, carNames) => {
  const CAR_NAME = input.split(",");

  CAR_NAME.forEach((el) => carNames.push({ name: el, score: 0 }));
};

MoveCar

import { Console } from "@woowacourse/mission-utils";
import { randomNumberGenerator } from "./RandomNumberGenerator";

export const moveCar = (carNames) => {
  carNames = carNames.map(({ name, score }) => ({
    name: name,
    score: score + +randomNumberGenerator(),
  }));
  carNames.map(({ name, score }) =>
    Console.print(`${name} : ${"-".repeat(score)}`)
  );
  Console.print("\n");
};

playGame

import { Console } from "@woowacourse/mission-utils";
import { moveCar } from "./MoveCar";

export const playGame = (trialNumbers, input, carNames) => {
  Console.print("\n์‹คํ–‰ ๊ฒฐ๊ณผ");

  while (trialNumbers < input) {
    moveCar(carNames);
    trialNumbers = trialNumbers + 1;
  }
};

RandomNumberGenerator

import { Random } from "@woowacourse/mission-utils";

export const randomNumberGenerator = () => {
  const RANDOM_NUMBER = Random.pickNumberInRange(0, 9);
  if (RANDOM_NUMBER >= 4) {
    return true;
  } else {
    return false;
  }
};

validateCarNames

export const validateCarNames = (input) => {
  const CAR_NAME = input.split(",");

  if (!CAR_NAME) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์ด ๋น„์–ด ์žˆ์Šต๋‹ˆ๋‹ค.");
  } else if (CAR_NAME.length < 2) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์ด ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
  } else if (CAR_NAME.filter((el) => el.length > 5).length > 0) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ๊ธธ์ด๊ฐ€ 5๋ณด๋‹ค ํฝ๋‹ˆ๋‹ค.");
  } else if (CAR_NAME.filter((el) => !isNaN(+el)).length > 0) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ํ˜•์‹์ด ์ž˜๋ชป ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
  } else if (new Set(CAR_NAME).size !== CAR_NAME.length) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์ด ์ค‘๋ณต๋ฉ๋‹ˆ๋‹ค.");
  }

  return true;
};

validateTrialNumbers

export const validateTrialNumbers = (input) => {
  if (input === 0) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์€ 0๋ณด๋‹ค ์ปค์•ผ ํ•ฉ๋‹ˆ๋‹ค.");
  } else if (isNaN(input)) {
    throw new Error("[ERROR] ์ž…๋ ฅ๊ฐ’์˜ ํ˜•์‹์ด ์ž˜๋ชป ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.");
  }
  return true;
};



๐Ÿ” ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

์ž๋™์ฐจ ์ด๋ฆ„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ…Œ์ŠคํŠธ

import { validateCarNames } from "../src/ValidateCarNames";

test("์ž…๋ ฅ๊ฐ’์ด ๋น„์–ด์žˆ์„ ๊ฒฝ์šฐ", () => {
  expect(() => validateCarNames("")).toThrow("[ERROR]");
});

test("์ž…๋ ฅ๊ฐ’์ด ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋˜์–ด ์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ", () => {
  expect(() => validateCarNames("pobiwoni")).toThrow("[ERROR]");
});

test("์ž…๋ ฅ๊ฐ’์˜ ๊ธธ์ด๊ฐ€ 5๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ", () => {
  expect(() => validateCarNames("pobi,woni,stella")).toThrow("[ERROR]");
});

test("์ž…๋ ฅ๊ฐ’ ํ˜•์‹์ด ์ž˜๋ชป๋œ ๊ฒฝ์šฐ", () => {
  expect(() => validateCarNames("123,456")).toThrow("[ERROR]");
});

test("์ž…๋ ฅ๊ฐ’์ด ์ค‘๋ณต๋œ ๊ฒฝ์šฐ", () => {
  expect(() => validateCarNames("pobi,pobi,woni")).toThrow("[ERROR]");
});

์‹œํ–‰ ํšŸ์ˆ˜ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ํ…Œ์ŠคํŠธ

import { validateTrialNumbers } from "../src/ValidateTrialNumbers";

test("์ž…๋ ฅ๊ฐ’์ด 0์ธ ๊ฒฝ์šฐ", () => {
  expect(() => validateTrialNumbers(0)).toThrow("[ERROR]");
});

test("์ž…๋ ฅ๊ฐ’ ํ˜•์‹์ด ์ž˜๋ชป๋œ ๊ฒฝ์šฐ", () => {
  expect(() => validateTrialNumbers("abc")).toThrow("[ERROR]");
});

์šฐ์Šน์ž ์ถœ๋ ฅ ํ…Œ์ŠคํŠธ

import App from "../src/App";

test("์šฐ์Šน์ž ๋‹ค์ˆ˜์ผ ๋•Œ ํ…Œ์ŠคํŠธ", () => {
  const app = new App();

  app.carNames = [
    { name: "Car1", score: 2 },
    { name: "Car2", score: 4 },
    { name: "Car3", score: 4 },
  ];

  const message = app.printWinner();

  expect(message).toBe("์ตœ์†ก ์šฐ์Šน์ž : Car2, Car3");
});

test("์šฐ์Šน์ž 1๋ช…์ผ ๋•Œ ํ…Œ์ŠคํŠธ", () => {
  const app = new App();

  app.carNames = [
    { name: "Car1", score: 2 },
    { name: "Car2", score: 5 },
    { name: "Car3", score: 4 },
  ];

  const message = app.printWinner();

  expect(message).toBe("์ตœ์†ก ์šฐ์Šน์ž : Car2");
});



๐Ÿ‘€ ๊ฐœ์„ ํ•œ ์ 

  • ๊ณตํ†ต ํ”ผ๋“œ๋ฐฑ ์‚ฌํ•ญ์„ ์ฐธ๊ณ ํ•˜๊ณ  ๋‹ค๋ฅธ ๋ถ„๋“ค์˜ ์ฝ”๋“œ๋ฅผ ํ•™์Šตํ•˜๋ฉฐ ์ฝ”๋“œ๋ฅผ ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ธฐ๋Šฅ ๋ชฉ๋ก์„ ๋‹จ๊ณ„๋ณ„๋กœ ์ƒ์„ธํžˆ ๋‚˜๋ˆ„์–ด ์ž‘์„ฑํ•˜๊ณ , ์ด์— ๋”ฐ๋ผ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋„๋ก ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ฐ€๋Šฅํ•œ ์˜ˆ์™ธ ์ผ€์ด์Šค๋ฅผ ์ตœ๋Œ€ํ•œ ๊ณ ๋ คํ•˜์—ฌ ์ž…๋ ฅ๊ฐ’ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด์ „์—๋Š” ํ•œ ํŒŒ์ผ์— ๋ชจ๋‘ ์ž‘์„ฑํ•˜์—ฌ ์ฝ”๋“œ ๊ธธ์ด๊ฐ€ ๊ธธ์–ด์ง€๊ณ  depth๊ฐ€ ๊นŠ์–ด์ง€๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ์—ˆ๋Š”๋ฐ, ์ด๋ฒˆ์—๋Š” ํ•จ์ˆ˜๋ฅผ ๋ชจ๋“ˆ๋กœ ๋ถ„๋ฆฌํ•˜์—ฌ depth ๋‚ฎ์ถ”๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ณ€์ˆ˜๋‚˜ ํ•จ์ˆ˜ ์ด๋ฆ„์„ ์ถ•์•ฝํ•˜์ง€ ์•Š๊ณ  ์ตœ๋Œ€ํ•œ ์ •ํ™•ํ•˜๊ฒŒ ์ „๋‹ฌํ•˜๋„๋ก ๊ฐœ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€์— ์ด๋ชจ์ง€์™€ ์ปค๋ฐ‹ ๋ฉ”์„ธ์ง€ ํ—ค๋”๋ฅผ ํ•จ๊ป˜ ์ž‘์„ฑํ•ด ์ปค๋ฐ‹ ์ปจ๋ฒค์…˜์„ ์ง€ํ‚ค๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ฒ˜์Œ ์ž‘์„ฑํ•ด๋ณด๋ฉฐ ํ…Œ์ŠคํŠธ ์ž‘์„ฑ๋ฒ•์„ ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค.



โœŒ๏ธ 2์ฃผ์ฐจ ๊ณผ์ œ ์™„๋ฃŒ



์ฐธ๊ณ ์ž๋ฃŒ

์ปค๋ฐ‹ ๋˜๋Œ๋ฆฌ๊ธฐ
https://wooono.tistory.com/667
ํ…Œ์ŠคํŠธ ์ฝ”๋“œ ์ž‘์„ฑ๋ฒ•
https://codiving.kr/115
https://velog.io/@velopert/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%85%8C%EC%8A%A4%ED%8C%85%EC%9D%98-%EA%B8%B0%EC%B4%88

profile
๋ชจ๋“ ๊ฒŒ ์ƒˆ๋กญ๊ณ  ์žฌ๋ฐŒ๋Š” ํ”„๋ก ํŠธ์—”๋“œ ์ƒˆ์‹น

0๊ฐœ์˜ ๋Œ“๊ธ€

๊ด€๋ จ ์ฑ„์šฉ ์ •๋ณด