From 5d8479e37d2e6ced3d3972a287fed87467f6775d Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 21:03:05 +0900 Subject: [PATCH 01/55] =?UTF-8?q?doc:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=EC=84=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index b4b1377..70e92b2 100644 --- a/README.md +++ b/README.md @@ -20,10 +20,37 @@ - 정답과 답안은 `words.txt`에 존재하는 단어여야 한다. - 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다. + +### 기능 명세서 +- [ ] 단어 + - [ ] 단어는 5글자이어야한다. + - [ ] 단어는 알파벳이어야한다. + - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다. +- [ ] 타일 + - [ ] 타일은 30개이다. + - [ ] 타일은 노란색, 초록색, 회색을 가진다. +- [ ] 매칭 + - [ ] 답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다. + - [ ] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다. + - [ ] 답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다. + - [ ] 답안과 정답의 단어 중 앞서 한 단어가 판별이 난 경우 뒤에 있는 동일한 단어는 판별되지 않는다. + - (예 - 정답이 ROYAL인 경우 MOONY를 입력하면 회초회회노 가 결과로 나온다) +- [ ] 게임 + - [ ] 6x5 타일로 이루어져 있다. + - [ ] 5글자 단어를 6번동안 추측할 수 있다. + - [ ] 5글자의 모든 위치와 스펠을 맞추는 경우 게임에 승리한다. + - [ ] 6번의 기회동안 맞추지 못하면 패배한다. + - [ ] 종료 시 시도한 횟수와 총 횟수를 보여준다. + - [ ] 결과를 누적해서 보여준다. + - [ ] 정답이 words.txt 에 없는 것인 경우 재입력을 받는다. + - [ ] 정답과 답안(단어)는 words.txt 안에 있는 것이어야 한다. + + ### 입출력 요구 사항 #### 실행 결과 예시 + ``` WORDLE을 6번 만에 맞춰 보세요. 시도의 결과는 타일의 색 변화로 나타납니다. From eb31a9d0d85659c08e2804a4415a530818872915 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 22:53:44 +0900 Subject: [PATCH 02/55] =?UTF-8?q?feat:=20Word=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EA=B8=B0=EB=8A=A5=EB=AA=85=EC=84=B8=EC=84=9C?= =?UTF-8?q?=EC=9D=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=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/domain/Word.kt | 16 ++++++++++ src/test/kotlin/wordle/domain/WordTest.kt | 38 +++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Word.kt create mode 100644 src/test/kotlin/wordle/domain/WordTest.kt diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt new file mode 100644 index 0000000..92ae1b4 --- /dev/null +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -0,0 +1,16 @@ +package wordle.domain + +data class Word(val value:String) { + + init { + require(value.length == WORD_SIZE && regex.matches(value)) { + throw IllegalArgumentException(WRONG_WORD_SIZE_MESSAGE) + } + } + + companion object { + const val WORD_SIZE = 5 + const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" + val regex = Regex("^[a-zA-Z]*$") + } +} \ No newline at end of file diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt new file mode 100644 index 0000000..fded99e --- /dev/null +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -0,0 +1,38 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource + +class WordTest { + + @Test + fun `단어를 만들 수 있다`() { + val givenWord = "value" + val word = Word(givenWord) + + assertThat(word.value).isEqualTo(givenWord) + } + + @ParameterizedTest + @ValueSource(strings = ["abc", "abcdef"]) + fun `단어는 5글자가 아닌 경우 예외를 던진다`(wrongWord: String) { + val message = assertThrows { + Word(wrongWord) + }.message + + assertThat(message).isEqualTo("5글자여야합니다") + } + + @Test + fun `단어는 알파벳이어야한다`() { + val givenWrongWord = "a1234" + val message = assertThrows { + Word(givenWrongWord) + }.message + + assertThat(message).isEqualTo("5글자여야합니다") + } +} \ No newline at end of file From f2afbd3bb766054f34c05c56235654791e9a853f Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 22:53:59 +0900 Subject: [PATCH 03/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20gitkeep=20=ED=8C=8C=EC=9D=BC=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/.gitkeep | 0 src/test/kotlin/.gitkeep | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/kotlin/.gitkeep delete mode 100644 src/test/kotlin/.gitkeep diff --git a/src/main/kotlin/.gitkeep b/src/main/kotlin/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/kotlin/.gitkeep b/src/test/kotlin/.gitkeep deleted file mode 100644 index e69de29..0000000 From 5bab906d6896068cddb915af6c76a1a3fd6b9af7 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 22:54:10 +0900 Subject: [PATCH 04/55] =?UTF-8?q?doc:=20=EA=B5=AC=ED=98=84=ED=95=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 70e92b2..09ecc23 100644 --- a/README.md +++ b/README.md @@ -23,8 +23,9 @@ ### 기능 명세서 - [ ] 단어 - - [ ] 단어는 5글자이어야한다. - - [ ] 단어는 알파벳이어야한다. + - [X] 단어를 만들 수 있다. + - [X] 단어는 5글자가 아닌 경우 예외를 던진다. + - [X] 단어는 알파벳이어야한다. - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다. - [ ] 타일 - [ ] 타일은 30개이다. From 58b435b60c3f709a4ba690d0cc1504a09651e1af Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 22:55:51 +0900 Subject: [PATCH 05/55] =?UTF-8?q?refactor:=20klint=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A8=EB=B2=A4=EC=85=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 | 2 +- src/test/kotlin/wordle/domain/WordTest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 92ae1b4..088cd00 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -1,6 +1,6 @@ package wordle.domain -data class Word(val value:String) { +data class Word(val value: String) { init { require(value.length == WORD_SIZE && regex.matches(value)) { diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index fded99e..3c79029 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -35,4 +35,4 @@ class WordTest { assertThat(message).isEqualTo("5글자여야합니다") } -} \ No newline at end of file +} From 35852c30037c4a622db95a3c171782b9837d581e Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 23:22:18 +0900 Subject: [PATCH 06/55] =?UTF-8?q?feat:=20=ED=83=80=EC=9D=BC=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85=EC=84=B8?= =?UTF-8?q?=EC=84=9C=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=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/domain/Tile.kt | 7 +++++++ src/test/kotlin/wordle/domain/TileTest.kt | 20 ++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Tile.kt create mode 100644 src/test/kotlin/wordle/domain/TileTest.kt diff --git a/src/main/kotlin/wordle/domain/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt new file mode 100644 index 0000000..1ae1ba3 --- /dev/null +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -0,0 +1,7 @@ +package wordle.domain + +enum class Tile(val value: String) { + YELLOW("\uD83D\uDFE7"), + GREEN("\uD83D\uDFE9"), + GRAY("\uD83D\uDFE8"); +} diff --git a/src/test/kotlin/wordle/domain/TileTest.kt b/src/test/kotlin/wordle/domain/TileTest.kt new file mode 100644 index 0000000..1a3f8cc --- /dev/null +++ b/src/test/kotlin/wordle/domain/TileTest.kt @@ -0,0 +1,20 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource + +class TileTest { + + @Test + fun `타일은 노란색, 초록색, 회색을 가진다`() { + assertThat(Tile.values()).containsExactly(Tile.YELLOW, Tile.GREEN, Tile.GRAY) + } + + @ParameterizedTest + @CsvSource("GRAY, \uD83D\uDFE8", "GREEN, \uD83D\uDFE9", "YELLOW, \uD83D\uDFE7") + fun `흰색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다`(tile: Tile, color: String) { + assertThat(tile.value).isEqualTo(color) + } +} From 6fde073150cd5b0bf2759265ec45572087432c38 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 23:23:14 +0900 Subject: [PATCH 07/55] =?UTF-8?q?doc:=20=EA=B5=AC=ED=98=84=ED=95=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 09ecc23..aa05801 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다. - [ ] 타일 - [ ] 타일은 30개이다. - - [ ] 타일은 노란색, 초록색, 회색을 가진다. + - [X] 타일은 노란색, 초록색, 회색을 가진다. + - [X] 흰색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다. - [ ] 매칭 - [ ] 답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다. - [ ] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다. From 3bb816424ce7a4e84f6662fde1a1b5c90c08cc97 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Tue, 12 Apr 2022 23:23:27 +0900 Subject: [PATCH 08/55] =?UTF-8?q?refactor:=20klint=20=EC=97=90=20=EB=8C=80?= =?UTF-8?q?=ED=95=9C=20=EC=BB=A8=EB=B2=A4=EC=85=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 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 088cd00..0d1c97a 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -13,4 +13,4 @@ data class Word(val value: String) { const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" val regex = Regex("^[a-zA-Z]*$") } -} \ No newline at end of file +} From 6fc22882bee3b96272baed1aa3a4a4419862e4e9 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 00:11:21 +0900 Subject: [PATCH 09/55] =?UTF-8?q?refactor:=20=EB=8B=A8=EC=96=B4=EB=A5=BC?= =?UTF-8?q?=20=EB=B9=84=EA=B5=90=ED=95=98=EC=97=AC=20=ED=83=80=EC=9D=BC?= =?UTF-8?q?=EC=9D=84=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94=20WordMatcher?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=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/domain/WordMatcher.kt | 11 +++++++++++ src/test/kotlin/wordle/domain/WordMatcherTest.kt | 16 ++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/WordMatcher.kt create mode 100644 src/test/kotlin/wordle/domain/WordMatcherTest.kt diff --git a/src/main/kotlin/wordle/domain/WordMatcher.kt b/src/main/kotlin/wordle/domain/WordMatcher.kt new file mode 100644 index 0000000..57327cf --- /dev/null +++ b/src/main/kotlin/wordle/domain/WordMatcher.kt @@ -0,0 +1,11 @@ +package wordle.domain + +class WordMatcher(private val answer: Word) { + + fun match(alphabet: String, index: Int): Tile { + if (alphabet == answer.foundAlphabet(index)) { + return Tile.GREEN + } + return Tile.GRAY + } +} diff --git a/src/test/kotlin/wordle/domain/WordMatcherTest.kt b/src/test/kotlin/wordle/domain/WordMatcherTest.kt new file mode 100644 index 0000000..82fda40 --- /dev/null +++ b/src/test/kotlin/wordle/domain/WordMatcherTest.kt @@ -0,0 +1,16 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.CsvSource + +class WordMatcherTest { + + @ParameterizedTest + @CsvSource("i, 0", "n, 1", "t, 4") + fun `답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다`(alphabet: String, index: Int) { + val wordMatcher = WordMatcher(Word("input")) + + assertThat(wordMatcher.match(alphabet, index)).isEqualTo(Tile.GREEN) + } +} From 991380a77209112b30ab1a0ea514e2418b67ae92 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 00:12:39 +0900 Subject: [PATCH 10/55] =?UTF-8?q?refactor:=20Word=20=EB=82=B4=20=EC=9D=B8?= =?UTF-8?q?=EB=8D=B1=EC=8A=A4=20=EC=9C=84=EC=B9=98=EC=97=90=20=EB=8B=A8?= =?UTF-8?q?=EC=96=B4=EA=B0=80=20=EC=A1=B4=EC=9E=AC=ED=95=98=EB=8A=94?= =?UTF-8?q?=EC=A7=80=20=EC=B0=BE=EB=8A=94=20foundAlphabet=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=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/domain/Word.kt | 8 ++++++++ src/test/kotlin/wordle/domain/WordTest.kt | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 0d1c97a..8416fdd 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -8,6 +8,14 @@ data class Word(val value: String) { } } + fun foundAlphabet(index: Int): String { + if (index < FIRST_INDEX || index > value.length) { + throw IllegalArgumentException(INDEX_OUT_RANGE_MESSAGE) + } + + return value[index].toString() + } + companion object { const val WORD_SIZE = 5 const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index 3c79029..85c8cfd 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -35,4 +35,17 @@ class WordTest { assertThat(message).isEqualTo("5글자여야합니다") } + + @ParameterizedTest + @ValueSource(ints = [-1, 8]) + fun `인덱스 위치가 올바르지 않은 경우 예외를 던진다`(index: Int) { + val givenWord = "value" + val word = Word(givenWord) + + val message = assertThrows { + word.foundAlphabet(index) + }.message + + assertThat(message).isEqualTo("인덱스 범위를 초과했습니다.") + } } From 7369f19ec2ca634840104d5b24aa9deab35bd456 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 00:13:00 +0900 Subject: [PATCH 11/55] =?UTF-8?q?refactor:=20=EB=A7=A4=EC=A7=81=EB=84=98?= =?UTF-8?q?=EB=B2=84=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=83=81=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Word.kt | 2 ++ src/test/kotlin/wordle/domain/WordTest.kt | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 8416fdd..a64b351 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -17,8 +17,10 @@ data class Word(val value: String) { } companion object { + const val FIRST_INDEX = 0 const val WORD_SIZE = 5 const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" + const val INDEX_OUT_RANGE_MESSAGE = "인덱스 범위를 초과했습니다." val regex = Regex("^[a-zA-Z]*$") } } diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index 85c8cfd..528c7c8 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -36,6 +36,16 @@ class WordTest { assertThat(message).isEqualTo("5글자여야합니다") } + @Test + fun `인덱스 위치에 있는 알파벳을 가져온다`() { + val givenWord = "value" + val word = Word(givenWord) + + val actual = word.foundAlphabet(1) + + assertThat(actual).isEqualTo("a") + } + @ParameterizedTest @ValueSource(ints = [-1, 8]) fun `인덱스 위치가 올바르지 않은 경우 예외를 던진다`(index: Int) { From 51876df29501144e245ea7892911c5afa5f0b9c7 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 20:55:39 +0900 Subject: [PATCH 12/55] =?UTF-8?q?doc:=20=EA=B8=B0=EB=8A=A5=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=EB=A5=BC=20=EC=83=88=EB=A1=9C=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=ED=95=A8=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=20*=20=EC=B6=94=EA=B0=80=EB=90=9C=20=EB=AA=85=EC=84=B8=20:=20h?= =?UTF-8?q?ello=EA=B0=80=20=EB=8B=B5=EC=9D=B4=EA=B3=A0=20llloo=20=EB=9D=BC?= =?UTF-8?q?=EA=B3=A0=20=EC=9E=85=EB=A0=A5=ED=95=98=EB=A9=B4=20GRAY,=20YELL?= =?UTF-8?q?O,=20GREEN,=20GRAY,=20GREEN=20=EB=A1=9C=20=EB=82=98=EC=99=80?= =?UTF-8?q?=EC=95=BC=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index aa05801..99d15ce 100644 --- a/README.md +++ b/README.md @@ -23,30 +23,34 @@ ### 기능 명세서 - [ ] 단어 - - [X] 단어를 만들 수 있다. - - [X] 단어는 5글자가 아닌 경우 예외를 던진다. - - [X] 단어는 알파벳이어야한다. - - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다. + - [X] 단어를 만들 수 있다 + - [X] 단어는 5글자가 아닌 경우 예외를 던진다 + - [X] 단어는 알파벳이어야한다 + - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다 - [ ] 타일 - - [ ] 타일은 30개이다. - - [X] 타일은 노란색, 초록색, 회색을 가진다. - - [X] 흰색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다. + - [ ] 타일은 30개이다 + - [X] 타일은 노란색, 초록색, 회색을 가진다 + - [X] 회색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다 - [ ] 매칭 - - [ ] 답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다. - - [ ] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다. - - [ ] 답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다. - - [ ] 답안과 정답의 단어 중 앞서 한 단어가 판별이 난 경우 뒤에 있는 동일한 단어는 판별되지 않는다. + - [X] 답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다 + - [ ] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다 + - [ ] 답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다 + - [ ] 답안과 정답의 단어 중 앞서 한 단어가 판별이 난 경우 뒤에 있는 동일한 단어는 판별되지 않는다 - (예 - 정답이 ROYAL인 경우 MOONY를 입력하면 회초회회노 가 결과로 나온다) + - hello가 답이고 llloo 라고 입력하면 GRAY, YELLO, GREEN, GRAY, GREEN 로 나와야한다 + - 우선순위가 GREEN -> YELLO -> GRAY 순 - [ ] 게임 - - [ ] 6x5 타일로 이루어져 있다. - - [ ] 5글자 단어를 6번동안 추측할 수 있다. - - [ ] 5글자의 모든 위치와 스펠을 맞추는 경우 게임에 승리한다. - - [ ] 6번의 기회동안 맞추지 못하면 패배한다. - - [ ] 종료 시 시도한 횟수와 총 횟수를 보여준다. - - [ ] 결과를 누적해서 보여준다. - - [ ] 정답이 words.txt 에 없는 것인 경우 재입력을 받는다. - - [ ] 정답과 답안(단어)는 words.txt 안에 있는 것이어야 한다. - + - [ ] 5글자의 모든 위치와 스펠을 6번안에 맞추는 경우 게임에 승리한다 + - [ ] 6번의 기회동안 맞추지 못하면 패배한다 + - [ ] 5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다 + - [ ] 정답과 답안을 비교하여 결과 타일을 담아 전달한다 + - [ ] 5글자 단어를 6번동안 맞출 수 있다 + - [ ] 답안을 입력받는다 + - [ ] 정답과 답안(단어)는 words.txt 안에 있는 것이어야 한다 + - [ ] 정답이 words.txt 에 없는 것인 경우 재입력을 받는다 + - [ ] 결과를 출력한다 + - [ ] 결과를 누적해서 보여준다 + - [ ] 종료 시 시도한 횟수와 총 횟수를 출력한다. ### 입출력 요구 사항 From 7bba0b94bc21691e68d316d45af9243307189e14 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 21:26:20 +0900 Subject: [PATCH 13/55] =?UTF-8?q?feat:=20=EB=A7=A4=EC=B9=AD=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EB=85=B8=EB=9E=80=EC=83=89=EA=B3=BC=20?= =?UTF-8?q?=ED=9A=8C=EC=83=89=EC=9D=B4=20=EB=90=98=EB=8A=94=20=EC=BC=80?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=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/domain/WordMatcher.kt | 5 +++++ .../kotlin/wordle/domain/WordMatcherTest.kt | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/main/kotlin/wordle/domain/WordMatcher.kt b/src/main/kotlin/wordle/domain/WordMatcher.kt index 57327cf..e48cb5b 100644 --- a/src/main/kotlin/wordle/domain/WordMatcher.kt +++ b/src/main/kotlin/wordle/domain/WordMatcher.kt @@ -6,6 +6,11 @@ class WordMatcher(private val answer: Word) { if (alphabet == answer.foundAlphabet(index)) { return Tile.GREEN } + + if (answer.contains(alphabet)) { + return Tile.YELLOW + } + return Tile.GRAY } } diff --git a/src/test/kotlin/wordle/domain/WordMatcherTest.kt b/src/test/kotlin/wordle/domain/WordMatcherTest.kt index 82fda40..3cb8d7f 100644 --- a/src/test/kotlin/wordle/domain/WordMatcherTest.kt +++ b/src/test/kotlin/wordle/domain/WordMatcherTest.kt @@ -13,4 +13,25 @@ class WordMatcherTest { assertThat(wordMatcher.match(alphabet, index)).isEqualTo(Tile.GREEN) } + + @ParameterizedTest + @CsvSource("i, 2", "n, 3", "p, 4") + fun `답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다`(givenAlphabet: String, givenIndex: Int) { + val wordMatcher = WordMatcher(Word("input")) + + val actual = wordMatcher.match(givenAlphabet, givenIndex) + + assertThat(actual).isEqualTo(Tile.YELLOW) + } + + @Test + fun `답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다`() { + val wordMatcher = WordMatcher(Word("input")) + val givenAlphabet = "a" + val givenIndex = 4 + + val actual = wordMatcher.match(givenAlphabet, givenIndex) + + assertThat(actual).isEqualTo(Tile.GRAY) + } } From 3d994bfc97dfb075dec1d88a2fc67121cbf96be7 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 21:26:37 +0900 Subject: [PATCH 14/55] =?UTF-8?q?feat:=20Word=20=EC=97=90=20=EC=95=8C?= =?UTF-8?q?=ED=8C=8C=EB=B2=B3=EC=9D=B4=20=ED=8F=AC=ED=95=A8=EB=90=98?= =?UTF-8?q?=EB=8A=94=20=EC=A7=80=EC=97=90=20=EB=8C=80=ED=95=9C=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=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/domain/Word.kt | 4 ++++ src/test/kotlin/wordle/domain/WordTest.kt | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index a64b351..9b748cf 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -16,6 +16,10 @@ data class Word(val value: String) { return value[index].toString() } + fun contains(compareValue: String): Boolean { + return value.contains(compareValue) + } + companion object { const val FIRST_INDEX = 0 const val WORD_SIZE = 5 diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index 528c7c8..08f1699 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -58,4 +58,15 @@ class WordTest { assertThat(message).isEqualTo("인덱스 범위를 초과했습니다.") } + + @Test + fun `단어에 알파벳이 포함되면 참을 리턴한다`() { + val givenWord = "value" + val word = Word(givenWord) + val givenAlphabet = "e" + + val actual = word.contains(givenAlphabet) + + assertThat(actual).isTrue + } } From 050f6193199cb269a4243759d3a6cfefc6179413 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Wed, 13 Apr 2022 21:26:47 +0900 Subject: [PATCH 15/55] =?UTF-8?q?doc:=20=EB=A7=A4=EC=B9=AD=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=B4=20=EA=B5=AC=ED=98=84=ED=95=9C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B2=B4=ED=81=AC=EB=A6=AC=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99d15ce..bd4fe1b 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ - [X] 회색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다 - [ ] 매칭 - [X] 답안과 정답의 한 단어가 위치와 스펠이 같은 경우 초록색이 된다 - - [ ] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다 - - [ ] 답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다 + - [X] 답안과 정답의 한 단어가 위치는 같지만 스펠이 다른 경우 노란색이 된다 + - [X] 답안과 정답의 한 단어가 위치도 다르고 스펠도 다른 경우 회색이 된다 - [ ] 답안과 정답의 단어 중 앞서 한 단어가 판별이 난 경우 뒤에 있는 동일한 단어는 판별되지 않는다 - (예 - 정답이 ROYAL인 경우 MOONY를 입력하면 회초회회노 가 결과로 나온다) - hello가 답이고 llloo 라고 입력하면 GRAY, YELLO, GREEN, GRAY, GREEN 로 나와야한다 From de730f8a03b30367b37abe6abff435cc09316ae9 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:47:33 +0900 Subject: [PATCH 16/55] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=84=20?= =?UTF-8?q?=EC=8A=B9=EB=A6=AC=ED=95=98=EB=8A=94=20=EA=B7=9C=EC=B9=99?= =?UTF-8?q?=EA=B3=BC=20=EC=8B=A4=ED=8C=A8=ED=95=98=EB=8A=94=20=EA=B7=9C?= =?UTF-8?q?=EC=B9=99=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=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/domain/Game.kt | 34 +++++++++++++++++++++++ src/test/kotlin/wordle/domain/GameTest.kt | 29 +++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Game.kt create mode 100644 src/test/kotlin/wordle/domain/GameTest.kt diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt new file mode 100644 index 0000000..bccf2e5 --- /dev/null +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -0,0 +1,34 @@ +package wordle.domain + +class Game(tryCount: TryCount) { + private var _tryCount: TryCount = tryCount + + fun play(input: Word, answer: Word): Boolean { + val inputChars = input.value.toCharArray() + val wordMatcher = WordMatcher(answer) + if (countMatches(inputChars, wordMatcher) == WINNER_MATCHING_COUNT) { + return true + } + + _tryCount = _tryCount.increase() + return false + } + + fun tryCount(): TryCount { + return _tryCount + } + + private fun countMatches(inputChars: CharArray, wordMatcher: WordMatcher): Int { + var sumCount = 0 + inputChars.forEachIndexed { index, it -> + if (wordMatcher.match(it.toString(), index) == Tile.GREEN) { + sumCount++ + } + } + return sumCount + } + + companion object { + const val WINNER_MATCHING_COUNT = 5 + } +} diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt new file mode 100644 index 0000000..0c85df3 --- /dev/null +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -0,0 +1,29 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class GameTest { + + @Test + fun `6번의 기회안에 5글자를 모두 맞추면 성공한다`() { + val game = Game(TryCount(2)) + val input = Word("words") + val answer = Word("words") + + val isWinner = game.play(input, answer) + + assertThat(isWinner).isTrue + } + + @Test + fun `5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다`() { + val game = Game(TryCount(3)) + val input = Word("input") + val answer = Word("hello") + + game.play(input, answer) + + assertThat(game.tryCount()).isEqualTo(TryCount(4)) + } +} From d9546f334bf07e0edcd8a6938749d441fadff5e8 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:47:54 +0900 Subject: [PATCH 17/55] =?UTF-8?q?feat:=20=EC=8B=9C=EB=8F=84=ED=9A=9F?= =?UTF-8?q?=EC=88=98=EC=97=90=20=EB=8C=80=ED=95=9C=20value=20object=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/TryCount.kt | 20 +++++++++++++++++++ src/test/kotlin/wordle/domain/TryCountTest.kt | 19 ++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/TryCount.kt create mode 100644 src/test/kotlin/wordle/domain/TryCountTest.kt diff --git a/src/main/kotlin/wordle/domain/TryCount.kt b/src/main/kotlin/wordle/domain/TryCount.kt new file mode 100644 index 0000000..4f07f20 --- /dev/null +++ b/src/main/kotlin/wordle/domain/TryCount.kt @@ -0,0 +1,20 @@ +package wordle.domain + +@JvmInline +value class TryCount(private val value: Int) { + init { + require(MIN_VALUE <= value && MAX_VALUE > value) { + INPUT_NOT_ALLOWED_MESSAGE + } + } + + fun increase(): TryCount { + return TryCount(value + 1) + } + + companion object { + private const val MIN_VALUE = 0 + private const val MAX_VALUE = 6 + private const val INPUT_NOT_ALLOWED_MESSAGE = "더 이상 입력할 수 없습니다." + } +} diff --git a/src/test/kotlin/wordle/domain/TryCountTest.kt b/src/test/kotlin/wordle/domain/TryCountTest.kt new file mode 100644 index 0000000..f15e676 --- /dev/null +++ b/src/test/kotlin/wordle/domain/TryCountTest.kt @@ -0,0 +1,19 @@ +package wordle.domain + +import org.assertj.core.api.Assertions +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows + +class TryCountTest { + + @Test + fun `6번의 기회동안 맞추지 못하면 패배한다`() { + val givenTryCount = 7 + + val message = assertThrows { + TryCount(givenTryCount) + }.message + + Assertions.assertThat(message).isEqualTo("더 이상 입력할 수 없습니다.") + } +} From 3bb172b2f492680f4527923a5dfe6ecf4dc64ad7 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:48:14 +0900 Subject: [PATCH 18/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=98=88=EC=99=B8=20=EB=AA=85=EC=8B=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20private=20=EC=A0=91=EA=B7=BC=EC=A0=9C?= =?UTF-8?q?=EC=96=B4=EC=9E=90=20=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/domain/Word.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 9b748cf..f205a2a 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -4,7 +4,7 @@ data class Word(val value: String) { init { require(value.length == WORD_SIZE && regex.matches(value)) { - throw IllegalArgumentException(WRONG_WORD_SIZE_MESSAGE) + WRONG_WORD_SIZE_MESSAGE } } @@ -21,10 +21,10 @@ data class Word(val value: String) { } companion object { - const val FIRST_INDEX = 0 - const val WORD_SIZE = 5 - const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" - const val INDEX_OUT_RANGE_MESSAGE = "인덱스 범위를 초과했습니다." + private const val FIRST_INDEX = 0 + private const val WORD_SIZE = 5 + private const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" + private const val INDEX_OUT_RANGE_MESSAGE = "인덱스 범위를 초과했습니다." val regex = Regex("^[a-zA-Z]*$") } } From ced063d3d40bb80bb985d14f39a0144b68b580fe Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:48:30 +0900 Subject: [PATCH 19/55] =?UTF-8?q?doc:=20=EA=B5=AC=ED=98=84=EB=90=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=AA=85?= =?UTF-8?q?=EC=84=B8=EC=84=9C=20=EC=B2=B4=ED=81=AC=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index bd4fe1b..7a4b2fc 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ - 우선순위가 GREEN -> YELLO -> GRAY 순 - [ ] 게임 - [ ] 5글자의 모든 위치와 스펠을 6번안에 맞추는 경우 게임에 승리한다 - - [ ] 6번의 기회동안 맞추지 못하면 패배한다 - - [ ] 5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다 + - [X] 6번의 기회안에 5글자를 모두 맞추면 성공한다. + - [X] 6번의 기회동안 맞추지 못하면 패배한다 + - [X] 5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다 - [ ] 정답과 답안을 비교하여 결과 타일을 담아 전달한다 - [ ] 5글자 단어를 6번동안 맞출 수 있다 - [ ] 답안을 입력받는다 From 759013e6c8fc5fe9c2e973828ac3a46f576d64ea Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:51:22 +0900 Subject: [PATCH 20/55] =?UTF-8?q?refactor:=20foundAlphabet=20->=20findAlph?= =?UTF-8?q?abet=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EC=B6=9C=20=EC=A7=84=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 | 8 +++++--- src/main/kotlin/wordle/domain/WordMatcher.kt | 2 +- src/test/kotlin/wordle/domain/WordTest.kt | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index f205a2a..bd54fe4 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -3,12 +3,14 @@ package wordle.domain data class Word(val value: String) { init { - require(value.length == WORD_SIZE && regex.matches(value)) { + require(isWordSizeAndAlphabet()) { WRONG_WORD_SIZE_MESSAGE } } - fun foundAlphabet(index: Int): String { + private fun isWordSizeAndAlphabet() = value.length == WORD_SIZE && ALPHABET_REGEX.matches(value) + + fun findAlphabet(index: Int): String { if (index < FIRST_INDEX || index > value.length) { throw IllegalArgumentException(INDEX_OUT_RANGE_MESSAGE) } @@ -25,6 +27,6 @@ data class Word(val value: String) { private const val WORD_SIZE = 5 private const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" private const val INDEX_OUT_RANGE_MESSAGE = "인덱스 범위를 초과했습니다." - val regex = Regex("^[a-zA-Z]*$") + val ALPHABET_REGEX = Regex("^[a-zA-Z]*$") } } diff --git a/src/main/kotlin/wordle/domain/WordMatcher.kt b/src/main/kotlin/wordle/domain/WordMatcher.kt index e48cb5b..323ce43 100644 --- a/src/main/kotlin/wordle/domain/WordMatcher.kt +++ b/src/main/kotlin/wordle/domain/WordMatcher.kt @@ -3,7 +3,7 @@ package wordle.domain class WordMatcher(private val answer: Word) { fun match(alphabet: String, index: Int): Tile { - if (alphabet == answer.foundAlphabet(index)) { + if (alphabet == answer.findAlphabet(index)) { return Tile.GREEN } diff --git a/src/test/kotlin/wordle/domain/WordTest.kt b/src/test/kotlin/wordle/domain/WordTest.kt index 08f1699..3e4b93b 100644 --- a/src/test/kotlin/wordle/domain/WordTest.kt +++ b/src/test/kotlin/wordle/domain/WordTest.kt @@ -41,7 +41,7 @@ class WordTest { val givenWord = "value" val word = Word(givenWord) - val actual = word.foundAlphabet(1) + val actual = word.findAlphabet(1) assertThat(actual).isEqualTo("a") } @@ -53,7 +53,7 @@ class WordTest { val word = Word(givenWord) val message = assertThrows { - word.foundAlphabet(index) + word.findAlphabet(index) }.message assertThat(message).isEqualTo("인덱스 범위를 초과했습니다.") From 1d39fa965d2218964e643d5cb14b39ab1cf54722 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:52:01 +0900 Subject: [PATCH 21/55] =?UTF-8?q?refactor:=20private=20=EC=A0=91=EA=B7=BC?= =?UTF-8?q?=EC=A0=9C=EC=96=B4=EC=9E=90=20=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/domain/Word.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index bd54fe4..8c873da 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -27,6 +27,6 @@ data class Word(val value: String) { private const val WORD_SIZE = 5 private const val WRONG_WORD_SIZE_MESSAGE = "5글자여야합니다" private const val INDEX_OUT_RANGE_MESSAGE = "인덱스 범위를 초과했습니다." - val ALPHABET_REGEX = Regex("^[a-zA-Z]*$") + private val ALPHABET_REGEX = Regex("^[a-zA-Z]*$") } } From eb710872e041344e922a1f1bc51f4009df24eb4d Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:52:13 +0900 Subject: [PATCH 22/55] =?UTF-8?q?refactor:=20=EA=B0=80=EB=8F=85=EC=84=B1?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20until=EB=A1=9C=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/TryCount.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/TryCount.kt b/src/main/kotlin/wordle/domain/TryCount.kt index 4f07f20..098716b 100644 --- a/src/main/kotlin/wordle/domain/TryCount.kt +++ b/src/main/kotlin/wordle/domain/TryCount.kt @@ -3,7 +3,7 @@ package wordle.domain @JvmInline value class TryCount(private val value: Int) { init { - require(MIN_VALUE <= value && MAX_VALUE > value) { + require(value in MIN_VALUE until MAX_VALUE) { INPUT_NOT_ALLOWED_MESSAGE } } From cbf8f749cb4a49eeb56e411d9ea41ba9dbbc29b5 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 10:52:43 +0900 Subject: [PATCH 23/55] =?UTF-8?q?feat:=20junit=20test=20import=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/wordle/domain/WordMatcherTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/kotlin/wordle/domain/WordMatcherTest.kt b/src/test/kotlin/wordle/domain/WordMatcherTest.kt index 3cb8d7f..e8856b4 100644 --- a/src/test/kotlin/wordle/domain/WordMatcherTest.kt +++ b/src/test/kotlin/wordle/domain/WordMatcherTest.kt @@ -1,6 +1,7 @@ package wordle.domain import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.CsvSource From 8e52fd556f58fcaa7eefb249a6c260b4deb337ae Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 16:11:26 +0900 Subject: [PATCH 24/55] =?UTF-8?q?refactor:=20answer=20=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=A4=91=EB=B3=B5=EB=90=9C=20=ED=8C=8C?= =?UTF-8?q?=EB=9D=BC=EB=AF=B8=ED=84=B0=EB=A1=9C=20=EC=9D=B8=ED=95=B4=20?= =?UTF-8?q?=EB=A9=A4=EB=B2=84=EB=B3=80=EC=88=98=EB=A1=9C=20=EC=A0=84?= =?UTF-8?q?=ED=99=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Game.kt | 5 ++-- src/test/kotlin/wordle/domain/GameTest.kt | 31 +++++++++++++++++------ 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index bccf2e5..8ec4c4e 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,9 +1,9 @@ package wordle.domain -class Game(tryCount: TryCount) { +class Game(tryCount: TryCount, private val answer: Word) { private var _tryCount: TryCount = tryCount - fun play(input: Word, answer: Word): Boolean { + fun play(input: Word): Boolean { val inputChars = input.value.toCharArray() val wordMatcher = WordMatcher(answer) if (countMatches(inputChars, wordMatcher) == WINNER_MATCHING_COUNT) { @@ -25,6 +25,7 @@ class Game(tryCount: TryCount) { sumCount++ } } + return sumCount } diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt index 0c85df3..d36bcd9 100644 --- a/src/test/kotlin/wordle/domain/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -7,23 +7,38 @@ class GameTest { @Test fun `6번의 기회안에 5글자를 모두 맞추면 성공한다`() { - val game = Game(TryCount(2)) - val input = Word("words") - val answer = Word("words") + val givenAnswer = Word("words") + val game = Game(TryCount(2), givenAnswer) + val givenInput = Word("words") - val isWinner = game.play(input, answer) + val isWinner = game.play(givenInput) assertThat(isWinner).isTrue } @Test fun `5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다`() { - val game = Game(TryCount(3)) - val input = Word("input") - val answer = Word("hello") + val givenAnswer = Word("hello") + val game = Game(TryCount(3), givenAnswer) + val givenInput = Word("input") - game.play(input, answer) + game.play(givenInput) assertThat(game.tryCount()).isEqualTo(TryCount(4)) } + +// @Test +// fun `정답과 답안을 비교하여 결과 타일을 담아 전달한다`() { +// val game = Game(TryCount(0)) +// val input = Word("input") +// val answer = Word("hello") +// +// game.play(input, answer) +// +// val game = Game(TryCount(3)) +// +// List resultTiles = game.retreiveResultTiles() +// +// assertThat(resultTiles).isEqualTo(TryCount(4)) +// } } From 0a32d12091a7430947af7e67f462b447041e4fe8 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 17:31:56 +0900 Subject: [PATCH 25/55] =?UTF-8?q?refactor:=20=EA=B2=8C=EC=9E=84=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=EC=97=90=20=EB=8C=80=ED=95=B4=EC=84=9C=20?= =?UTF-8?q?=ED=83=80=EC=9D=BC=EB=93=A4=EC=9D=84=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EA=B5=AC=ED=98=84=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?=20*=20=EA=B8=B0=EC=A1=B4=EC=97=90=20true,=20false=20=EB=A1=9C?= =?UTF-8?q?=20=EB=A6=AC=ED=84=B4=ED=95=98=EB=8A=94=20=EA=B2=83=EC=9D=84=20?= =?UTF-8?q?=ED=83=80=EC=9D=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/Game.kt | 33 ++++++++++++++--------- src/test/kotlin/wordle/domain/GameTest.kt | 31 ++++++++++----------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 8ec4c4e..478cad5 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -3,33 +3,42 @@ package wordle.domain class Game(tryCount: TryCount, private val answer: Word) { private var _tryCount: TryCount = tryCount - fun play(input: Word): Boolean { + fun play(input: Word): List { val inputChars = input.value.toCharArray() val wordMatcher = WordMatcher(answer) - if (countMatches(inputChars, wordMatcher) == WINNER_MATCHING_COUNT) { - return true + + val resultTiles = createResultTiles(inputChars, wordMatcher) + + if (isWinner(resultTiles)) { + return resultTiles; } _tryCount = _tryCount.increase() - return false + + return resultTiles + } + + fun isWinner(resultTiles: List): Boolean { + return resultTiles.containsAll( + listOf(Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN) + ) } fun tryCount(): TryCount { return _tryCount } - private fun countMatches(inputChars: CharArray, wordMatcher: WordMatcher): Int { - var sumCount = 0 + private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): List { + val resultTiles = mutableListOf() + inputChars.forEachIndexed { index, it -> - if (wordMatcher.match(it.toString(), index) == Tile.GREEN) { - sumCount++ - } + resultTiles.add(wordMatcher.match(it.toString(), index)) } - return sumCount + return resultTiles.toList() } - companion object { - const val WINNER_MATCHING_COUNT = 5 + fun retrieveResultTiles(): List { + return listOf(Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY) } } diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt index d36bcd9..4e46025 100644 --- a/src/test/kotlin/wordle/domain/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -11,7 +11,8 @@ class GameTest { val game = Game(TryCount(2), givenAnswer) val givenInput = Word("words") - val isWinner = game.play(givenInput) + val result = game.play(givenInput) + val isWinner = game.isWinner(result) assertThat(isWinner).isTrue } @@ -27,18 +28,18 @@ class GameTest { assertThat(game.tryCount()).isEqualTo(TryCount(4)) } -// @Test -// fun `정답과 답안을 비교하여 결과 타일을 담아 전달한다`() { -// val game = Game(TryCount(0)) -// val input = Word("input") -// val answer = Word("hello") -// -// game.play(input, answer) -// -// val game = Game(TryCount(3)) -// -// List resultTiles = game.retreiveResultTiles() -// -// assertThat(resultTiles).isEqualTo(TryCount(4)) -// } + @Test + fun `정답과 답안을 비교하여 결과 타일을 담아 전달한다`() { + val givenAnswer = Word("hello") + val game = Game(TryCount(0), givenAnswer) + val input = Word("oxide") + + game.play(input) + + val resultTiles = game.retrieveResultTiles() + + assertThat(resultTiles).containsExactly( + Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY + ) + } } From b06d616f5e23356f733acc8af1d5fd4055e69a15 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 17:53:04 +0900 Subject: [PATCH 26/55] =?UTF-8?q?feat:=20Tiles=20value=20object=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=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/domain/Tiles.kt | 18 ++++++++++++++++ src/test/kotlin/wordle/domain/TilesTest.kt | 25 ++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Tiles.kt create mode 100644 src/test/kotlin/wordle/domain/TilesTest.kt diff --git a/src/main/kotlin/wordle/domain/Tiles.kt b/src/main/kotlin/wordle/domain/Tiles.kt new file mode 100644 index 0000000..79078ad --- /dev/null +++ b/src/main/kotlin/wordle/domain/Tiles.kt @@ -0,0 +1,18 @@ +package wordle.domain + +class Tiles(private val tiles: List) { + + fun isWinner(): Boolean { + val count = tiles.count { it == Tile.GREEN } + + if (count == TOTAL_TILE_COUNT) { + return true + } + + return false + } + + companion object { + private const val TOTAL_TILE_COUNT = 5 + } +} diff --git a/src/test/kotlin/wordle/domain/TilesTest.kt b/src/test/kotlin/wordle/domain/TilesTest.kt new file mode 100644 index 0000000..420043b --- /dev/null +++ b/src/test/kotlin/wordle/domain/TilesTest.kt @@ -0,0 +1,25 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class TilesTest { + @Test + fun `모두 초록색인 경우 우승자이다`() { + val givenTiles = Tiles(listOf(Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN)) + + val actual = givenTiles.isWinner() + + assertThat(actual).isTrue + } + + @Test + fun `모두 초록색이 아닌 경우 우승자가아니다`() { + val givenTiles = Tiles(listOf(Tile.GREEN, Tile.YELLOW, Tile.GREEN, Tile.GRAY, Tile.GREEN)) + + val actual = givenTiles.isWinner() + + assertThat(actual).isFalse + } + +} From 79f9e49b50ff4342d5c184a222d78fb7ca31b8c8 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 17:53:26 +0900 Subject: [PATCH 27/55] =?UTF-8?q?refactor:=20Tiles=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=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/Game.kt | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 478cad5..95ff7f0 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -3,14 +3,14 @@ package wordle.domain class Game(tryCount: TryCount, private val answer: Word) { private var _tryCount: TryCount = tryCount - fun play(input: Word): List { + fun play(input: Word): Tiles { val inputChars = input.value.toCharArray() val wordMatcher = WordMatcher(answer) val resultTiles = createResultTiles(inputChars, wordMatcher) - if (isWinner(resultTiles)) { - return resultTiles; + if (resultTiles.isWinner()) { + return resultTiles } _tryCount = _tryCount.increase() @@ -18,24 +18,22 @@ class Game(tryCount: TryCount, private val answer: Word) { return resultTiles } - fun isWinner(resultTiles: List): Boolean { - return resultTiles.containsAll( - listOf(Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN, Tile.GREEN) - ) + fun isWinner(resultTiles: Tiles): Boolean { + return resultTiles.isWinner() } fun tryCount(): TryCount { return _tryCount } - private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): List { + private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): Tiles { val resultTiles = mutableListOf() inputChars.forEachIndexed { index, it -> resultTiles.add(wordMatcher.match(it.toString(), index)) } - return resultTiles.toList() + return Tiles(resultTiles.toList()) } fun retrieveResultTiles(): List { From c4263dddf879bd80d51e2151e64ed22b1016c5ca Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:46:42 +0900 Subject: [PATCH 28/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20tryCount=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/TryCount.kt | 20 ------------------- src/test/kotlin/wordle/domain/TryCountTest.kt | 19 ------------------ 2 files changed, 39 deletions(-) delete mode 100644 src/main/kotlin/wordle/domain/TryCount.kt delete mode 100644 src/test/kotlin/wordle/domain/TryCountTest.kt diff --git a/src/main/kotlin/wordle/domain/TryCount.kt b/src/main/kotlin/wordle/domain/TryCount.kt deleted file mode 100644 index 098716b..0000000 --- a/src/main/kotlin/wordle/domain/TryCount.kt +++ /dev/null @@ -1,20 +0,0 @@ -package wordle.domain - -@JvmInline -value class TryCount(private val value: Int) { - init { - require(value in MIN_VALUE until MAX_VALUE) { - INPUT_NOT_ALLOWED_MESSAGE - } - } - - fun increase(): TryCount { - return TryCount(value + 1) - } - - companion object { - private const val MIN_VALUE = 0 - private const val MAX_VALUE = 6 - private const val INPUT_NOT_ALLOWED_MESSAGE = "더 이상 입력할 수 없습니다." - } -} diff --git a/src/test/kotlin/wordle/domain/TryCountTest.kt b/src/test/kotlin/wordle/domain/TryCountTest.kt deleted file mode 100644 index f15e676..0000000 --- a/src/test/kotlin/wordle/domain/TryCountTest.kt +++ /dev/null @@ -1,19 +0,0 @@ -package wordle.domain - -import org.assertj.core.api.Assertions -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.assertThrows - -class TryCountTest { - - @Test - fun `6번의 기회동안 맞추지 못하면 패배한다`() { - val givenTryCount = 7 - - val message = assertThrows { - TryCount(givenTryCount) - }.message - - Assertions.assertThat(message).isEqualTo("더 이상 입력할 수 없습니다.") - } -} From 21a5791b2d435b3ec456e72cfa8102e287919ad2 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:49:48 +0900 Subject: [PATCH 29/55] =?UTF-8?q?feat:=20words.txt=20=EC=9D=98=20=EC=A0=95?= =?UTF-8?q?=EB=8B=B5=EB=93=A4=EC=9D=84=20=EA=B0=80=EC=A7=80=EB=8A=94=20Ans?= =?UTF-8?q?wers=20=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/domain/Answers.kt | 31 ++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Answers.kt diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt new file mode 100644 index 0000000..489c52c --- /dev/null +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -0,0 +1,31 @@ +package wordle.domain + +import wordle.controller.getResourceText +import java.time.LocalDate +import java.time.temporal.ChronoUnit + +class Answers { + + companion object { + private const val ANSWERS_TEXT_PATH = "./words.txt" + val WORDS = createWords() + val ANSWER = createAnswer() + + private fun createWords(): List { + val wordsFile = getResourceText(ANSWERS_TEXT_PATH) + + val words = mutableListOf() + wordsFile.forEachLine { + words.add(Word(it)) + } + + return words + } + + private fun createAnswer(): Word { + return WORDS[(createAnswerPosition() % WORDS.size).toInt()] + } + + private fun createAnswerPosition() = ChronoUnit.DAYS.between(LocalDate.of(2021, 6, 19), LocalDate.now()) + } +} From 1d526cdaf1f3ad1e9f37327e1a28ca181e710ff5 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:50:04 +0900 Subject: [PATCH 30/55] =?UTF-8?q?feat:=20=EC=9E=85=EB=A0=A5=EC=9D=84=20?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0=20=EC=9C=84=ED=95=9C=20InputView=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/view/InputView.kt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 src/main/kotlin/wordle/view/InputView.kt diff --git a/src/main/kotlin/wordle/view/InputView.kt b/src/main/kotlin/wordle/view/InputView.kt new file mode 100644 index 0000000..61d04c9 --- /dev/null +++ b/src/main/kotlin/wordle/view/InputView.kt @@ -0,0 +1,22 @@ +package wordle.view + +import wordle.domain.Word + +object InputView { + + fun askWord(words: List): String { + while (true) { + val input = question("정답을 입력해 주세요.") + if (words.contains(Word(input))) { + return input + } + + println("올바르지 않은 단어입니다.") + } + } + + private tailrec fun question(question: String): String { + println(question) + return readLine() ?: question(question) + } +} From 1f4a3329d2ec90da9efbf53d59bd25835966e742 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:50:14 +0900 Subject: [PATCH 31/55] =?UTF-8?q?refactor:=20=EA=B2=B0=EA=B3=BC=EB=A5=BC?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20?= =?UTF-8?q?resultView=20=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/view/ResultView.kt | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/kotlin/wordle/view/ResultView.kt diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt new file mode 100644 index 0000000..d84f375 --- /dev/null +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -0,0 +1,29 @@ +package wordle.view + +import wordle.domain.Tiles + +object ResultView { + fun printInit() { + println("WORDLE을 6번 만에 맞춰 보세요.") + println("시도의 결과는 타일의 색 변화로 나타납니다.") + } + + fun printGamePlayCount(index: Int) { + print(index) + print("/6") + println() + } + + fun printAllResults(results: MutableList) { + results.forEach { + printAllTiles(it) + println() + } + } + + private fun printAllTiles(tiles: Tiles) { + tiles.tiles.forEach { tile -> + print(tile.value) + } + } +} From ad3d1b52c53040a201cb4417cd6f72d202dd36ed Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:50:45 +0900 Subject: [PATCH 32/55] =?UTF-8?q?feat:=20=EA=B2=8C=EC=9E=84=EC=9D=84=20?= =?UTF-8?q?=ED=94=8C=EB=A0=88=EC=9D=B4=ED=95=98=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20=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 --- .../kotlin/wordle/controller/Application.kt | 46 +++++++++++++++++++ src/main/kotlin/wordle/domain/Game.kt | 13 ++---- src/main/kotlin/wordle/domain/Tile.kt | 4 +- src/main/kotlin/wordle/domain/Tiles.kt | 2 +- src/test/kotlin/wordle/domain/GameTest.kt | 17 ++----- src/test/kotlin/wordle/domain/TilesTest.kt | 1 - 6 files changed, 55 insertions(+), 28 deletions(-) create mode 100644 src/main/kotlin/wordle/controller/Application.kt diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt new file mode 100644 index 0000000..a58234f --- /dev/null +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -0,0 +1,46 @@ +package wordle.controller + +import wordle.domain.Answers +import wordle.domain.Game +import wordle.domain.Tiles +import wordle.domain.Word +import wordle.view.InputView +import wordle.view.ResultView +import java.io.File + +private const val START_PLAY_COUNT = 1 +private const val LAST_PLAY_COUNT = 7 + +fun main() { + val game = Game(Answers.ANSWER) + + ResultView.printInit() + + val results = mutableListOf() + playGame(game, results) +} + +private fun playGame(game: Game, results: MutableList) { + (START_PLAY_COUNT until LAST_PLAY_COUNT).forEachIndexed { _, index -> + val inputWord = InputView.askWord(Answers.WORDS) + + val resultTiles = game.play(Word(inputWord)) + + results.add(resultTiles) + + ResultView.printAllResults(results) + + checkIsWinner(game, resultTiles, index) + } +} + +private fun checkIsWinner(game: Game, resultTiles: Tiles, index: Int) { + if (game.isWinner(resultTiles)) { + ResultView.printGamePlayCount(index) + throw IllegalStateException("게임이 종료되었습니다.") + } +} + +fun getResourceText(path: String): File { + return File(ClassLoader.getSystemResource(path).file) +} diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 95ff7f0..788c0df 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -1,7 +1,6 @@ package wordle.domain -class Game(tryCount: TryCount, private val answer: Word) { - private var _tryCount: TryCount = tryCount +class Game(private val answer: Word) { fun play(input: Word): Tiles { val inputChars = input.value.toCharArray() @@ -13,8 +12,6 @@ class Game(tryCount: TryCount, private val answer: Word) { return resultTiles } - _tryCount = _tryCount.increase() - return resultTiles } @@ -22,10 +19,6 @@ class Game(tryCount: TryCount, private val answer: Word) { return resultTiles.isWinner() } - fun tryCount(): TryCount { - return _tryCount - } - private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): Tiles { val resultTiles = mutableListOf() @@ -36,7 +29,7 @@ class Game(tryCount: TryCount, private val answer: Word) { return Tiles(resultTiles.toList()) } - fun retrieveResultTiles(): List { - return listOf(Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY) + fun retrieveResultTiles(): Tiles { + return Tiles(listOf(Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY)) } } diff --git a/src/main/kotlin/wordle/domain/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt index 1ae1ba3..59da41b 100644 --- a/src/main/kotlin/wordle/domain/Tile.kt +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -1,7 +1,7 @@ package wordle.domain enum class Tile(val value: String) { - YELLOW("\uD83D\uDFE7"), + YELLOW("\uD83D\uDFE8"), GREEN("\uD83D\uDFE9"), - GRAY("\uD83D\uDFE8"); + GRAY("⬜"); } diff --git a/src/main/kotlin/wordle/domain/Tiles.kt b/src/main/kotlin/wordle/domain/Tiles.kt index 79078ad..d768c15 100644 --- a/src/main/kotlin/wordle/domain/Tiles.kt +++ b/src/main/kotlin/wordle/domain/Tiles.kt @@ -1,6 +1,6 @@ package wordle.domain -class Tiles(private val tiles: List) { +class Tiles(val tiles: List) { fun isWinner(): Boolean { val count = tiles.count { it == Tile.GREEN } diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt index 4e46025..c7dd780 100644 --- a/src/test/kotlin/wordle/domain/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -8,7 +8,7 @@ class GameTest { @Test fun `6번의 기회안에 5글자를 모두 맞추면 성공한다`() { val givenAnswer = Word("words") - val game = Game(TryCount(2), givenAnswer) + val game = Game(givenAnswer) val givenInput = Word("words") val result = game.play(givenInput) @@ -17,28 +17,17 @@ class GameTest { assertThat(isWinner).isTrue } - @Test - fun `5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다`() { - val givenAnswer = Word("hello") - val game = Game(TryCount(3), givenAnswer) - val givenInput = Word("input") - - game.play(givenInput) - - assertThat(game.tryCount()).isEqualTo(TryCount(4)) - } - @Test fun `정답과 답안을 비교하여 결과 타일을 담아 전달한다`() { val givenAnswer = Word("hello") - val game = Game(TryCount(0), givenAnswer) + val game = Game(givenAnswer) val input = Word("oxide") game.play(input) val resultTiles = game.retrieveResultTiles() - assertThat(resultTiles).containsExactly( + assertThat(resultTiles.tiles).containsExactly( Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY ) } diff --git a/src/test/kotlin/wordle/domain/TilesTest.kt b/src/test/kotlin/wordle/domain/TilesTest.kt index 420043b..e216e73 100644 --- a/src/test/kotlin/wordle/domain/TilesTest.kt +++ b/src/test/kotlin/wordle/domain/TilesTest.kt @@ -21,5 +21,4 @@ class TilesTest { assertThat(actual).isFalse } - } From 6783141faf866ac0b0d330294bfe874bef58bb74 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:51:21 +0900 Subject: [PATCH 33/55] =?UTF-8?q?doc:=20=EA=B5=AC=ED=98=84=EB=90=9C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B2=B4?= =?UTF-8?q?=ED=81=AC=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7a4b2fc..c0ff378 100644 --- a/README.md +++ b/README.md @@ -22,13 +22,12 @@ ### 기능 명세서 -- [ ] 단어 +- [X] 단어 - [X] 단어를 만들 수 있다 - [X] 단어는 5글자가 아닌 경우 예외를 던진다 - [X] 단어는 알파벳이어야한다 - - [ ] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다 -- [ ] 타일 - - [ ] 타일은 30개이다 + - [X] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다 +- [X] 타일 - [X] 타일은 노란색, 초록색, 회색을 가진다 - [X] 회색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다 - [ ] 매칭 @@ -39,19 +38,19 @@ - (예 - 정답이 ROYAL인 경우 MOONY를 입력하면 회초회회노 가 결과로 나온다) - hello가 답이고 llloo 라고 입력하면 GRAY, YELLO, GREEN, GRAY, GREEN 로 나와야한다 - 우선순위가 GREEN -> YELLO -> GRAY 순 -- [ ] 게임 - - [ ] 5글자의 모든 위치와 스펠을 6번안에 맞추는 경우 게임에 승리한다 +- [X] 게임 + - [X] 5글자의 모든 위치와 스펠을 6번안에 맞추는 경우 게임에 승리한다 - [X] 6번의 기회안에 5글자를 모두 맞추면 성공한다. - [X] 6번의 기회동안 맞추지 못하면 패배한다 - [X] 5글자의 모든 위치와 스펠이 같지 않은 경우 시도 횟수가 더해진다 - - [ ] 정답과 답안을 비교하여 결과 타일을 담아 전달한다 - - [ ] 5글자 단어를 6번동안 맞출 수 있다 - - [ ] 답안을 입력받는다 - - [ ] 정답과 답안(단어)는 words.txt 안에 있는 것이어야 한다 - - [ ] 정답이 words.txt 에 없는 것인 경우 재입력을 받는다 - - [ ] 결과를 출력한다 - - [ ] 결과를 누적해서 보여준다 - - [ ] 종료 시 시도한 횟수와 총 횟수를 출력한다. + - [X] 정답과 답안을 비교하여 결과 타일을 담아 전달한다 + - [X] 답안을 입력받는다 + - [X] 정답과 답안(단어)는 words.txt 안에 있는 것이어야 한다 + - [X] 정답이 words.txt 에 없는 것인 경우 재입력을 받는다 + - [X] 정답은 매일 바뀌며 ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어이다 + - [X] 결과를 출력한다 + - [X] 결과를 누적해서 보여준다 + - [X] 종료 시 시도한 횟수와 총 횟수를 출력한다. ### 입출력 요구 사항 From 5319a1ae697c599aa7cfa2743c54477b6f03b824 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 21:59:25 +0900 Subject: [PATCH 34/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=95=A8=EC=88=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Game.kt | 10 +++------- src/test/kotlin/wordle/domain/GameTest.kt | 15 --------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 788c0df..5ce997f 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -15,10 +15,6 @@ class Game(private val answer: Word) { return resultTiles } - fun isWinner(resultTiles: Tiles): Boolean { - return resultTiles.isWinner() - } - private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): Tiles { val resultTiles = mutableListOf() @@ -26,10 +22,10 @@ class Game(private val answer: Word) { resultTiles.add(wordMatcher.match(it.toString(), index)) } - return Tiles(resultTiles.toList()) + return Tiles(resultTiles) } - fun retrieveResultTiles(): Tiles { - return Tiles(listOf(Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY)) + fun isWinner(resultTiles: Tiles): Boolean { + return resultTiles.isWinner() } } diff --git a/src/test/kotlin/wordle/domain/GameTest.kt b/src/test/kotlin/wordle/domain/GameTest.kt index c7dd780..bbbb7df 100644 --- a/src/test/kotlin/wordle/domain/GameTest.kt +++ b/src/test/kotlin/wordle/domain/GameTest.kt @@ -16,19 +16,4 @@ class GameTest { assertThat(isWinner).isTrue } - - @Test - fun `정답과 답안을 비교하여 결과 타일을 담아 전달한다`() { - val givenAnswer = Word("hello") - val game = Game(givenAnswer) - val input = Word("oxide") - - game.play(input) - - val resultTiles = game.retrieveResultTiles() - - assertThat(resultTiles.tiles).containsExactly( - Tile.YELLOW, Tile.GRAY, Tile.GRAY, Tile.GRAY, Tile.GRAY - ) - } } From 6d6d0546907fcdf395d7d5f3dd6ba21925426817 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:03:54 +0900 Subject: [PATCH 35/55] =?UTF-8?q?refactor:=20data=20=EB=A5=BC=20value=20cl?= =?UTF-8?q?ass=20=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 8c873da..7e88163 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -1,6 +1,7 @@ package wordle.domain -data class Word(val value: String) { +@JvmInline +value class Word(val value: String) { init { require(isWordSizeAndAlphabet()) { From e4dfdf073dbab81a74cd17a4e984085ad6dfa165 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:10:48 +0900 Subject: [PATCH 36/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=84=A0=EC=96=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/controller/Application.kt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index a58234f..73c742d 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -16,11 +16,12 @@ fun main() { ResultView.printInit() - val results = mutableListOf() - playGame(game, results) + playGame(game) } -private fun playGame(game: Game, results: MutableList) { +private fun playGame(game: Game) { + val results = mutableListOf() + (START_PLAY_COUNT until LAST_PLAY_COUNT).forEachIndexed { _, index -> val inputWord = InputView.askWord(Answers.WORDS) From 4ee303d3c71449e83ae09e804e37f9760c23fdec Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:11:33 +0900 Subject: [PATCH 37/55] =?UTF-8?q?refactor:=20MAX=5FTRY=5FCOUNT=20=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EC=83=81=EC=88=98=20=EC=B6=94=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/view/ResultView.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index d84f375..1d5406a 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -2,15 +2,17 @@ package wordle.view import wordle.domain.Tiles +private const val MAX_TRY_COUNT = 6 + object ResultView { fun printInit() { - println("WORDLE을 6번 만에 맞춰 보세요.") + println("WORDLE을 ${MAX_TRY_COUNT}번 만에 맞춰 보세요.") println("시도의 결과는 타일의 색 변화로 나타납니다.") } fun printGamePlayCount(index: Int) { print(index) - print("/6") + print("/$MAX_TRY_COUNT") println() } @@ -22,7 +24,7 @@ object ResultView { } private fun printAllTiles(tiles: Tiles) { - tiles.tiles.forEach { tile -> + tiles.forEach { tile -> print(tile.value) } } From 6cc86beb70570de4483bfe8e73b0e31bc00c96d7 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:11:48 +0900 Subject: [PATCH 38/55] =?UTF-8?q?refactor:=20List=20=EB=A1=9C=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=A0=20=EC=88=98=20=EC=9E=88=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Tiles.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Tiles.kt b/src/main/kotlin/wordle/domain/Tiles.kt index d768c15..65ba7aa 100644 --- a/src/main/kotlin/wordle/domain/Tiles.kt +++ b/src/main/kotlin/wordle/domain/Tiles.kt @@ -1,6 +1,6 @@ package wordle.domain -class Tiles(val tiles: List) { +class Tiles(private val tiles: List) : List by tiles { fun isWinner(): Boolean { val count = tiles.count { it == Tile.GREEN } From beb1b1829ae200dd810e1df66cb41e20fa69393c Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:18:08 +0900 Subject: [PATCH 39/55] =?UTF-8?q?refactor:=20=ED=83=80=EC=9D=BC=EC=9D=84?= =?UTF-8?q?=20=EB=B7=B0=EC=99=80=20=EB=B6=84=EB=A6=AC=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20viewTiles=20=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/domain/Tile.kt | 8 ++++---- src/main/kotlin/wordle/view/ResultView.kt | 9 ++++++++- src/test/kotlin/wordle/domain/TileTest.kt | 8 -------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Tile.kt b/src/main/kotlin/wordle/domain/Tile.kt index 59da41b..88eb801 100644 --- a/src/main/kotlin/wordle/domain/Tile.kt +++ b/src/main/kotlin/wordle/domain/Tile.kt @@ -1,7 +1,7 @@ package wordle.domain -enum class Tile(val value: String) { - YELLOW("\uD83D\uDFE8"), - GREEN("\uD83D\uDFE9"), - GRAY("⬜"); +enum class Tile { + YELLOW, + GREEN, + GRAY } diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index 1d5406a..4174398 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -1,5 +1,6 @@ package wordle.view +import wordle.domain.Tile import wordle.domain.Tiles private const val MAX_TRY_COUNT = 6 @@ -25,7 +26,13 @@ object ResultView { private fun printAllTiles(tiles: Tiles) { tiles.forEach { tile -> - print(tile.value) + print(viewTile(tile)) } } + + private fun viewTile(tile: Tile) = when (tile) { + Tile.GREEN -> "\uD83D\uDFE9" + Tile.YELLOW -> "\uD83D\uDFE8" + Tile.GRAY -> "⬜" + } } diff --git a/src/test/kotlin/wordle/domain/TileTest.kt b/src/test/kotlin/wordle/domain/TileTest.kt index 1a3f8cc..9ab6858 100644 --- a/src/test/kotlin/wordle/domain/TileTest.kt +++ b/src/test/kotlin/wordle/domain/TileTest.kt @@ -2,8 +2,6 @@ package wordle.domain import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test -import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.CsvSource class TileTest { @@ -11,10 +9,4 @@ class TileTest { fun `타일은 노란색, 초록색, 회색을 가진다`() { assertThat(Tile.values()).containsExactly(Tile.YELLOW, Tile.GREEN, Tile.GRAY) } - - @ParameterizedTest - @CsvSource("GRAY, \uD83D\uDFE8", "GREEN, \uD83D\uDFE9", "YELLOW, \uD83D\uDFE7") - fun `흰색 타일은 ⬜, 초록색 타일은 🟩, 노란색 타일은 🟨 값을 가진다`(tile: Tile, color: String) { - assertThat(tile.value).isEqualTo(color) - } } From 249415598f2645eb9bf886131487095fa40b3b2a Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:18:49 +0900 Subject: [PATCH 40/55] =?UTF-8?q?refactor:=20=EA=B2=B0=EA=B3=BC=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EB=A9=98=ED=8A=B8=20=EC=88=98=EC=A0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/controller/Application.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index 73c742d..946f7ca 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -38,7 +38,7 @@ private fun playGame(game: Game) { private fun checkIsWinner(game: Game, resultTiles: Tiles, index: Int) { if (game.isWinner(resultTiles)) { ResultView.printGamePlayCount(index) - throw IllegalStateException("게임이 종료되었습니다.") + throw IllegalStateException("정답을 맞추셨습니다.") } } From 605b476ec7ed9893c197c2137b1f6e3b7a71d1e1 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:22:13 +0900 Subject: [PATCH 41/55] =?UTF-8?q?refactor:=20Words=20=EC=9D=BC=EA=B8=89=20?= =?UTF-8?q?=EC=BB=AC=EB=A0=89=EC=85=98=20=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/domain/Answers.kt | 4 ++-- src/main/kotlin/wordle/domain/Words.kt | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/wordle/domain/Words.kt diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index 489c52c..2997543 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -11,7 +11,7 @@ class Answers { val WORDS = createWords() val ANSWER = createAnswer() - private fun createWords(): List { + private fun createWords(): Words { val wordsFile = getResourceText(ANSWERS_TEXT_PATH) val words = mutableListOf() @@ -19,7 +19,7 @@ class Answers { words.add(Word(it)) } - return words + return Words(words) } private fun createAnswer(): Word { diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt new file mode 100644 index 0000000..df501a3 --- /dev/null +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -0,0 +1,3 @@ +package wordle.domain + +class Words(private val words: List) : List by words From dd9930b94ad708bda9a351c4a8c296721faa0659 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Thu, 14 Apr 2022 22:27:04 +0900 Subject: [PATCH 42/55] =?UTF-8?q?refactor:=20=EC=BD=94=ED=8B=80=EB=A6=B0?= =?UTF-8?q?=20=ED=95=A8=EC=88=98=20=EC=82=AC=EC=9A=A9=ED=95=98=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/domain/Answers.kt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index 2997543..8f46cff 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -22,10 +22,7 @@ class Answers { return Words(words) } - private fun createAnswer(): Word { - return WORDS[(createAnswerPosition() % WORDS.size).toInt()] - } - + private fun createAnswer() = WORDS[(createAnswerPosition() % WORDS.size).toInt()] private fun createAnswerPosition() = ChronoUnit.DAYS.between(LocalDate.of(2021, 6, 19), LocalDate.now()) } } From 828fb3415bd2f8bef43e1888c87e1f3f5da7b053 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:33:40 +0900 Subject: [PATCH 43/55] =?UTF-8?q?refactor:=20=EC=A1=B0=EA=B1=B4=EB=AC=B8?= =?UTF-8?q?=EC=9D=84=20=EA=B0=84=EA=B2=B0=ED=95=98=EA=B2=8C=20=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=B6=88?= =?UTF-8?q?=ED=95=84=EC=9A=94=ED=95=9C=20delicate=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/domain/Tiles.kt | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Tiles.kt b/src/main/kotlin/wordle/domain/Tiles.kt index 65ba7aa..cd11ea7 100644 --- a/src/main/kotlin/wordle/domain/Tiles.kt +++ b/src/main/kotlin/wordle/domain/Tiles.kt @@ -1,15 +1,12 @@ package wordle.domain -class Tiles(private val tiles: List) : List by tiles { +@JvmInline +value class Tiles(val tiles: List) { fun isWinner(): Boolean { val count = tiles.count { it == Tile.GREEN } - if (count == TOTAL_TILE_COUNT) { - return true - } - - return false + return count == TOTAL_TILE_COUNT } companion object { From 155f16a415ff668dff2bbd2a3555f17e46b13867 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:33:49 +0900 Subject: [PATCH 44/55] =?UTF-8?q?refactor:=20delicate=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=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/view/ResultView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index 4174398..0e29509 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -17,14 +17,14 @@ object ResultView { println() } - fun printAllResults(results: MutableList) { + fun printAllResults(results: List) { results.forEach { - printAllTiles(it) + printAllTiles(it.tiles) println() } } - private fun printAllTiles(tiles: Tiles) { + private fun printAllTiles(tiles: List) { tiles.forEach { tile -> print(viewTile(tile)) } From 72ebdb837071752e556f1f3480344cd746c9389c Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:34:22 +0900 Subject: [PATCH 45/55] =?UTF-8?q?feat:=20=EA=B2=B0=EA=B3=BC=EB=AC=BC?= =?UTF-8?q?=EC=9D=84=20=EB=A7=8C=EB=93=A4=EC=96=B4=EB=82=B4=EA=B8=B0=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Results=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=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/domain/Results.kt | 11 +++++++++++ src/test/kotlin/wordle/domain/ResultsTest.kt | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/main/kotlin/wordle/domain/Results.kt create mode 100644 src/test/kotlin/wordle/domain/ResultsTest.kt diff --git a/src/main/kotlin/wordle/domain/Results.kt b/src/main/kotlin/wordle/domain/Results.kt new file mode 100644 index 0000000..12a5041 --- /dev/null +++ b/src/main/kotlin/wordle/domain/Results.kt @@ -0,0 +1,11 @@ +package wordle.domain + +class Results { + private val _results = mutableListOf() + val results: List + get() = _results + + fun combine(newResults: Tiles) { + _results.add(newResults) + } +} diff --git a/src/test/kotlin/wordle/domain/ResultsTest.kt b/src/test/kotlin/wordle/domain/ResultsTest.kt new file mode 100644 index 0000000..5a89fd4 --- /dev/null +++ b/src/test/kotlin/wordle/domain/ResultsTest.kt @@ -0,0 +1,20 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class ResultsTest { + + @Test + fun `기존에_존재하는_결과타일에_타일결과를_추가한다`() { + val results = Results() + + results.combine(Tiles(listOf(Tile.YELLOW, Tile.YELLOW, Tile.YELLOW, Tile.GRAY, Tile.YELLOW))) + results.combine(Tiles(listOf(Tile.GREEN, Tile.GRAY, Tile.GREEN, Tile.GRAY, Tile.YELLOW))) + + assertThat(results.results).containsExactly( + Tiles(listOf(Tile.YELLOW, Tile.YELLOW, Tile.YELLOW, Tile.GRAY, Tile.YELLOW)), + Tiles(listOf(Tile.GREEN, Tile.GRAY, Tile.GREEN, Tile.GRAY, Tile.YELLOW)) + ) + } +} From f57b1e550aa43b69b5c00aeba5ac028d18a482c2 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:38:33 +0900 Subject: [PATCH 46/55] =?UTF-8?q?refactor:=20word=20=EB=A5=BC=20=EB=A7=A4?= =?UTF-8?q?=EB=B2=88=20=EC=83=9D=EC=84=B1=EA=B0=80=EB=8A=A5=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=202021.6.19?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=83=81=EC=88=98=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/wordle/controller/Application.kt | 36 ++++++++----------- src/main/kotlin/wordle/domain/Answers.kt | 20 +++++++---- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index 946f7ca..f58b3e8 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -2,17 +2,15 @@ package wordle.controller import wordle.domain.Answers import wordle.domain.Game -import wordle.domain.Tiles +import wordle.domain.Results import wordle.domain.Word import wordle.view.InputView import wordle.view.ResultView -import java.io.File -private const val START_PLAY_COUNT = 1 -private const val LAST_PLAY_COUNT = 7 +private const val LAST_PLAY_COUNT = 6 fun main() { - val game = Game(Answers.ANSWER) + val game = Game(Answers().answer) ResultView.printInit() @@ -20,28 +18,22 @@ fun main() { } private fun playGame(game: Game) { - val results = mutableListOf() + val results = Results() - (START_PLAY_COUNT until LAST_PLAY_COUNT).forEachIndexed { _, index -> - val inputWord = InputView.askWord(Answers.WORDS) + var tryCount = 0 + while (tryCount < LAST_PLAY_COUNT) { + val inputWord = InputView.askWord(Answers.WORDS) val resultTiles = game.play(Word(inputWord)) + results.combine(resultTiles) - results.add(resultTiles) + ResultView.printAllResults(results.results) - ResultView.printAllResults(results) + tryCount++ - checkIsWinner(game, resultTiles, index) + if (game.isWinner(resultTiles)) { + ResultView.printGamePlayCount(tryCount) + break + } } } - -private fun checkIsWinner(game: Game, resultTiles: Tiles, index: Int) { - if (game.isWinner(resultTiles)) { - ResultView.printGamePlayCount(index) - throw IllegalStateException("정답을 맞추셨습니다.") - } -} - -fun getResourceText(path: String): File { - return File(ClassLoader.getSystemResource(path).file) -} diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index 8f46cff..a41f0d9 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -1,28 +1,36 @@ package wordle.domain -import wordle.controller.getResourceText +import java.io.File import java.time.LocalDate import java.time.temporal.ChronoUnit class Answers { + val answer: Word + get() = createAnswer() + + private fun createAnswer() = WORDS[(createAnswerPosition() % WORDS.size).toInt()] companion object { - private const val ANSWERS_TEXT_PATH = "./words.txt" val WORDS = createWords() - val ANSWER = createAnswer() + private const val ANSWERS_TEXT_PATH = "./words.txt" + private val SUBTRACT_DATE_FOR_ANSWER = LocalDate.of(2021, 6, 19) private fun createWords(): Words { - val wordsFile = getResourceText(ANSWERS_TEXT_PATH) + val wordsFile = getResourceText() val words = mutableListOf() wordsFile.forEachLine { words.add(Word(it)) } + return Words(words) } - private fun createAnswer() = WORDS[(createAnswerPosition() % WORDS.size).toInt()] - private fun createAnswerPosition() = ChronoUnit.DAYS.between(LocalDate.of(2021, 6, 19), LocalDate.now()) + private fun createAnswerPosition() = ChronoUnit.DAYS.between(SUBTRACT_DATE_FOR_ANSWER, LocalDate.now()) + + private fun getResourceText(): File { + return File(ClassLoader.getSystemResource(ANSWERS_TEXT_PATH).file) + } } } From 64f24a9284d0c2db1fe3e03ecc6f75eb6d281e5f Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:38:49 +0900 Subject: [PATCH 47/55] refactor: klint --- src/main/kotlin/wordle/domain/Answers.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index a41f0d9..eb75e47 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -23,7 +23,6 @@ class Answers { words.add(Word(it)) } - return Words(words) } From 5bce301d0204e4e8367e179b11cc351f4909bcde Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:40:20 +0900 Subject: [PATCH 48/55] =?UTF-8?q?refactor:=20readlin()=20=EC=9C=BC?= =?UTF-8?q?=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/view/InputView.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/wordle/view/InputView.kt b/src/main/kotlin/wordle/view/InputView.kt index 61d04c9..152d98d 100644 --- a/src/main/kotlin/wordle/view/InputView.kt +++ b/src/main/kotlin/wordle/view/InputView.kt @@ -6,7 +6,7 @@ object InputView { fun askWord(words: List): String { while (true) { - val input = question("정답을 입력해 주세요.") + val input = question() if (words.contains(Word(input))) { return input } @@ -15,8 +15,8 @@ object InputView { } } - private tailrec fun question(question: String): String { - println(question) - return readLine() ?: question(question) + private fun question(): String { + println("정답을 입력해 주세요.") + return readln() } } From e544c0f37c4af9379b7490f7276fbfc4f60aa426 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 15:49:12 +0900 Subject: [PATCH 49/55] =?UTF-8?q?refactor:=20results=EB=A5=BC=20ResultView?= =?UTF-8?q?=20=EC=97=90=EC=84=9C=20=EA=B0=80=EC=A0=B8=EB=8B=A4=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=ED=95=98=EB=8F=84=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/controller/Application.kt | 2 +- src/main/kotlin/wordle/view/ResultView.kt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index f58b3e8..adf76ef 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -27,7 +27,7 @@ private fun playGame(game: Game) { val resultTiles = game.play(Word(inputWord)) results.combine(resultTiles) - ResultView.printAllResults(results.results) + ResultView.printAllResults(results) tryCount++ diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index 0e29509..5681b39 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -1,7 +1,7 @@ package wordle.view +import wordle.domain.Results import wordle.domain.Tile -import wordle.domain.Tiles private const val MAX_TRY_COUNT = 6 @@ -17,8 +17,8 @@ object ResultView { println() } - fun printAllResults(results: List) { - results.forEach { + fun printAllResults(results: Results) { + results.results.forEach { printAllTiles(it.tiles) println() } From c0633eb49f2d284d85f5f6dfc5a352070cdf0e8e Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 16:05:29 +0900 Subject: [PATCH 50/55] =?UTF-8?q?refactor:=20mutableList=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=EB=B6=88?= =?UTF-8?q?=EB=B3=80=ED=98=95=ED=83=9C=EB=A1=9C=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/Answers.kt | 10 ++-------- src/main/kotlin/wordle/domain/Game.kt | 8 +------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index eb75e47..9f81299 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -16,14 +16,8 @@ class Answers { private val SUBTRACT_DATE_FOR_ANSWER = LocalDate.of(2021, 6, 19) private fun createWords(): Words { - val wordsFile = getResourceText() - - val words = mutableListOf() - wordsFile.forEachLine { - words.add(Word(it)) - } - - return Words(words) + val wordsFile = getResourceText().readLines() + return Words(wordsFile.map { Word(it) }) } private fun createAnswerPosition() = ChronoUnit.DAYS.between(SUBTRACT_DATE_FOR_ANSWER, LocalDate.now()) diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index 5ce997f..cd47129 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -16,13 +16,7 @@ class Game(private val answer: Word) { } private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): Tiles { - val resultTiles = mutableListOf() - - inputChars.forEachIndexed { index, it -> - resultTiles.add(wordMatcher.match(it.toString(), index)) - } - - return Tiles(resultTiles) + return Tiles(inputChars.mapIndexed { index, it -> wordMatcher.match(it.toString(), index) }) } fun isWinner(resultTiles: Tiles): Boolean { From 7e674358824b561e547c5e6cc6cc8bfc0198621a Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 16:20:23 +0900 Subject: [PATCH 51/55] =?UTF-8?q?refactor:=20Words=20=EC=9D=BC=EA=B8=89?= =?UTF-8?q?=EC=BB=AC=EB=A0=89=EC=85=98=20=EC=B6=94=EA=B0=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=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/domain/Answers.kt | 7 +------ src/main/kotlin/wordle/domain/Words.kt | 20 +++++++++++++++++++- src/main/kotlin/wordle/view/InputView.kt | 6 +++--- src/test/kotlin/wordle/domain/WordsTest.kt | 18 ++++++++++++++++++ 4 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 src/test/kotlin/wordle/domain/WordsTest.kt diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index 9f81299..1547ff9 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -1,27 +1,22 @@ package wordle.domain import java.io.File -import java.time.LocalDate -import java.time.temporal.ChronoUnit class Answers { val answer: Word get() = createAnswer() - private fun createAnswer() = WORDS[(createAnswerPosition() % WORDS.size).toInt()] + private fun createAnswer() = WORDS.findAnswer() companion object { val WORDS = createWords() private const val ANSWERS_TEXT_PATH = "./words.txt" - private val SUBTRACT_DATE_FOR_ANSWER = LocalDate.of(2021, 6, 19) private fun createWords(): Words { val wordsFile = getResourceText().readLines() return Words(wordsFile.map { Word(it) }) } - private fun createAnswerPosition() = ChronoUnit.DAYS.between(SUBTRACT_DATE_FOR_ANSWER, LocalDate.now()) - private fun getResourceText(): File { return File(ClassLoader.getSystemResource(ANSWERS_TEXT_PATH).file) } diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index df501a3..00f4bdc 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -1,3 +1,21 @@ package wordle.domain -class Words(private val words: List) : List by words +import java.time.LocalDate +import java.time.temporal.ChronoUnit + +class Words(private val words: List) { + + fun findAnswer(): Word { + return words[(findAnswerPosition() % words.size).toInt()] + } + + private fun findAnswerPosition() = ChronoUnit.DAYS.between(SUBTRACT_DATE_FOR_ANSWER, LocalDate.now()) + + fun contains(value: String): Boolean { + return words.contains(Word(value)) + } + + companion object { + private val SUBTRACT_DATE_FOR_ANSWER = LocalDate.of(2021, 6, 19) + } +} diff --git a/src/main/kotlin/wordle/view/InputView.kt b/src/main/kotlin/wordle/view/InputView.kt index 152d98d..6b5011b 100644 --- a/src/main/kotlin/wordle/view/InputView.kt +++ b/src/main/kotlin/wordle/view/InputView.kt @@ -1,13 +1,13 @@ package wordle.view -import wordle.domain.Word +import wordle.domain.Words object InputView { - fun askWord(words: List): String { + fun askWord(words: Words): String { while (true) { val input = question() - if (words.contains(Word(input))) { + if (words.contains(input)) { return input } diff --git a/src/test/kotlin/wordle/domain/WordsTest.kt b/src/test/kotlin/wordle/domain/WordsTest.kt new file mode 100644 index 0000000..b41e478 --- /dev/null +++ b/src/test/kotlin/wordle/domain/WordsTest.kt @@ -0,0 +1,18 @@ +package wordle.domain + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test +import wordle.domain.Answers.Companion.WORDS + +class WordsTest { + + @Test + fun `오늘의 정답이 맞는지 확인한다`() { + val words = WORDS + val answer = words.findAnswer() + + println(answer) + + assertThat(answer).isNotNull + } +} From 842c92e686919b4de4850866e29f678f532a3f63 Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 17:34:33 +0900 Subject: [PATCH 52/55] =?UTF-8?q?refactor:=20kotlin=20extension=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=EB=A1=9C=20=EB=B3=80=EA=B2=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/view/ResultView.kt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index 5681b39..8ed8f79 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -6,6 +6,7 @@ import wordle.domain.Tile private const val MAX_TRY_COUNT = 6 object ResultView { + fun printInit() { println("WORDLE을 ${MAX_TRY_COUNT}번 만에 맞춰 보세요.") println("시도의 결과는 타일의 색 변화로 나타납니다.") @@ -26,13 +27,16 @@ object ResultView { private fun printAllTiles(tiles: List) { tiles.forEach { tile -> - print(viewTile(tile)) + print(tile.viewTile()) } } - private fun viewTile(tile: Tile) = when (tile) { - Tile.GREEN -> "\uD83D\uDFE9" - Tile.YELLOW -> "\uD83D\uDFE8" - Tile.GRAY -> "⬜" - } + private val Tile.viewTile: () -> String + get() = { + when (this) { + Tile.GREEN -> "\uD83D\uDFE9" + Tile.YELLOW -> "\uD83D\uDFE8" + Tile.GRAY -> "⬜" + } + } } From 0fcd81e008b8c9934929ef452cc82eb9446f34ae Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 22:48:48 +0900 Subject: [PATCH 53/55] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20println=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/view/ResultView.kt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/wordle/view/ResultView.kt b/src/main/kotlin/wordle/view/ResultView.kt index 8ed8f79..601cf0f 100644 --- a/src/main/kotlin/wordle/view/ResultView.kt +++ b/src/main/kotlin/wordle/view/ResultView.kt @@ -8,14 +8,11 @@ private const val MAX_TRY_COUNT = 6 object ResultView { fun printInit() { - println("WORDLE을 ${MAX_TRY_COUNT}번 만에 맞춰 보세요.") - println("시도의 결과는 타일의 색 변화로 나타납니다.") + println("WORDLE을 ${MAX_TRY_COUNT}번 만에 맞춰 보세요.\n시도의 결과는 타일의 색 변화로 나타납니다.") } fun printGamePlayCount(index: Int) { - print(index) - print("/$MAX_TRY_COUNT") - println() + println("$index /$MAX_TRY_COUNT") } fun printAllResults(results: Results) { From 293c4b6ee31189ffeefc3a4ce7528e5849c7e48b Mon Sep 17 00:00:00 2001 From: sgkim94 Date: Fri, 15 Apr 2022 23:14:16 +0900 Subject: [PATCH 54/55] =?UTF-8?q?refactor:=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81=20=EB=B0=8F=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=ED=95=84=EC=9A=94=ED=95=9C=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=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/controller/Application.kt | 4 +++- src/main/kotlin/wordle/domain/Answers.kt | 4 +++- src/main/kotlin/wordle/domain/Game.kt | 8 +------- src/main/kotlin/wordle/domain/Results.kt | 2 ++ src/main/kotlin/wordle/domain/Word.kt | 1 + src/main/kotlin/wordle/domain/Words.kt | 1 + 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index adf76ef..fea38bf 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -25,12 +25,14 @@ private fun playGame(game: Game) { while (tryCount < LAST_PLAY_COUNT) { val inputWord = InputView.askWord(Answers.WORDS) val resultTiles = game.play(Word(inputWord)) + + // 리펙토링 필요 results.combine(resultTiles) - ResultView.printAllResults(results) tryCount++ + // 게임을 종료하는 부분인데 if (game.isWinner(resultTiles)) { ResultView.printGamePlayCount(tryCount) break diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index 1547ff9..d5c63c3 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -9,14 +9,16 @@ class Answers { private fun createAnswer() = WORDS.findAnswer() companion object { - val WORDS = createWords() + // 선언 위치 확인 필요 private const val ANSWERS_TEXT_PATH = "./words.txt" + val WORDS = createWords() private fun createWords(): Words { val wordsFile = getResourceText().readLines() return Words(wordsFile.map { Word(it) }) } + // 파일 읽는 부분만 목킹이 되면 될 듯 private fun getResourceText(): File { return File(ClassLoader.getSystemResource(ANSWERS_TEXT_PATH).file) } diff --git a/src/main/kotlin/wordle/domain/Game.kt b/src/main/kotlin/wordle/domain/Game.kt index cd47129..5fe7bbe 100644 --- a/src/main/kotlin/wordle/domain/Game.kt +++ b/src/main/kotlin/wordle/domain/Game.kt @@ -6,13 +6,7 @@ class Game(private val answer: Word) { val inputChars = input.value.toCharArray() val wordMatcher = WordMatcher(answer) - val resultTiles = createResultTiles(inputChars, wordMatcher) - - if (resultTiles.isWinner()) { - return resultTiles - } - - return resultTiles + return createResultTiles(inputChars, wordMatcher) } private fun createResultTiles(inputChars: CharArray, wordMatcher: WordMatcher): Tiles { diff --git a/src/main/kotlin/wordle/domain/Results.kt b/src/main/kotlin/wordle/domain/Results.kt index 12a5041..dd6fe91 100644 --- a/src/main/kotlin/wordle/domain/Results.kt +++ b/src/main/kotlin/wordle/domain/Results.kt @@ -1,10 +1,12 @@ package wordle.domain +// 불변 보장 필요 class Results { private val _results = mutableListOf() val results: List get() = _results + // 더 나은 메서드명이 있지 않을까? fun combine(newResults: Tiles) { _results.add(newResults) } diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index 7e88163..e6acdb2 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -12,6 +12,7 @@ value class Word(val value: String) { private fun isWordSizeAndAlphabet() = value.length == WORD_SIZE && ALPHABET_REGEX.matches(value) fun findAlphabet(index: Int): String { + // require 변경해야 됨 if (index < FIRST_INDEX || index > value.length) { throw IllegalArgumentException(INDEX_OUT_RANGE_MESSAGE) } diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index 00f4bdc..3ef063a 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -3,6 +3,7 @@ package wordle.domain import java.time.LocalDate import java.time.temporal.ChronoUnit +// 전략패턴 필요 class Words(private val words: List) { fun findAnswer(): Word { From c40742d779d4435b8d047ea3993e97051fcf0675 Mon Sep 17 00:00:00 2001 From: etff Date: Sat, 16 Apr 2022 13:41:11 +0900 Subject: [PATCH 55/55] =?UTF-8?q?refactor:=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20-=20=EC=A3=BC=EC=84=9D=EB=82=B4=EC=97=AD?= =?UTF-8?q?=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/wordle/controller/Application.kt | 5 +---- src/main/kotlin/wordle/domain/Answers.kt | 2 -- src/main/kotlin/wordle/domain/Results.kt | 2 -- src/main/kotlin/wordle/domain/Word.kt | 5 ++--- src/main/kotlin/wordle/domain/Words.kt | 1 - 5 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/wordle/controller/Application.kt b/src/main/kotlin/wordle/controller/Application.kt index fea38bf..aa8aec8 100644 --- a/src/main/kotlin/wordle/controller/Application.kt +++ b/src/main/kotlin/wordle/controller/Application.kt @@ -25,14 +25,11 @@ private fun playGame(game: Game) { while (tryCount < LAST_PLAY_COUNT) { val inputWord = InputView.askWord(Answers.WORDS) val resultTiles = game.play(Word(inputWord)) - - // 리펙토링 필요 + results.combine(resultTiles) ResultView.printAllResults(results) - tryCount++ - // 게임을 종료하는 부분인데 if (game.isWinner(resultTiles)) { ResultView.printGamePlayCount(tryCount) break diff --git a/src/main/kotlin/wordle/domain/Answers.kt b/src/main/kotlin/wordle/domain/Answers.kt index d5c63c3..204d78b 100644 --- a/src/main/kotlin/wordle/domain/Answers.kt +++ b/src/main/kotlin/wordle/domain/Answers.kt @@ -9,7 +9,6 @@ class Answers { private fun createAnswer() = WORDS.findAnswer() companion object { - // 선언 위치 확인 필요 private const val ANSWERS_TEXT_PATH = "./words.txt" val WORDS = createWords() @@ -18,7 +17,6 @@ class Answers { return Words(wordsFile.map { Word(it) }) } - // 파일 읽는 부분만 목킹이 되면 될 듯 private fun getResourceText(): File { return File(ClassLoader.getSystemResource(ANSWERS_TEXT_PATH).file) } diff --git a/src/main/kotlin/wordle/domain/Results.kt b/src/main/kotlin/wordle/domain/Results.kt index dd6fe91..12a5041 100644 --- a/src/main/kotlin/wordle/domain/Results.kt +++ b/src/main/kotlin/wordle/domain/Results.kt @@ -1,12 +1,10 @@ package wordle.domain -// 불변 보장 필요 class Results { private val _results = mutableListOf() val results: List get() = _results - // 더 나은 메서드명이 있지 않을까? fun combine(newResults: Tiles) { _results.add(newResults) } diff --git a/src/main/kotlin/wordle/domain/Word.kt b/src/main/kotlin/wordle/domain/Word.kt index e6acdb2..a75ec24 100644 --- a/src/main/kotlin/wordle/domain/Word.kt +++ b/src/main/kotlin/wordle/domain/Word.kt @@ -12,9 +12,8 @@ value class Word(val value: String) { private fun isWordSizeAndAlphabet() = value.length == WORD_SIZE && ALPHABET_REGEX.matches(value) fun findAlphabet(index: Int): String { - // require 변경해야 됨 - if (index < FIRST_INDEX || index > value.length) { - throw IllegalArgumentException(INDEX_OUT_RANGE_MESSAGE) + require(index >= FIRST_INDEX && index <= value.length) { + INDEX_OUT_RANGE_MESSAGE } return value[index].toString() diff --git a/src/main/kotlin/wordle/domain/Words.kt b/src/main/kotlin/wordle/domain/Words.kt index 3ef063a..00f4bdc 100644 --- a/src/main/kotlin/wordle/domain/Words.kt +++ b/src/main/kotlin/wordle/domain/Words.kt @@ -3,7 +3,6 @@ package wordle.domain import java.time.LocalDate import java.time.temporal.ChronoUnit -// 전략패턴 필요 class Words(private val words: List) { fun findAnswer(): Word {