From 5577af4e6ab8f85db50a69b8d4f9fa69179015ca Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Thu, 12 May 2022 15:46:31 +0900 Subject: [PATCH 01/30] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=20=EC=82=AC=ED=95=AD=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index b4b1377..d267387 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,19 @@ ## πŸš€ κΈ°λŠ₯ μš”κ΅¬ 사항 +- [ ] μ‹œμž‘ 문ꡬλ₯Ό λ„μ›Œμ€€λ‹€. +- [ ] λ‹΅μ•ˆμ„ μž…λ ₯λ°›λŠ”λ‹€. + - λ‹΅μ•ˆμ€ 5κΈ€μžμ—¬μ•Ό ν•œλ‹€. + - λ‹΅μ•ˆμ€ `words.txt` μ•ˆμ— μ‘΄μž¬ν•˜λŠ” 단어여야 ν•œλ‹€. +- [ ] μ •λ‹΅κ³Ό λ‹΅μ•ˆμ„ λΉ„κ΅ν•˜μ—¬ κ²°κ³Όλ₯Ό νƒ€μΌλ‘œ ν‘œν˜„ν•œλ‹€. + - λ§žλŠ” κΈ€μžλŠ” μ΄ˆλ‘μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. + - μœ„μΉ˜κ°€ 틀리면 λ…Έλž€μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. + - 정닡에 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κΈ€μžλ©΄ νšŒμƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. + - 두 개의 λ™μΌν•œ 문자λ₯Ό μž…λ ₯ν•˜κ³  그쀑 ν•˜λ‚˜κ°€ νšŒμƒ‰μœΌλ‘œ ν‘œμ‹œλ˜λ©΄ ν•΄λ‹Ή 문자 쀑 ν•˜λ‚˜λ§Œ μ΅œμ’… 단어에 λ‚˜νƒ€λ‚œλ‹€. +- [ ] 정닡은 맀일 바뀐닀. + - `words.txt` μ•ˆμ˜ ((ν˜„μž¬ λ‚ μ§œ - 2021λ…„ 6μ›” 19일) % λ°°μ—΄μ˜ 크기) 번째의 단어이닀. +- [ ] 정닡을 λ§žμ·„μ„ 경우 타일 ν‘œν˜„ 전에 λͺ‡ 번째 λ§Œμ— λ§žμ·„λŠ”μ§€ 좜λ ₯ν•œλ‹€. + 선풍적인 인기λ₯Ό λŒμ—ˆλ˜ μ˜μ–΄ 단어 λ§žμΆ”κΈ° κ²Œμž„μ΄λ‹€. - 6x5 격자λ₯Ό ν†΅ν•΄μ„œ 5κΈ€μž 단어λ₯Ό 6번 λ§Œμ— μΆ”μΈ‘ν•œλ‹€. From 913234c74a5dcff44df45036396034584acb93b6 Mon Sep 17 00:00:00 2001 From: summerlunaa Date: Thu, 12 May 2022 16:36:28 +0900 Subject: [PATCH 02/30] =?UTF-8?q?feat:=20GameWord=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/GameWord.kt | 9 +++++++++ src/test/kotlin/wordle/GameWordTest.kt | 27 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/main/kotlin/wordle/GameWord.kt create mode 100644 src/test/kotlin/wordle/GameWordTest.kt diff --git a/src/main/kotlin/wordle/GameWord.kt b/src/main/kotlin/wordle/GameWord.kt new file mode 100644 index 0000000..c1b5fc2 --- /dev/null +++ b/src/main/kotlin/wordle/GameWord.kt @@ -0,0 +1,9 @@ +package wordle + +class GameWord(private val word: String) { + + init { + require(word.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } + require(Regex("[a-zA-Z]*").matches(word)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } + } +} diff --git a/src/test/kotlin/wordle/GameWordTest.kt b/src/test/kotlin/wordle/GameWordTest.kt new file mode 100644 index 0000000..9159f63 --- /dev/null +++ b/src/test/kotlin/wordle/GameWordTest.kt @@ -0,0 +1,27 @@ +package wordle + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +class GameWordTest { + + @Test + fun `5κΈ€μžκ°€ μ•„λ‹Œ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { + val exception = shouldThrow { + GameWord("test") + } + exception.message shouldBe "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." + } + + @ParameterizedTest + @ValueSource(strings = ["ap pl", "apν”Όle"]) + fun `μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžκ°€ ν¬ν•¨λœ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`(word: String) { + val exception = shouldThrow { + GameWord(word) + } + exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." + } +} From 9adf4b79d7d3dbdfc7bd4aa2419d4224a79b4786 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 17:22:51 +0900 Subject: [PATCH 03/30] =?UTF-8?q?refactor:=20=ED=81=B4=EB=9E=98=EC=8A=A4?= =?UTF-8?q?=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/{GameWord.kt => Word.kt} | 5 ++++- src/test/kotlin/wordle/{GameWordTest.kt => WordTest.kt} | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-) rename src/main/kotlin/wordle/{GameWord.kt => Word.kt} (51%) rename src/test/kotlin/wordle/{GameWordTest.kt => WordTest.kt} (91%) diff --git a/src/main/kotlin/wordle/GameWord.kt b/src/main/kotlin/wordle/Word.kt similarity index 51% rename from src/main/kotlin/wordle/GameWord.kt rename to src/main/kotlin/wordle/Word.kt index c1b5fc2..82dc2f6 100644 --- a/src/main/kotlin/wordle/GameWord.kt +++ b/src/main/kotlin/wordle/Word.kt @@ -1,9 +1,12 @@ package wordle -class GameWord(private val word: String) { +class Word(private val word: String) { init { require(word.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } require(Regex("[a-zA-Z]*").matches(word)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } + // κ²Œμž„μ΄ μ‹œμž‘λ˜λ©΄ ν•œλ²ˆμ— word.textλ₯Ό κ°€μ Έμ™€μ„œ μ½μ–΄μ˜¨ λ‹€μŒμ— λΉ„κ΅ν•˜λŠ”κ²Œ λ‚«λ‹€ + // 맀번 μ½λŠ”κ±° -> λΉ„νš¨μœ¨μ  + // Words List <- words.text } } diff --git a/src/test/kotlin/wordle/GameWordTest.kt b/src/test/kotlin/wordle/WordTest.kt similarity index 91% rename from src/test/kotlin/wordle/GameWordTest.kt rename to src/test/kotlin/wordle/WordTest.kt index 9159f63..78bd112 100644 --- a/src/test/kotlin/wordle/GameWordTest.kt +++ b/src/test/kotlin/wordle/WordTest.kt @@ -6,12 +6,12 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.ValueSource -class GameWordTest { +class WordTest { @Test fun `5κΈ€μžκ°€ μ•„λ‹Œ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { val exception = shouldThrow { - GameWord("test") + Word("test") } exception.message shouldBe "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } @@ -20,7 +20,7 @@ class GameWordTest { @ValueSource(strings = ["ap pl", "apν”Όle"]) fun `μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžκ°€ ν¬ν•¨λœ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`(word: String) { val exception = shouldThrow { - GameWord(word) + Word(word) } exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } From 490274e6e25ba6c92340d7ed267ad430a05738a3 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 17:25:39 +0900 Subject: [PATCH 04/30] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=97=90=20forAll=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/wordle/WordTest.kt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/kotlin/wordle/WordTest.kt b/src/test/kotlin/wordle/WordTest.kt index 78bd112..3143148 100644 --- a/src/test/kotlin/wordle/WordTest.kt +++ b/src/test/kotlin/wordle/WordTest.kt @@ -1,10 +1,9 @@ package wordle import io.kotest.assertions.throwables.shouldThrow +import io.kotest.inspectors.forAll import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.ValueSource class WordTest { @@ -16,12 +15,13 @@ class WordTest { exception.message shouldBe "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } - @ParameterizedTest - @ValueSource(strings = ["ap pl", "apν”Όle"]) - fun `μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžκ°€ ν¬ν•¨λœ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`(word: String) { - val exception = shouldThrow { - Word(word) + @Test + fun `μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžκ°€ ν¬ν•¨λœ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { + listOf("ap pl", "apν”Όle").forAll { + val exception = shouldThrow { + Word(it) + } + exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } - exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } } From 6fd8eb7fcc012b7b92d5bd19429c77d258c28ea4 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 18:05:26 +0900 Subject: [PATCH 05/30] =?UTF-8?q?feat:=20Words=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/kotlin/wordle/Word.kt | 2 +- src/main/kotlin/wordle/Words.kt | 24 ++++++++++++++++++++++++ src/test/kotlin/wordle/WordsTest.kt | 26 ++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/wordle/Words.kt create mode 100644 src/test/kotlin/wordle/WordsTest.kt diff --git a/README.md b/README.md index d267387..bcf4d88 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ - [ ] μ‹œμž‘ 문ꡬλ₯Ό λ„μ›Œμ€€λ‹€. - [ ] λ‹΅μ•ˆμ„ μž…λ ₯λ°›λŠ”λ‹€. - - λ‹΅μ•ˆμ€ 5κΈ€μžμ—¬μ•Ό ν•œλ‹€. + - [x] λ‹΅μ•ˆμ€ 5κΈ€μžμ—¬μ•Ό ν•œλ‹€. - λ‹΅μ•ˆμ€ `words.txt` μ•ˆμ— μ‘΄μž¬ν•˜λŠ” 단어여야 ν•œλ‹€. - [ ] μ •λ‹΅κ³Ό λ‹΅μ•ˆμ„ λΉ„κ΅ν•˜μ—¬ κ²°κ³Όλ₯Ό νƒ€μΌλ‘œ ν‘œν˜„ν•œλ‹€. - λ§žλŠ” κΈ€μžλŠ” μ΄ˆλ‘μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. diff --git a/src/main/kotlin/wordle/Word.kt b/src/main/kotlin/wordle/Word.kt index 82dc2f6..fb25f38 100644 --- a/src/main/kotlin/wordle/Word.kt +++ b/src/main/kotlin/wordle/Word.kt @@ -1,6 +1,6 @@ package wordle -class Word(private val word: String) { +data class Word(private val word: String) { init { require(word.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } diff --git a/src/main/kotlin/wordle/Words.kt b/src/main/kotlin/wordle/Words.kt new file mode 100644 index 0000000..621b53b --- /dev/null +++ b/src/main/kotlin/wordle/Words.kt @@ -0,0 +1,24 @@ +package wordle + +import java.time.LocalDate +import java.time.temporal.ChronoUnit + +class Words(private val values: List) { + + private val answer: Word = findAnswer() + + private fun findAnswer(): Word { + val date: LocalDate = LocalDate.now() + val standardDate: LocalDate = LocalDate.of(2021, 6, 19) + val days: Int = ChronoUnit.DAYS.between(standardDate, date).toInt() + return values[days % values.size] + } + + fun contains(word: Word): Boolean { + return values.contains(word) + } + + fun isCorrect(word: Word): Boolean { + return word == answer + } +} diff --git a/src/test/kotlin/wordle/WordsTest.kt b/src/test/kotlin/wordle/WordsTest.kt new file mode 100644 index 0000000..1001f37 --- /dev/null +++ b/src/test/kotlin/wordle/WordsTest.kt @@ -0,0 +1,26 @@ +package wordle + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class WordsTest { + + @Test + fun `단어가 리슀트 μ•ˆμ— μ‘΄μž¬ν•˜λŠ”μ§€ 확인해쀀닀`() { + val apple = Word("apple") + val happy = Word("happy") + val doggy = Word("doggy") + val words = Words(listOf(apple, happy)) + + words.contains(apple) shouldBe true + words.contains(doggy) shouldBe false + } + + @Test + fun `단어가 정닡인지 확인해쀀닀`() { + val words = Words(listOf(Word("apple"))) + + words.isCorrect(Word("apple")) shouldBe true + words.isCorrect(Word("happy")) shouldBe false + } +} From 41725cb5d4b34e999fe65d8dc6a79a650f3b322c Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 19:16:48 +0900 Subject: [PATCH 06/30] =?UTF-8?q?feat:=20WordsReader=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- src/main/kotlin/wordle/WordsReader.kt | 12 ++++++++++++ src/test/kotlin/wordle/WordsReaderTest.kt | 13 +++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/wordle/WordsReader.kt create mode 100644 src/test/kotlin/wordle/WordsReaderTest.kt diff --git a/README.md b/README.md index bcf4d88..c712185 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ - μœ„μΉ˜κ°€ 틀리면 λ…Έλž€μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. - 정닡에 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κΈ€μžλ©΄ νšŒμƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. - 두 개의 λ™μΌν•œ 문자λ₯Ό μž…λ ₯ν•˜κ³  그쀑 ν•˜λ‚˜κ°€ νšŒμƒ‰μœΌλ‘œ ν‘œμ‹œλ˜λ©΄ ν•΄λ‹Ή 문자 쀑 ν•˜λ‚˜λ§Œ μ΅œμ’… 단어에 λ‚˜νƒ€λ‚œλ‹€. -- [ ] 정닡은 맀일 바뀐닀. - - `words.txt` μ•ˆμ˜ ((ν˜„μž¬ λ‚ μ§œ - 2021λ…„ 6μ›” 19일) % λ°°μ—΄μ˜ 크기) 번째의 단어이닀. +- [x] 정닡은 맀일 바뀐닀. + - [x] `words.txt` μ•ˆμ˜ ((ν˜„μž¬ λ‚ μ§œ - 2021λ…„ 6μ›” 19일) % λ°°μ—΄μ˜ 크기) 번째의 단어이닀. - [ ] 정닡을 λ§žμ·„μ„ 경우 타일 ν‘œν˜„ 전에 λͺ‡ 번째 λ§Œμ— λ§žμ·„λŠ”μ§€ 좜λ ₯ν•œλ‹€. 선풍적인 인기λ₯Ό λŒμ—ˆλ˜ μ˜μ–΄ 단어 λ§žμΆ”κΈ° κ²Œμž„μ΄λ‹€. diff --git a/src/main/kotlin/wordle/WordsReader.kt b/src/main/kotlin/wordle/WordsReader.kt new file mode 100644 index 0000000..dbdb214 --- /dev/null +++ b/src/main/kotlin/wordle/WordsReader.kt @@ -0,0 +1,12 @@ +package wordle + +import java.io.FileReader + +object WordsReader { + + fun getWords(): List { + val path = "src/main/resources/words.txt" + val reader = FileReader(path) + return reader.readLines().map { Word(it) } + } +} diff --git a/src/test/kotlin/wordle/WordsReaderTest.kt b/src/test/kotlin/wordle/WordsReaderTest.kt new file mode 100644 index 0000000..96fe9de --- /dev/null +++ b/src/test/kotlin/wordle/WordsReaderTest.kt @@ -0,0 +1,13 @@ +package wordle + +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class WordsReaderTest { + + @Test + fun `νŒŒμΌμ„ μ½μ–΄μ„œ Listλ₯Ό λ°˜ν™˜ν•΄μ€€λ‹€`() { + val words = WordsReader.getWords() + words.size shouldBe 2309 + } +} From eb2e781ad94a6de236c57299443429e4037d26b9 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 21:31:08 +0900 Subject: [PATCH 07/30] =?UTF-8?q?feat:=20=EB=8B=A8=EC=96=B4=EB=A5=BC=20?= =?UTF-8?q?=EB=B9=84=EA=B5=90=ED=95=98=EC=97=AC=20=EA=B2=B0=EA=B3=BC?= =?UTF-8?q?=EB=A5=BC=20=EA=B3=84=EC=82=B0=ED=95=98=EB=8A=94=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Tile.kt | 6 ++++ src/main/kotlin/wordle/Word.kt | 13 ++++---- src/main/kotlin/wordle/Words.kt | 46 +++++++++++++++++++++++++++++ src/test/kotlin/wordle/WordTest.kt | 8 +++++ src/test/kotlin/wordle/WordsTest.kt | 10 +++++++ 5 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/wordle/Tile.kt diff --git a/src/main/kotlin/wordle/Tile.kt b/src/main/kotlin/wordle/Tile.kt new file mode 100644 index 0000000..3ca485f --- /dev/null +++ b/src/main/kotlin/wordle/Tile.kt @@ -0,0 +1,6 @@ +package wordle + +enum class Tile(val symbol: String) { + + YELLOW("🟨"), GREEN("🟩"), GRAY("⬜") +} diff --git a/src/main/kotlin/wordle/Word.kt b/src/main/kotlin/wordle/Word.kt index fb25f38..9affdfd 100644 --- a/src/main/kotlin/wordle/Word.kt +++ b/src/main/kotlin/wordle/Word.kt @@ -1,12 +1,13 @@ package wordle -data class Word(private val word: String) { +data class Word(val value: String) { init { - require(word.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } - require(Regex("[a-zA-Z]*").matches(word)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } - // κ²Œμž„μ΄ μ‹œμž‘λ˜λ©΄ ν•œλ²ˆμ— word.textλ₯Ό κ°€μ Έμ™€μ„œ μ½μ–΄μ˜¨ λ‹€μŒμ— λΉ„κ΅ν•˜λŠ”κ²Œ λ‚«λ‹€ - // 맀번 μ½λŠ”κ±° -> λΉ„νš¨μœ¨μ  - // Words List <- words.text + require(value.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } + require(Regex("[a-zA-Z]*").matches(value)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } + } + + fun isSameChar(other: Word, index: Int): Boolean { + return this.value[index] == other.value[index] } } diff --git a/src/main/kotlin/wordle/Words.kt b/src/main/kotlin/wordle/Words.kt index 621b53b..9dc6993 100644 --- a/src/main/kotlin/wordle/Words.kt +++ b/src/main/kotlin/wordle/Words.kt @@ -6,6 +6,7 @@ import java.time.temporal.ChronoUnit class Words(private val values: List) { private val answer: Word = findAnswer() + private var answerMap: MutableMap = HashMap() private fun findAnswer(): Word { val date: LocalDate = LocalDate.now() @@ -21,4 +22,49 @@ class Words(private val values: List) { fun isCorrect(word: Word): Boolean { return word == answer } + + fun check(word: Word): List { + answerMap = initAnswerMap() + val result: ArrayList = ArrayList() + repeat(5) { result.add(Tile.GRAY) } + + repeat(5) { i -> result[i] = findTileBySameCheck(word, i) } + repeat(5) { i -> result[i] = findTileByContainCheck(result, word, i) } + return result + } + + private fun initAnswerMap(): MutableMap { + val answerMap: MutableMap = HashMap() + answer.value.forEach { + answerMap.putIfAbsent(it, 0) + answerMap.computeIfPresent(it) { _, v -> v + 1 } + } + return answerMap + } + + private fun findTileBySameCheck(word: Word, index: Int): Tile { + if (answer.isSameChar(word, index)) { + calculateAnswerMap(word.value[index]) + return Tile.GREEN + } + return Tile.GRAY + } + + private fun findTileByContainCheck(result: List, word: Word, index: Int): Tile { + if (result[index] == Tile.GREEN) { + return Tile.GREEN + } + if (answerMap.keys.contains(word.value[index])) { + calculateAnswerMap(word.value[index]) + return Tile.YELLOW + } + return Tile.GRAY + } + + private fun calculateAnswerMap(key: Char) { + answerMap.computeIfPresent(key) { _, v -> v - 1 } + if (answerMap[key] == 0) { + answerMap.remove(key) + } + } } diff --git a/src/test/kotlin/wordle/WordTest.kt b/src/test/kotlin/wordle/WordTest.kt index 3143148..4433706 100644 --- a/src/test/kotlin/wordle/WordTest.kt +++ b/src/test/kotlin/wordle/WordTest.kt @@ -24,4 +24,12 @@ class WordTest { exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } } + + @Test + fun `ν•΄λ‹Ή κΈ€μžκ°€ λ‹¨μ–΄μ˜ νŠΉμ • μΈλ±μŠ€μ™€ μΌμΉ˜ν•˜λŠ”μ§€ ν™•μΈν•œλ‹€`() { + val word = Word("style") + val other = Word("soooo") + word.isSameChar(other, 0) shouldBe true + word.isSameChar(other, 1) shouldBe false + } } diff --git a/src/test/kotlin/wordle/WordsTest.kt b/src/test/kotlin/wordle/WordsTest.kt index 1001f37..b51ce29 100644 --- a/src/test/kotlin/wordle/WordsTest.kt +++ b/src/test/kotlin/wordle/WordsTest.kt @@ -23,4 +23,14 @@ class WordsTest { words.isCorrect(Word("apple")) shouldBe true words.isCorrect(Word("happy")) shouldBe false } + + @Test + fun `단어λ₯Ό μ •λ‹΅κ³Ό λΉ„κ΅ν•˜μ—¬ κ²°κ³Ό 타일을 λ°˜ν™˜ν•œλ‹€`() { + val words = Words(listOf(Word("apple"))) + val word = Word("hello") + + val checkList = words.check(word) + + checkList shouldBe listOf(Tile.GRAY, Tile.YELLOW, Tile.GRAY, Tile.GREEN, Tile.GRAY) + } } From 50de938d00e14367df0da1e4442bb8e1823222ca Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 21:48:14 +0900 Subject: [PATCH 08/30] =?UTF-8?q?feat:=20Game=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Game.kt | 19 +++++++++++++++++++ src/test/kotlin/wordle/GameTest.kt | 25 +++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 src/main/kotlin/wordle/Game.kt create mode 100644 src/test/kotlin/wordle/GameTest.kt diff --git a/src/main/kotlin/wordle/Game.kt b/src/main/kotlin/wordle/Game.kt new file mode 100644 index 0000000..d8451f6 --- /dev/null +++ b/src/main/kotlin/wordle/Game.kt @@ -0,0 +1,19 @@ +package wordle + +class Game(private val words: Words) { + + constructor(words: List) : this(Words(words)) + + var count: Int = 0 + private set + + fun isGameOver(): Boolean { + return count == 6 + } + + fun match(answer: Word): List { + count++ + require(words.contains(answer)) { "λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€." } + return words.check(answer) + } +} diff --git a/src/test/kotlin/wordle/GameTest.kt b/src/test/kotlin/wordle/GameTest.kt new file mode 100644 index 0000000..855704e --- /dev/null +++ b/src/test/kotlin/wordle/GameTest.kt @@ -0,0 +1,25 @@ +package wordle + +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +class GameTest { + + @Test + fun `λ“±λ‘λœ 단어가 μ•„λ‹Œ 경우 μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { + val game = Game(listOf(Word("apple"), Word("hello"), Word("spicy"))) + + val exception = shouldThrow { + game.match(Word("spell")) + } + exception.message shouldBe "λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€." + } + + @Test + internal fun `κ²Œμž„ μ’…λ£Œμ—¬λΆ€λ₯Ό ν™•μΈν•œλ‹€`() { + val game = Game(listOf(Word("apple"), Word("hello"), Word("spicy"))) + repeat(6) { game.match(Word("apple")) } + game.isGameOver() shouldBe true + } +} From 6ca90e73c5de6494e669a510ed0f171e0405f641 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Fri, 13 May 2022 23:07:50 +0900 Subject: [PATCH 09/30] =?UTF-8?q?feat:=20View=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?=EB=B0=8F=20Application=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 19 +++++++++++++++++++ src/main/kotlin/wordle/Game.kt | 13 ++++++++----- src/main/kotlin/wordle/InputView.kt | 9 +++++++++ src/main/kotlin/wordle/OutputView.kt | 27 +++++++++++++++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/main/kotlin/wordle/Application.kt create mode 100644 src/main/kotlin/wordle/InputView.kt create mode 100644 src/main/kotlin/wordle/OutputView.kt diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt new file mode 100644 index 0000000..ad49237 --- /dev/null +++ b/src/main/kotlin/wordle/Application.kt @@ -0,0 +1,19 @@ +package wordle + +fun main() { + val game = Game(WordsReader.getWords()) + OutputView.printStartMessage() + doGame(game) + OutputView.printCount(game.count) + OutputView.printResults(game.results) +} + +private fun doGame(game: Game) { + val answer = Word(InputView.inputAnswer()) + game.match(answer) + if (game.isGameOver(answer)) { + return + } + OutputView.printResults(game.results) + doGame(game) +} diff --git a/src/main/kotlin/wordle/Game.kt b/src/main/kotlin/wordle/Game.kt index d8451f6..f3a347e 100644 --- a/src/main/kotlin/wordle/Game.kt +++ b/src/main/kotlin/wordle/Game.kt @@ -5,15 +5,18 @@ class Game(private val words: Words) { constructor(words: List) : this(Words(words)) var count: Int = 0 - private set + private set - fun isGameOver(): Boolean { - return count == 6 + var results: MutableList> = ArrayList() + private set + + fun isGameOver(answer: Word): Boolean { + return count == 6 || words.isCorrect(answer) } - fun match(answer: Word): List { + fun match(answer: Word) { count++ require(words.contains(answer)) { "λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€." } - return words.check(answer) + results.add(words.check(answer)) } } diff --git a/src/main/kotlin/wordle/InputView.kt b/src/main/kotlin/wordle/InputView.kt new file mode 100644 index 0000000..3641fbc --- /dev/null +++ b/src/main/kotlin/wordle/InputView.kt @@ -0,0 +1,9 @@ +package wordle + +object InputView { + + fun inputAnswer(): String { + println("정닡을 μž…λ ₯ν•΄ μ£Όμ„Έμš”.") + return readln() + } +} diff --git a/src/main/kotlin/wordle/OutputView.kt b/src/main/kotlin/wordle/OutputView.kt new file mode 100644 index 0000000..46fc851 --- /dev/null +++ b/src/main/kotlin/wordle/OutputView.kt @@ -0,0 +1,27 @@ +package wordle + +object OutputView { + + fun printStartMessage() { + println( + "WORDLE을 6번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.\n" + + "μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€." + ) + } + + fun printResults(results: List>) { + println() + results.forEach { printResult(it) } + println() + } + + private fun printResult(result: List) { + result.forEach { print(it.symbol) } + println() + } + + fun printCount(count: Int) { + println() + println("$count/6") + } +} From 9a24bc9af9e2239e2deb925f0cddbfd5813393f7 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sat, 14 May 2022 21:30:22 +0900 Subject: [PATCH 10/30] =?UTF-8?q?refactor:=20=ED=8C=A8=ED=82=A4=EC=A7=80?= =?UTF-8?q?=20=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 6 ++++++ src/main/kotlin/wordle/{ => domain}/Game.kt | 2 +- src/main/kotlin/wordle/{ => domain}/Tile.kt | 2 +- src/main/kotlin/wordle/{ => domain}/Word.kt | 2 +- src/main/kotlin/wordle/{ => domain}/Words.kt | 2 +- src/main/kotlin/wordle/{ => utils}/WordsReader.kt | 3 ++- src/main/kotlin/wordle/{ => view}/InputView.kt | 2 +- src/main/kotlin/wordle/{ => view}/OutputView.kt | 6 ++++-- src/test/kotlin/wordle/{ => domain}/GameTest.kt | 4 ++-- src/test/kotlin/wordle/{ => domain}/WordTest.kt | 2 +- src/test/kotlin/wordle/{ => domain}/WordsTest.kt | 2 +- src/test/kotlin/wordle/{ => utils}/WordsReaderTest.kt | 2 +- 12 files changed, 22 insertions(+), 13 deletions(-) rename src/main/kotlin/wordle/{ => domain}/Game.kt (95%) rename src/main/kotlin/wordle/{ => domain}/Tile.kt (80%) rename src/main/kotlin/wordle/{ => domain}/Word.kt (94%) rename src/main/kotlin/wordle/{ => domain}/Words.kt (98%) rename src/main/kotlin/wordle/{ => utils}/WordsReader.kt (83%) rename src/main/kotlin/wordle/{ => view}/InputView.kt (87%) rename src/main/kotlin/wordle/{ => view}/OutputView.kt (79%) rename src/test/kotlin/wordle/{ => domain}/GameTest.kt (90%) rename src/test/kotlin/wordle/{ => domain}/WordTest.kt (98%) rename src/test/kotlin/wordle/{ => domain}/WordsTest.kt (97%) rename src/test/kotlin/wordle/{ => utils}/WordsReaderTest.kt (92%) diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt index ad49237..84ed342 100644 --- a/src/main/kotlin/wordle/Application.kt +++ b/src/main/kotlin/wordle/Application.kt @@ -1,5 +1,11 @@ package wordle +import wordle.domain.Game +import wordle.domain.Word +import wordle.utils.WordsReader +import wordle.view.InputView +import wordle.view.OutputView + fun main() { val game = Game(WordsReader.getWords()) OutputView.printStartMessage() diff --git a/src/main/kotlin/wordle/Game.kt b/src/main/kotlin/wordle/domain/Game.kt similarity index 95% rename from src/main/kotlin/wordle/Game.kt rename to src/main/kotlin/wordle/domain/Game.kt index f3a347e..eea40a3 100644 --- a/src/main/kotlin/wordle/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain class Game(private val words: Words) { diff --git a/src/main/kotlin/wordle/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt similarity index 80% rename from src/main/kotlin/wordle/Tile.kt rename to src/main/kotlin/wordle/domain/Tile.kt index 3ca485f..7a54096 100644 --- a/src/main/kotlin/wordle/Tile.kt +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain enum class Tile(val symbol: String) { diff --git a/src/main/kotlin/wordle/Word.kt b/src/main/kotlin/wordle/domain/Word.kt similarity index 94% rename from src/main/kotlin/wordle/Word.kt rename to src/main/kotlin/wordle/domain/Word.kt index 9affdfd..30c4194 100644 --- a/src/main/kotlin/wordle/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain data class Word(val value: String) { diff --git a/src/main/kotlin/wordle/Words.kt b/src/main/kotlin/wordle/domain/Words.kt similarity index 98% rename from src/main/kotlin/wordle/Words.kt rename to src/main/kotlin/wordle/domain/Words.kt index 9dc6993..96c62db 100644 --- a/src/main/kotlin/wordle/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain import java.time.LocalDate import java.time.temporal.ChronoUnit diff --git a/src/main/kotlin/wordle/WordsReader.kt b/src/main/kotlin/wordle/utils/WordsReader.kt similarity index 83% rename from src/main/kotlin/wordle/WordsReader.kt rename to src/main/kotlin/wordle/utils/WordsReader.kt index dbdb214..9ed5274 100644 --- a/src/main/kotlin/wordle/WordsReader.kt +++ b/src/main/kotlin/wordle/utils/WordsReader.kt @@ -1,5 +1,6 @@ -package wordle +package wordle.utils +import wordle.domain.Word import java.io.FileReader object WordsReader { diff --git a/src/main/kotlin/wordle/InputView.kt b/src/main/kotlin/wordle/view/InputView.kt similarity index 87% rename from src/main/kotlin/wordle/InputView.kt rename to src/main/kotlin/wordle/view/InputView.kt index 3641fbc..968eaa8 100644 --- a/src/main/kotlin/wordle/InputView.kt +++ b/src/main/kotlin/wordle/view/InputView.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.view object InputView { diff --git a/src/main/kotlin/wordle/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt similarity index 79% rename from src/main/kotlin/wordle/OutputView.kt rename to src/main/kotlin/wordle/view/OutputView.kt index 46fc851..9e3d7ce 100644 --- a/src/main/kotlin/wordle/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -1,11 +1,13 @@ -package wordle +package wordle.view + +import wordle.domain.Tile object OutputView { fun printStartMessage() { println( "WORDLE을 6번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.\n" + - "μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€." + "μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€." ) } diff --git a/src/test/kotlin/wordle/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt similarity index 90% rename from src/test/kotlin/wordle/GameTest.kt rename to src/test/kotlin/wordle/domain/GameTest.kt index 855704e..5e03b39 100644 --- a/src/test/kotlin/wordle/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe @@ -20,6 +20,6 @@ class GameTest { internal fun `κ²Œμž„ μ’…λ£Œμ—¬λΆ€λ₯Ό ν™•μΈν•œλ‹€`() { val game = Game(listOf(Word("apple"), Word("hello"), Word("spicy"))) repeat(6) { game.match(Word("apple")) } - game.isGameOver() shouldBe true + game.isGameOver(Word("apple")) shouldBe true } } diff --git a/src/test/kotlin/wordle/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt similarity index 98% rename from src/test/kotlin/wordle/WordTest.kt rename to src/test/kotlin/wordle/domain/WordTest.kt index 4433706..0e845ab 100644 --- a/src/test/kotlin/wordle/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain import io.kotest.assertions.throwables.shouldThrow import io.kotest.inspectors.forAll diff --git a/src/test/kotlin/wordle/WordsTest.kt b/src/test/kotlin/wordle/domain/WordsTest.kt similarity index 97% rename from src/test/kotlin/wordle/WordsTest.kt rename to src/test/kotlin/wordle/domain/WordsTest.kt index b51ce29..e9f9665 100644 --- a/src/test/kotlin/wordle/WordsTest.kt +++ b/src/test/kotlin/wordle/domain/WordsTest.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.domain import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test diff --git a/src/test/kotlin/wordle/WordsReaderTest.kt b/src/test/kotlin/wordle/utils/WordsReaderTest.kt similarity index 92% rename from src/test/kotlin/wordle/WordsReaderTest.kt rename to src/test/kotlin/wordle/utils/WordsReaderTest.kt index 96fe9de..eb17f20 100644 --- a/src/test/kotlin/wordle/WordsReaderTest.kt +++ b/src/test/kotlin/wordle/utils/WordsReaderTest.kt @@ -1,4 +1,4 @@ -package wordle +package wordle.utils import io.kotest.matchers.shouldBe import org.junit.jupiter.api.Test From 88c3d73aafc32caedde0a82824c90893ecb8175a Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sat, 14 May 2022 21:33:24 +0900 Subject: [PATCH 11/30] =?UTF-8?q?docs:=20=EA=B8=B0=EB=8A=A5=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c712185..2b0b089 100644 --- a/README.md +++ b/README.md @@ -10,18 +10,18 @@ ## πŸš€ κΈ°λŠ₯ μš”κ΅¬ 사항 -- [ ] μ‹œμž‘ 문ꡬλ₯Ό λ„μ›Œμ€€λ‹€. -- [ ] λ‹΅μ•ˆμ„ μž…λ ₯λ°›λŠ”λ‹€. +- [x] μ‹œμž‘ 문ꡬλ₯Ό λ„μ›Œμ€€λ‹€. +- [x] λ‹΅μ•ˆμ„ μž…λ ₯λ°›λŠ”λ‹€. - [x] λ‹΅μ•ˆμ€ 5κΈ€μžμ—¬μ•Ό ν•œλ‹€. - λ‹΅μ•ˆμ€ `words.txt` μ•ˆμ— μ‘΄μž¬ν•˜λŠ” 단어여야 ν•œλ‹€. -- [ ] μ •λ‹΅κ³Ό λ‹΅μ•ˆμ„ λΉ„κ΅ν•˜μ—¬ κ²°κ³Όλ₯Ό νƒ€μΌλ‘œ ν‘œν˜„ν•œλ‹€. +- [x] μ •λ‹΅κ³Ό λ‹΅μ•ˆμ„ λΉ„κ΅ν•˜μ—¬ κ²°κ³Όλ₯Ό νƒ€μΌλ‘œ ν‘œν˜„ν•œλ‹€. - λ§žλŠ” κΈ€μžλŠ” μ΄ˆλ‘μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. - μœ„μΉ˜κ°€ 틀리면 λ…Έλž€μƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. - 정닡에 μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” κΈ€μžλ©΄ νšŒμƒ‰μœΌλ‘œ ν‘œν˜„ν•œλ‹€. - 두 개의 λ™μΌν•œ 문자λ₯Ό μž…λ ₯ν•˜κ³  그쀑 ν•˜λ‚˜κ°€ νšŒμƒ‰μœΌλ‘œ ν‘œμ‹œλ˜λ©΄ ν•΄λ‹Ή 문자 쀑 ν•˜λ‚˜λ§Œ μ΅œμ’… 단어에 λ‚˜νƒ€λ‚œλ‹€. - [x] 정닡은 맀일 바뀐닀. - [x] `words.txt` μ•ˆμ˜ ((ν˜„μž¬ λ‚ μ§œ - 2021λ…„ 6μ›” 19일) % λ°°μ—΄μ˜ 크기) 번째의 단어이닀. -- [ ] 정닡을 λ§žμ·„μ„ 경우 타일 ν‘œν˜„ 전에 λͺ‡ 번째 λ§Œμ— λ§žμ·„λŠ”μ§€ 좜λ ₯ν•œλ‹€. +- [x] 정닡을 λ§žμ·„μ„ 경우 타일 ν‘œν˜„ 전에 λͺ‡ 번째 λ§Œμ— λ§žμ·„λŠ”μ§€ 좜λ ₯ν•œλ‹€. 선풍적인 인기λ₯Ό λŒμ—ˆλ˜ μ˜μ–΄ 단어 λ§žμΆ”κΈ° κ²Œμž„μ΄λ‹€. From c44d184690d6ddc661a84f230268c2a5d2dd8939 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sat, 14 May 2022 21:37:20 +0900 Subject: [PATCH 12/30] =?UTF-8?q?refactor:=20println=20=EB=91=90=EA=B0=9C?= =?UTF-8?q?=EB=A1=9C=20=EB=82=98=EB=88=84=EC=96=B4=20=ED=91=9C=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/view/OutputView.kt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index 9e3d7ce..f1757c0 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -5,10 +5,8 @@ import wordle.domain.Tile object OutputView { fun printStartMessage() { - println( - "WORDLE을 6번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.\n" + - "μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€." - ) + println("WORDLE을 6번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.") + println("μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€.") } fun printResults(results: List>) { From 316ce9c85dbf22334d91e5860c32acef150b352b Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 15 May 2022 14:49:42 +0900 Subject: [PATCH 13/30] =?UTF-8?q?refactor:=20Word=EB=A5=BC=20=EC=86=8C?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EB=A1=9C=20=EC=9E=90=EB=8F=99=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B0=94=EA=BE=B8=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Word.kt | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 30c4194..d4491a9 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -1,13 +1,33 @@ package wordle.domain -data class Word(val value: String) { +private const val WORD_SIZE = 5 + +class Word(_value: String) { + + val value: String = _value.lowercase() init { - require(value.length == 5) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } + require(value.length == WORD_SIZE) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } require(Regex("[a-zA-Z]*").matches(value)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } } fun isSameChar(other: Word, index: Int): Boolean { return this.value[index] == other.value[index] } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as Word + + if (value != other.value) return false + + return true + } + + override fun hashCode(): Int { + return value.hashCode() + } + } From 787cc36289bd21d34189c7888bd35d918213aa68 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 15 May 2022 14:50:27 +0900 Subject: [PATCH 14/30] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=20=EC=83=81=EC=88=98=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Game.kt | 4 +++- src/main/kotlin/wordle/domain/Words.kt | 11 +++++++---- src/main/kotlin/wordle/utils/WordsReader.kt | 5 +++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index eea40a3..a1922f4 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,5 +1,7 @@ package wordle.domain +private const val TOTAL_ROUNDS_NUM = 6 + class Game(private val words: Words) { constructor(words: List) : this(Words(words)) @@ -11,7 +13,7 @@ class Game(private val words: Words) { private set fun isGameOver(answer: Word): Boolean { - return count == 6 || words.isCorrect(answer) + return count >= TOTAL_ROUNDS_NUM || words.isCorrect(answer) } fun match(answer: Word) { diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index 96c62db..8be3236 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -8,10 +8,13 @@ class Words(private val values: List) { private val answer: Word = findAnswer() private var answerMap: MutableMap = HashMap() + companion object { + private val STANDARD_DATE = LocalDate.of(2021, 6, 19) + } + private fun findAnswer(): Word { - val date: LocalDate = LocalDate.now() - val standardDate: LocalDate = LocalDate.of(2021, 6, 19) - val days: Int = ChronoUnit.DAYS.between(standardDate, date).toInt() + val nowDate: LocalDate = LocalDate.now() + val days: Int = ChronoUnit.DAYS.between(STANDARD_DATE, nowDate).toInt() return values[days % values.size] } @@ -25,7 +28,7 @@ class Words(private val values: List) { fun check(word: Word): List { answerMap = initAnswerMap() - val result: ArrayList = ArrayList() + val result: MutableList = ArrayList() repeat(5) { result.add(Tile.GRAY) } repeat(5) { i -> result[i] = findTileBySameCheck(word, i) } diff --git a/src/main/kotlin/wordle/utils/WordsReader.kt b/src/main/kotlin/wordle/utils/WordsReader.kt index 9ed5274..aee49b2 100644 --- a/src/main/kotlin/wordle/utils/WordsReader.kt +++ b/src/main/kotlin/wordle/utils/WordsReader.kt @@ -3,11 +3,12 @@ package wordle.utils import wordle.domain.Word import java.io.FileReader +private const val WORDS_PATH = "src/main/resources/words.txt" + object WordsReader { fun getWords(): List { - val path = "src/main/resources/words.txt" - val reader = FileReader(path) + val reader = FileReader(WORDS_PATH) return reader.readLines().map { Word(it) } } } From 6c159c8020129e86e2fc6e752cf4c76b4e7f5201 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 15 May 2022 14:50:56 +0900 Subject: [PATCH 15/30] =?UTF-8?q?style:=20enum=20=ED=91=9C=EA=B8=B0?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Tile.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt index 7a54096..d59fc58 100644 --- a/src/main/kotlin/wordle/domain/Tile.kt +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -2,5 +2,7 @@ package wordle.domain enum class Tile(val symbol: String) { - YELLOW("🟨"), GREEN("🟩"), GRAY("⬜") + YELLOW("🟨"), + GREEN("🟩"), + GRAY("⬜") } From 14570c89b539f400dbb95defecd2910bfd141ae2 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 15 May 2022 14:56:48 +0900 Subject: [PATCH 16/30] =?UTF-8?q?style:=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EB=82=B4=20=EB=B8=94=EB=A1=9D=20=EC=88=9C=EC=84=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Game.kt | 4 ++-- src/main/kotlin/wordle/domain/Words.kt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index a1922f4..4330cbe 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -4,14 +4,14 @@ private const val TOTAL_ROUNDS_NUM = 6 class Game(private val words: Words) { - constructor(words: List) : this(Words(words)) - var count: Int = 0 private set var results: MutableList> = ArrayList() private set + constructor(words: List) : this(Words(words)) + fun isGameOver(answer: Word): Boolean { return count >= TOTAL_ROUNDS_NUM || words.isCorrect(answer) } diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index 8be3236..8ca609a 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -8,10 +8,6 @@ class Words(private val values: List) { private val answer: Word = findAnswer() private var answerMap: MutableMap = HashMap() - companion object { - private val STANDARD_DATE = LocalDate.of(2021, 6, 19) - } - private fun findAnswer(): Word { val nowDate: LocalDate = LocalDate.now() val days: Int = ChronoUnit.DAYS.between(STANDARD_DATE, nowDate).toInt() @@ -70,4 +66,8 @@ class Words(private val values: List) { answerMap.remove(key) } } + + companion object { + private val STANDARD_DATE = LocalDate.of(2021, 6, 19) + } } From c671c8f9329ec29e88ef176500f2203d9ec906f9 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 17 May 2022 00:44:02 +0900 Subject: [PATCH 17/30] =?UTF-8?q?fix:=20count=20=EC=A6=9D=EA=B0=80=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Game.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 4330cbe..f5e6a91 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -17,8 +17,8 @@ class Game(private val words: Words) { } fun match(answer: Word) { - count++ require(words.contains(answer)) { "λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€." } results.add(words.check(answer)) + count++ } } From e0c048589f4438a7384be69c1b3df5826ce99828 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 17 May 2022 00:47:29 +0900 Subject: [PATCH 18/30] =?UTF-8?q?style:=20ktlintCheck=20=EC=88=98=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Word.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index d4491a9..4c46480 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -29,5 +29,4 @@ class Word(_value: String) { override fun hashCode(): Int { return value.hashCode() } - } From 0223a017cba951149dc6ce21282188b9259d30a5 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 17 May 2022 00:52:09 +0900 Subject: [PATCH 19/30] =?UTF-8?q?refactor:=20=EC=B4=9D=20=EB=9D=BC?= =?UTF-8?q?=EC=9A=B4=EB=93=9C=20=EC=88=98=EB=A5=BC=20=EC=99=B8=EB=B6=80?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=A3=BC=EC=9E=85=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=9D=98=20printStartMessage=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20it=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 3 ++- src/main/kotlin/wordle/domain/Game.kt | 2 +- src/main/kotlin/wordle/domain/Words.kt | 4 ++-- src/main/kotlin/wordle/view/OutputView.kt | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt index 84ed342..5261451 100644 --- a/src/main/kotlin/wordle/Application.kt +++ b/src/main/kotlin/wordle/Application.kt @@ -1,6 +1,7 @@ package wordle import wordle.domain.Game +import wordle.domain.TOTAL_ROUNDS_NUM import wordle.domain.Word import wordle.utils.WordsReader import wordle.view.InputView @@ -8,7 +9,7 @@ import wordle.view.OutputView fun main() { val game = Game(WordsReader.getWords()) - OutputView.printStartMessage() + OutputView.printStartMessage(TOTAL_ROUNDS_NUM) doGame(game) OutputView.printCount(game.count) OutputView.printResults(game.results) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index f5e6a91..1127bd2 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,6 +1,6 @@ package wordle.domain -private const val TOTAL_ROUNDS_NUM = 6 +const val TOTAL_ROUNDS_NUM = 6 class Game(private val words: Words) { diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index 8ca609a..b8ac22f 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -27,8 +27,8 @@ class Words(private val values: List) { val result: MutableList = ArrayList() repeat(5) { result.add(Tile.GRAY) } - repeat(5) { i -> result[i] = findTileBySameCheck(word, i) } - repeat(5) { i -> result[i] = findTileByContainCheck(result, word, i) } + repeat(5) { result[it] = findTileBySameCheck(word, it) } + repeat(5) { result[it] = findTileByContainCheck(result, word, it) } return result } diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index f1757c0..6fd55a3 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -4,8 +4,8 @@ import wordle.domain.Tile object OutputView { - fun printStartMessage() { - println("WORDLE을 6번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.") + fun printStartMessage(round: Int) { + println("WORDLE을 {$round}번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.") println("μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€.") } From ba60252c75c53039e30b2f9f6e76423b74a8f53d Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 17 May 2022 01:08:24 +0900 Subject: [PATCH 20/30] =?UTF-8?q?test:=20shouldHaveMessage=20=ED=99=9C?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/wordle/domain/GameTest.kt | 6 +++--- src/test/kotlin/wordle/domain/WordTest.kt | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt index 5e03b39..a93542b 100644 --- a/src/test/kotlin/wordle/domain/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -2,6 +2,7 @@ package wordle.domain import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage import org.junit.jupiter.api.Test class GameTest { @@ -10,10 +11,9 @@ class GameTest { fun `λ“±λ‘λœ 단어가 μ•„λ‹Œ 경우 μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { val game = Game(listOf(Word("apple"), Word("hello"), Word("spicy"))) - val exception = shouldThrow { + shouldThrow { game.match(Word("spell")) - } - exception.message shouldBe "λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€." + }.shouldHaveMessage("λ“±λ‘λœ 단어가 μ•„λ‹™λ‹ˆλ‹€.") } @Test diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index 0e845ab..ac8760d 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -3,25 +3,24 @@ package wordle.domain import io.kotest.assertions.throwables.shouldThrow import io.kotest.inspectors.forAll import io.kotest.matchers.shouldBe +import io.kotest.matchers.throwable.shouldHaveMessage import org.junit.jupiter.api.Test class WordTest { @Test fun `5κΈ€μžκ°€ μ•„λ‹Œ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { - val exception = shouldThrow { + shouldThrow { Word("test") - } - exception.message shouldBe "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." + }.shouldHaveMessage("λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€.") } @Test fun `μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžκ°€ ν¬ν•¨λœ wordλ₯Ό μƒμ„±ν•˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€`() { listOf("ap pl", "apν”Όle").forAll { - val exception = shouldThrow { + shouldThrow { Word(it) - } - exception.message shouldBe "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." + }.shouldHaveMessage("단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€.") } } From 0fe17d07aa372ab953d412a97ca7941a5c9947e7 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Wed, 18 May 2022 17:45:51 +0900 Subject: [PATCH 21/30] =?UTF-8?q?test:=20DslTest=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/study/DslTest.kt | 109 +++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/test/kotlin/study/DslTest.kt diff --git a/src/test/kotlin/study/DslTest.kt b/src/test/kotlin/study/DslTest.kt new file mode 100644 index 0000000..36bee99 --- /dev/null +++ b/src/test/kotlin/study/DslTest.kt @@ -0,0 +1,109 @@ +package study + +import io.kotest.assertions.assertSoftly +import io.kotest.matchers.collections.shouldContainExactly +import io.kotest.matchers.collections.shouldHaveSize +import io.kotest.matchers.shouldBe +import org.junit.jupiter.api.Test + +/* +introduce { + name("λ°•μž¬μ„±") + company("μš°μ•„ν•œν˜•μ œλ“€") + skills { + soft ("A passion for problem solving") + soft ("Good communication skills") + hard ("Kotlin") + } + languages { + "Korean" level 5 + "English" level 3 + } +} + */ +class DslTest { + + @Test + fun `μžκΈ°μ†Œκ°œ ν•¨μˆ˜ 버전`() { + val person = introduce { + name("κΉ€λ²”μˆ˜") + company("μš°μ•„ν•œν˜•μ œλ“€") + skills { + soft("μ½”ν‹€λ¦°") + soft("μžλ°”") + hard("μš΄λ™") + } + languages { + "Korean" level 100 + "English" level 10 + "Japanese" level 0 + } + } + + assertSoftly(person) { + it.name shouldBe "κΉ€λ²”μˆ˜" + it.company shouldBe "μš°μ•„ν•œν˜•μ œλ“€" + it.skills.soft shouldHaveSize 2 + it.skills.hard shouldHaveSize 1 + it.languages.values shouldHaveSize 3 + it.languages.values shouldContainExactly listOf( + Language("Korean", 100), + Language("English", 10), + Language("Japanese", 0) + ) + } + } +} + +fun introduce(builder: PersonBuilder.() -> Unit): Person { + return PersonBuilder().apply(builder).build() +} + +class PersonBuilder { + lateinit var name: String + lateinit var company: String + lateinit var skills: Skills + lateinit var languages: Languages + + fun name(value: String) { + name = value + } + + fun company(value: String) { + company = value + } + + fun skills(builder: Skills.() -> Unit) { + skills = Skills(mutableListOf(), mutableListOf()).apply(builder) + } + + fun languages(builder: Languages.() -> Unit) { + languages = Languages(mutableListOf()).apply(builder) + } + + fun build(): Person = Person(name, company, skills, languages) +} + +data class Person(val name: String, val company: String, val skills: Skills, val languages: Languages) + +class Skills(val soft: MutableList, val hard: MutableList) { + fun soft(value: String) { + soft.add(value) + } + + fun hard(value: String) { + hard.add(value) + } +} + +class Languages(val values: MutableList) { + + infix fun String.level(level: Int) { + values.add(Language(this, level)) + } +} + +data class Language(val value: String, val level: Int) + + + From fa76e293d6aebb36ef6f73e20bf57bf5e6b553c0 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Wed, 25 May 2022 15:35:47 +0900 Subject: [PATCH 22/30] =?UTF-8?q?style:=20ktlint=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/study/DslTest.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/test/kotlin/study/DslTest.kt b/src/test/kotlin/study/DslTest.kt index 36bee99..0774b44 100644 --- a/src/test/kotlin/study/DslTest.kt +++ b/src/test/kotlin/study/DslTest.kt @@ -104,6 +104,3 @@ class Languages(val values: MutableList) { } data class Language(val value: String, val level: Int) - - - From 5f11353c20fed0b8faceb7f4c6bd06b0cb23ada0 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Wed, 25 May 2022 15:36:28 +0900 Subject: [PATCH 23/30] =?UTF-8?q?refactor:=20Words=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81=20(=20findAnswer,=20answerMap=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8=20)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Words.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index b8ac22f..e3692ed 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -1,16 +1,14 @@ package wordle.domain import java.time.LocalDate -import java.time.temporal.ChronoUnit class Words(private val values: List) { private val answer: Word = findAnswer() - private var answerMap: MutableMap = HashMap() + private var answerMap: MutableMap = mutableMapOf() private fun findAnswer(): Word { - val nowDate: LocalDate = LocalDate.now() - val days: Int = ChronoUnit.DAYS.between(STANDARD_DATE, nowDate).toInt() + val days = TODAY.compareTo(STANDARD_DATE) return values[days % values.size] } @@ -24,7 +22,7 @@ class Words(private val values: List) { fun check(word: Word): List { answerMap = initAnswerMap() - val result: MutableList = ArrayList() + val result: MutableList = mutableListOf() repeat(5) { result.add(Tile.GRAY) } repeat(5) { result[it] = findTileBySameCheck(word, it) } @@ -68,6 +66,7 @@ class Words(private val values: List) { } companion object { + private val TODAY = LocalDate.now() private val STANDARD_DATE = LocalDate.of(2021, 6, 19) } } From a06696bb3a7b35271516a0df6eee37c824fc9295 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Wed, 25 May 2022 16:48:24 +0900 Subject: [PATCH 24/30] =?UTF-8?q?refactor:=20Words=20=EB=A6=AC=ED=8C=A9?= =?UTF-8?q?=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Words.kt | 47 +++++++++++++------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index e3692ed..d9ba34b 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -22,40 +22,40 @@ class Words(private val values: List) { fun check(word: Word): List { answerMap = initAnswerMap() - val result: MutableList = mutableListOf() - repeat(5) { result.add(Tile.GRAY) } - - repeat(5) { result[it] = findTileBySameCheck(word, it) } - repeat(5) { result[it] = findTileByContainCheck(result, word, it) } - return result + return DEFAULT_TILES.markGreen(word).markYellow(word) } private fun initAnswerMap(): MutableMap { - val answerMap: MutableMap = HashMap() - answer.value.forEach { - answerMap.putIfAbsent(it, 0) - answerMap.computeIfPresent(it) { _, v -> v + 1 } - } - return answerMap + return answer.value + .groupBy { it } + .mapValues { it.value.count() } + .toMutableMap() + } + + private fun List.markGreen(word: Word): List { + return List(size) { index -> grayOrGreen(word, index) } } - private fun findTileBySameCheck(word: Word, index: Int): Tile { - if (answer.isSameChar(word, index)) { + private fun grayOrGreen(word: Word, index: Int): Tile { + return if (answer.isSameChar(word, index)) { calculateAnswerMap(word.value[index]) - return Tile.GREEN + Tile.GREEN + } else { + Tile.GRAY } - return Tile.GRAY } - private fun findTileByContainCheck(result: List, word: Word, index: Int): Tile { - if (result[index] == Tile.GREEN) { - return Tile.GREEN - } - if (answerMap.keys.contains(word.value[index])) { + private fun List.markYellow(word: Word): List { + return mapIndexed { index, tile -> existOrYellow(tile, word, index) } + } + + private fun existOrYellow(tile: Tile, word: Word, index: Int): Tile { + return if (tile != Tile.GREEN && answerMap.containsKey(word.value[index])) { calculateAnswerMap(word.value[index]) - return Tile.YELLOW + Tile.YELLOW + } else { + tile } - return Tile.GRAY } private fun calculateAnswerMap(key: Char) { @@ -68,5 +68,6 @@ class Words(private val values: List) { companion object { private val TODAY = LocalDate.now() private val STANDARD_DATE = LocalDate.of(2021, 6, 19) + private val DEFAULT_TILES = List(5) { Tile.GRAY } } } From 8f373bd8f5ffcfc3693499e18db553c99ab32856 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 29 May 2022 21:34:59 +0900 Subject: [PATCH 25/30] =?UTF-8?q?refactor:=20printCount=20round=20?= =?UTF-8?q?=EC=9E=85=EB=A0=A5=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 2 +- src/main/kotlin/wordle/view/OutputView.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt index 5261451..c151734 100644 --- a/src/main/kotlin/wordle/Application.kt +++ b/src/main/kotlin/wordle/Application.kt @@ -11,7 +11,7 @@ fun main() { val game = Game(WordsReader.getWords()) OutputView.printStartMessage(TOTAL_ROUNDS_NUM) doGame(game) - OutputView.printCount(game.count) + OutputView.printCount(game.count, TOTAL_ROUNDS_NUM) OutputView.printResults(game.results) } diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index 6fd55a3..f91e7ce 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -20,8 +20,8 @@ object OutputView { println() } - fun printCount(count: Int) { + fun printCount(count: Int, round: Int) { println() - println("$count/6") + println("$count/$round") } } From 50c25d1f7a1bf85d00473655b965079092f4b26b Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 29 May 2022 22:42:36 +0900 Subject: [PATCH 26/30] =?UTF-8?q?refactor:=20Word=20=ED=99=95=EC=9E=A5?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Word.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 4c46480..52aa34a 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -7,14 +7,22 @@ class Word(_value: String) { val value: String = _value.lowercase() init { - require(value.length == WORD_SIZE) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } - require(Regex("[a-zA-Z]*").matches(value)) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } + require(value.isRightSize()) { "λ‹¨μ–΄μ˜ κΈΈμ΄λŠ” 5κΈ€μžμ—¬μ•Ό ν•©λ‹ˆλ‹€." } + require(value.isAlphabet()) { "단어에 μ˜μ–΄κ°€ μ•„λ‹Œ κΈ€μžλ‚˜ 곡백이 포함될 수 μ—†μŠ΅λ‹ˆλ‹€." } } fun isSameChar(other: Word, index: Int): Boolean { return this.value[index] == other.value[index] } + private fun String.isRightSize(): Boolean { + return this.length == WORD_SIZE + } + + private fun String.isAlphabet(): Boolean { + return Regex("[a-zA-Z]*").matches(this) + } + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false From 1d22723504ab3226f4146d87d8b981936dd219c1 Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Sun, 29 May 2022 22:47:28 +0900 Subject: [PATCH 27/30] =?UTF-8?q?refactor:=20Regex=EB=A5=BC=20=EB=AF=B8?= =?UTF-8?q?=EB=A6=AC=20=EC=83=9D=EC=84=B1=ED=95=B4=EB=86=93=EA=B3=A0=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EB=8A=94=20=EB=8A=90=EB=82=8C?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Word.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 52aa34a..942020e 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -1,6 +1,7 @@ package wordle.domain private const val WORD_SIZE = 5 +private val ALPHABET_REGEX = Regex("[a-zA-Z]*") class Word(_value: String) { @@ -20,7 +21,7 @@ class Word(_value: String) { } private fun String.isAlphabet(): Boolean { - return Regex("[a-zA-Z]*").matches(this) + return ALPHABET_REGEX.matches(this) } override fun equals(other: Any?): Boolean { From 6df3404718c6555b833bd36603ef3c12dff30c1a Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 31 May 2022 00:44:43 +0900 Subject: [PATCH 28/30] =?UTF-8?q?refactor:=20=EC=9E=AC=EA=B7=80=EB=AC=B8?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B3=A0=20while=EB=AC=B8?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 20 ++++++---------- src/main/kotlin/wordle/domain/Game.kt | 12 +++++++--- src/main/kotlin/wordle/view/OutputView.kt | 28 +++++++++++++++-------- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt index c151734..7ee0433 100644 --- a/src/main/kotlin/wordle/Application.kt +++ b/src/main/kotlin/wordle/Application.kt @@ -1,7 +1,6 @@ package wordle import wordle.domain.Game -import wordle.domain.TOTAL_ROUNDS_NUM import wordle.domain.Word import wordle.utils.WordsReader import wordle.view.InputView @@ -9,18 +8,13 @@ import wordle.view.OutputView fun main() { val game = Game(WordsReader.getWords()) - OutputView.printStartMessage(TOTAL_ROUNDS_NUM) - doGame(game) - OutputView.printCount(game.count, TOTAL_ROUNDS_NUM) - OutputView.printResults(game.results) -} + OutputView.printStartMessage(game) + var isOver = false -private fun doGame(game: Game) { - val answer = Word(InputView.inputAnswer()) - game.match(answer) - if (game.isGameOver(answer)) { - return + while (!isOver) { + val answer = Word(InputView.inputAnswer()) + game.match(answer) + isOver = game.isGameOver(answer) + OutputView.printResults(game, isOver) } - OutputView.printResults(game.results) - doGame(game) } diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 1127bd2..b70123e 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -2,7 +2,10 @@ package wordle.domain const val TOTAL_ROUNDS_NUM = 6 -class Game(private val words: Words) { +class Game( + private val words: Words, + val totalCount: Int = TOTAL_ROUNDS_NUM +) { var count: Int = 0 private set @@ -10,10 +13,13 @@ class Game(private val words: Words) { var results: MutableList> = ArrayList() private set - constructor(words: List) : this(Words(words)) + constructor( + words: List, + totalCount: Int = TOTAL_ROUNDS_NUM + ) : this(Words(words), totalCount) fun isGameOver(answer: Word): Boolean { - return count >= TOTAL_ROUNDS_NUM || words.isCorrect(answer) + return count >= totalCount || words.isCorrect(answer) } fun match(answer: Word) { diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index f91e7ce..5ad59e9 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -1,17 +1,23 @@ package wordle.view +import wordle.domain.Game import wordle.domain.Tile object OutputView { - fun printStartMessage(round: Int) { - println("WORDLE을 {$round}번 λ§Œμ— 맞좰 λ³΄μ„Έμš”.") - println("μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€.") - } + fun printStartMessage(game: Game) = println( + """ + |WORDLE을 ${game.totalCount}번 λ§Œμ— 맞좰 λ³΄μ„Έμš”. + |μ‹œλ„μ˜ κ²°κ³ΌλŠ” νƒ€μΌμ˜ 색 λ³€ν™”λ‘œ λ‚˜νƒ€λ‚©λ‹ˆλ‹€. + """.trimMargin() + ) - fun printResults(results: List>) { + fun printResults(game: Game, isGameOver: Boolean) { + if (isGameOver) { + printCount(game.count, game.totalCount) + } println() - results.forEach { printResult(it) } + game.results.forEach { printResult(it) } println() } @@ -20,8 +26,10 @@ object OutputView { println() } - fun printCount(count: Int, round: Int) { - println() - println("$count/$round") - } + private fun printCount(count: Int, totalRound: Int) = println( + """ + | + |$count/$totalRound + """.trimMargin() + ) } From 37d95d85591b53326044a50b231077c803842d5b Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 31 May 2022 00:59:41 +0900 Subject: [PATCH 29/30] =?UTF-8?q?refactor:=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=EC=8B=9C=20=EB=8B=A4=EC=8B=9C=20=EC=9E=85?= =?UTF-8?q?=EB=A0=A5=EB=B0=9B=EC=9D=84=20=EC=88=98=20=EC=9E=88=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/Application.kt | 14 +++++++++++++- src/main/kotlin/wordle/domain/Game.kt | 2 +- src/main/kotlin/wordle/view/OutputView.kt | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/wordle/Application.kt b/src/main/kotlin/wordle/Application.kt index 7ee0433..17d3834 100644 --- a/src/main/kotlin/wordle/Application.kt +++ b/src/main/kotlin/wordle/Application.kt @@ -9,8 +9,20 @@ import wordle.view.OutputView fun main() { val game = Game(WordsReader.getWords()) OutputView.printStartMessage(game) - var isOver = false + doGame(game) +} + +private fun doGame(game: Game) { + try { + submitAnswer(game) + } catch (exception: IllegalArgumentException) { + OutputView.printErrorMessage(exception) + doGame(game) + } +} +private fun submitAnswer(game: Game) { + var isOver = false while (!isOver) { val answer = Word(InputView.inputAnswer()) game.match(answer) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index b70123e..3bfd11a 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,6 +1,6 @@ package wordle.domain -const val TOTAL_ROUNDS_NUM = 6 +private const val TOTAL_ROUNDS_NUM = 6 class Game( private val words: Words, diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index 5ad59e9..1e96c71 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -32,4 +32,8 @@ object OutputView { |$count/$totalRound """.trimMargin() ) + + fun printErrorMessage(exception: RuntimeException) { + println(exception.message) + } } From ef7eab09f1e5dd0c36616782700ed0a05d3a1ead Mon Sep 17 00:00:00 2001 From: BeomsooKim Date: Tue, 31 May 2022 01:18:44 +0900 Subject: [PATCH 30/30] =?UTF-8?q?refactor:=20Tile=20=EC=B6=9C=EB=A0=A5?= =?UTF-8?q?=EA=B3=BC=20=EA=B4=80=EB=A0=A8=EB=90=9C=20=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=EB=A5=BC=20View=EB=A1=9C=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Tile.kt | 6 ++---- src/main/kotlin/wordle/view/OutputView.kt | 10 +++++++++- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt index d59fc58..8dc8143 100644 --- a/src/main/kotlin/wordle/domain/Tile.kt +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -1,8 +1,6 @@ package wordle.domain -enum class Tile(val symbol: String) { +enum class Tile() { - YELLOW("🟨"), - GREEN("🟩"), - GRAY("⬜") + YELLOW, GREEN, GRAY } diff --git a/src/main/kotlin/wordle/view/OutputView.kt b/src/main/kotlin/wordle/view/OutputView.kt index 1e96c71..cb4248a 100644 --- a/src/main/kotlin/wordle/view/OutputView.kt +++ b/src/main/kotlin/wordle/view/OutputView.kt @@ -22,7 +22,7 @@ object OutputView { } private fun printResult(result: List) { - result.forEach { print(it.symbol) } + result.forEach { printTile(it) } println() } @@ -36,4 +36,12 @@ object OutputView { fun printErrorMessage(exception: RuntimeException) { println(exception.message) } + + private fun printTile(tile: Tile) { + when (tile) { + Tile.GREEN -> print("🟩") + Tile.YELLOW -> print("🟨") + Tile.GRAY -> print("⬜") + } + } }