-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Wordle] 조조그린(조한석) 미션 제출합니다. #9
base: main
Are you sure you want to change the base?
Changes from all commits
a07ca44
13a13cf
c1d7d33
778f9c1
0782fbf
58cbf75
551f64f
f0c74c9
d9a554d
8f1f5f0
5422144
b496176
baf4d46
1645893
c945e41
edb8423
ababa6c
9c78be6
3d66ad9
e2a6511
a89d190
eb826ab
cd01e8f
e48beb2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import wordle.controller.WordleController | ||
|
||
fun main() { | ||
WordleController().run() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package wordle.controller | ||
|
||
import wordle.domain.Answer | ||
import wordle.domain.Game | ||
import wordle.domain.pickTodayWord | ||
import wordle.view.inputAnswer | ||
import wordle.view.printResults | ||
import wordle.view.printStartMessage | ||
import java.time.LocalDate | ||
|
||
class WordleController { | ||
|
||
fun run() { | ||
printStartMessage() | ||
val game = Game(LocalDate.now().pickTodayWord()) | ||
while (game.isPlaying) { | ||
game.playRound(Answer(inputAnswer())) | ||
printResults(game) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package wordle.domain | ||
|
||
import wordle.domain.Mark.* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요렇게 wildcard import 사용하면 ktlintCheck 에러 떠요! https://blog.leocat.kr/notes/2020/12/14/intellij-avoid-wildcard-imports-in-kotlin-with-intellij 요 블로그 참고하심 좋을 것 같아요! 나머지 에러 두 개는 import 순서 때문에 뜨네요. 포매팅 해주시면 에러 없앨 수 있을 것 같습니다! |
||
|
||
class Answer(private val answer: String) { | ||
|
||
init { | ||
require(answer.length == WORD_SIZE) { "[ERROR] 부적절한 글자 길이입니다." } | ||
require(answer.isInWords()) { "[ERROR] 목록에 존재하지 않는 단어입니다." } | ||
} | ||
|
||
fun compareToWord(word: String): List<Mark> { | ||
val result = MutableList(WORD_SIZE) { NONE } | ||
val wordTable = createWordTable(word) | ||
matchExact(word, result, wordTable) | ||
matchExist(result, wordTable) | ||
return result | ||
} | ||
|
||
private fun createWordTable(word: String): HashMap<Char, Int> { | ||
val wordTable = HashMap<Char, Int>() | ||
for (char in word) { | ||
wordTable[char] = wordTable.getOrDefault(char, 0) + 1 | ||
} | ||
Comment on lines
+22
to
+24
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return wordTable | ||
} | ||
|
||
private fun matchExact(word: String, result: MutableList<Mark>, wordTable: HashMap<Char, Int>) { | ||
for (i in 0 until WORD_SIZE) { | ||
markExact(i, word, result, wordTable) | ||
} | ||
} | ||
|
||
private fun markExact(i: Int, word: String, result: MutableList<Mark>, wordTable: HashMap<Char, Int>) { | ||
if (word[i] == answer[i]) { | ||
result[i] = EXACT | ||
wordTable.computeIfPresent(word[i]) { _, v -> v - 1 } | ||
} | ||
} | ||
|
||
private fun matchExist(result: MutableList<Mark>, wordTable: HashMap<Char, Int>) { | ||
for (index in 0 until WORD_SIZE) { | ||
markExist(index, result, wordTable) | ||
} | ||
} | ||
|
||
private fun markExist(index: Int, result: MutableList<Mark>, wordTable: HashMap<Char, Int>) { | ||
if (isExist(index, result, wordTable, answer[index])) { | ||
result[index] = EXIST | ||
wordTable.computeIfPresent(answer[index]) { _, v -> v - 1 } | ||
} | ||
} | ||
|
||
private fun isExist( | ||
index: Int, | ||
result: MutableList<Mark>, | ||
wordTable: HashMap<Char, Int>, | ||
charOfAnswer: Char, | ||
) = result[index] == NONE && wordTable.containsKey(charOfAnswer) && wordTable[charOfAnswer] != 0 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package wordle.domain | ||
|
||
class Game(private val word: String) { | ||
|
||
val results: Results = Results() | ||
var isPlaying: Boolean = true | ||
private set | ||
|
||
fun playRound(answer: Answer) { | ||
val result = answer.compareToWord(word) | ||
results.add(result) | ||
if (isOver(result)) { | ||
isPlaying = false | ||
} | ||
} | ||
|
||
private fun isOver(result: List<Mark>) = | ||
results.isLimit() || result.all { it == Mark.EXACT } | ||
|
||
fun findTryCount() = | ||
results.findTryCount() | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package wordle.domain | ||
|
||
enum class Mark { | ||
|
||
NONE, | ||
EXIST, | ||
EXACT | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package wordle.domain | ||
|
||
private const val LIMIT_SIZE = 6 | ||
|
||
class Results { | ||
|
||
private val _results: MutableList<List<Mark>> = mutableListOf() | ||
val results: List<List<Mark>> | ||
get() = _results | ||
|
||
fun add(result: List<Mark>) { | ||
_results.add(result) | ||
} | ||
Comment on lines
+7
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 내부에서는 MutableList를 외부에서는 List를 사용! 좋습니다! |
||
|
||
fun findTryCount() = | ||
_results.size | ||
|
||
fun isLimit() = | ||
_results.size >= LIMIT_SIZE | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package wordle.domain | ||
|
||
import java.io.FileReader | ||
import java.time.LocalDate | ||
import java.time.temporal.ChronoUnit | ||
|
||
const val WORD_SIZE = 5 | ||
|
||
val BASIC_DATE = LocalDate.of(2021, 6, 19)!! | ||
val WORDS = FileReader("src/main/resources/words.txt").readLines() | ||
|
||
fun LocalDate.pickTodayWord() = | ||
WORDS[(ChronoUnit.DAYS.between(BASIC_DATE, this) % WORDS.size).toInt()] | ||
|
||
fun String.isInWords() = | ||
WORDS.contains(this) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package wordle.view | ||
|
||
import wordle.domain.Mark.EXACT | ||
import wordle.domain.Mark.NONE | ||
import wordle.domain.Mark.EXIST | ||
import wordle.domain.Results | ||
import wordle.domain.Game | ||
import wordle.domain.Mark | ||
|
||
fun printStartMessage() { | ||
println("WORDLE 을 6번 만에 맞춰 보세요.\n시도의 결과는 타일의 색 변화로 나타납니다.") | ||
} | ||
|
||
private fun printInputMessage() { | ||
println("정답을 입력해 주세요.") | ||
} | ||
|
||
fun inputAnswer(): String { | ||
printInputMessage() | ||
return readln() | ||
} | ||
|
||
fun printResults(game: Game) { | ||
if (!game.isPlaying) { | ||
printTryCount(game.findTryCount()) | ||
} | ||
printTiles(game.results) | ||
} | ||
|
||
fun printTryCount(tryCount: Int) { | ||
println() | ||
println("$tryCount/6") | ||
} | ||
|
||
fun printTiles(results: Results) { | ||
println() | ||
results.results.forEach { | ||
printTile(it) | ||
} | ||
println() | ||
} | ||
|
||
private fun printTile(result: List<Mark>) { | ||
StringBuilder().apply { | ||
result.forEach { | ||
when (it) { | ||
NONE -> append("⬜") | ||
EXIST -> append("\uD83D\uDFE8") | ||
EXACT -> append("\uD83D\uDFE9") | ||
} | ||
} | ||
println(toString()) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package study | ||
|
||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
|
||
class DslTest { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. DslTest까지 구현해주셨네요ㅎㅎ 좋습니다! |
||
|
||
@Test | ||
fun introduce() { | ||
val person = introduce { | ||
name("조조그린") | ||
company("우아한테크코스") | ||
skills { | ||
soft("A passion for problem solving") | ||
soft("Good communication skills") | ||
hard("Java") | ||
} | ||
languages { | ||
"Korean" level 5 | ||
"English" level 3 | ||
} | ||
} | ||
|
||
assertThat(person.toString()).isEqualTo("Person(name=조조그린, company=우아한테크코스, skills=Skills(softSkills=[A passion for problem solving, Good communication skills], hardSkills=[Java]), languages=Languages(languages=[Korean level : 5, English level : 3]))") | ||
} | ||
} | ||
|
||
fun introduce(builder: PersonBuilder.() -> Unit): Person { | ||
return PersonBuilder().apply(builder).build() | ||
} | ||
|
||
class PersonBuilder { | ||
private lateinit var name: String | ||
private lateinit var company: String | ||
private lateinit var skills: Skills | ||
private lateinit var languages: Languages | ||
|
||
fun name(input: String) { | ||
name = input | ||
} | ||
|
||
fun company(input: String) { | ||
company = input | ||
} | ||
|
||
fun skills(builder: SkillsBuilder.() -> Unit) { | ||
skills = SkillsBuilder().apply(builder).build() | ||
} | ||
|
||
fun languages(builder: LanguagesBuilder.() -> Unit) { | ||
languages = LanguagesBuilder().apply(builder).build() | ||
} | ||
|
||
fun build(): Person { | ||
return Person(name, company, skills, languages) | ||
} | ||
} | ||
|
||
class SkillsBuilder { | ||
private val softSkills: MutableList<String> = mutableListOf() | ||
private val hardSkills: MutableList<String> = mutableListOf() | ||
|
||
fun soft(input: String) { | ||
this.softSkills.add(input) | ||
} | ||
|
||
fun hard(input: String) { | ||
this.hardSkills.add(input) | ||
} | ||
|
||
fun build(): Skills { | ||
return Skills(softSkills, hardSkills) | ||
} | ||
} | ||
|
||
class LanguagesBuilder { | ||
private var languages: MutableList<String> = mutableListOf() | ||
|
||
infix fun String.level(value: Int) { | ||
languages.add(plus(" level : ") + value) | ||
} | ||
|
||
fun build(): Languages { | ||
return Languages(languages) | ||
} | ||
} | ||
|
||
data class Person(val name: String, val company: String, val skills: Skills, val languages: Languages) | ||
|
||
data class Skills(val softSkills: List<String>, val hardSkills: List<String>) | ||
|
||
data class Languages(val languages: List<String>) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package wordle.domain | ||
|
||
import org.junit.jupiter.api.assertThrows | ||
import wordle.domain.Mark.EXACT | ||
import wordle.domain.Mark.NONE | ||
import wordle.domain.Mark.EXIST | ||
import io.kotest.matchers.throwable.shouldHaveMessage | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.jupiter.api.Test | ||
|
||
internal class AnswerTest { | ||
|
||
@Test | ||
fun 글자길이가_5가_아닌_경우_예외발생() { | ||
assertThrows<IllegalArgumentException> { Answer("abcdef") } | ||
.shouldHaveMessage("[ERROR] 부적절한 글자 길이입니다.") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
@Test | ||
fun 주어진_단어목록에_존재하지_않는_경우_예외발생() { | ||
assertThrows<IllegalArgumentException> { Answer("abcde") } | ||
.shouldHaveMessage("[ERROR] 목록에 존재하지 않는 단어입니다.") | ||
} | ||
|
||
@Test | ||
fun 답안과_정답을_비교_CASE_중복되는_문자_중_하나만_일치_할_때() { | ||
val answer = Answer("groom") | ||
|
||
assertThat(answer.compareToWord("goose")) | ||
.isEqualTo(listOf(EXACT, NONE, EXACT, EXIST, NONE)) | ||
} | ||
|
||
@Test | ||
fun 답안과_정답을_비교_CASE_중복되는_문자가_존재하지만_정답의_개수가_더_많을_때() { | ||
val answer = Answer("eerie") | ||
|
||
assertThat(answer.compareToWord("sheen")) | ||
.isEqualTo(listOf(EXIST, EXIST, NONE, NONE, NONE)) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ktlintCheck가 실패합니다ㅠ_ㅠ 한 번 확인하시고 수정해야할 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 계속 수정하는데 자꾸 새로운게 튀어나오고 지적하는 부분이 뭘 수정하라는 건지 모르겠네요ㅠㅠ
일단 계속 해볼게요 파랑🥲