Skip to content
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] 애쉬(김동호) 미션 제출합니다. #6

Open
wants to merge 24 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3208e76
docs: 기능 목록 작성
dongho108 May 11, 2022
a6bfd74
feat: 단어 생성 기능 추가
dongho108 May 11, 2022
5ecc453
feat: 정답 단어를 반환하는 기능 추가
dongho108 May 11, 2022
ae9220f
feat: 정답매칭기능 구현
dongho108 May 11, 2022
693fd1d
feat: 최대 6번까지 단어를 매칭하능 기능 구현
dongho108 May 11, 2022
977e755
feat: 플레이어의 입력으로 게임이 진행되도록 구현
dongho108 May 11, 2022
2bf267f
refactor: 변수명 수정
dongho108 May 11, 2022
4a32fdc
style: 변수 위치 수정
dongho108 May 11, 2022
6a91799
refactor: round를 game으로부터 받도록 수정
dongho108 May 11, 2022
960f8a4
style: kotlin 컨벤션에 맞게 수정
dongho108 May 11, 2022
4558c6f
refactor: 메서드 순서 변경
dongho108 May 12, 2022
0f59d95
rename: WordResponse -> WordReader
dongho108 May 15, 2022
22fb216
refactor: 반복문을 mapIndexedNotNull api를 이용하도록 수정
dongho108 May 15, 2022
f7572be
refactor: 변수 두개로 getter 만들던 코드 private set으로 수정
dongho108 May 15, 2022
e1e554c
test: kotest로 마이그레이션
dongho108 May 15, 2022
255eb1c
style: 중괄호 앞뒤에 공백 추가
dongho108 May 15, 2022
884db31
feat: dsl 실습 추가
dongho108 May 19, 2022
80b6701
feat: study 패키지 분리 및 data clas 테스트 추가
dongho108 May 25, 2022
12b5126
refactor: 외부에 companion object의 MAX_ROUND를 공개하도록 수정
dongho108 May 25, 2022
07e75fa
refactor: ArrayList의 InitialCapacity를 미리 지정하도록 수정
dongho108 May 26, 2022
cb2b7c6
refactor: Word로부터 GameResult의 size를 결정하도록 수정
dongho108 May 26, 2022
b58d199
refactor: word 검증메서드들 확장함수로 변경
dongho108 May 26, 2022
126673e
refactor: 메서드명 더 명확하게 변경
dongho108 May 26, 2022
1c4ec1a
refactor: Regex를 미리 생성해 사용하도록 수정
dongho108 May 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,29 @@

---

🛠 기능 목록
- [x] 정답 매칭
- [x] 판별 결과는 타일로 알려준다.
- [x] 정답은 `words.txt`의 ((현재 날짜 - 2021년 6월 19일) % `words.txt`의 단어 개수) 번째의 단어이다.
- [x] 매칭 결과
- [x] 플레이어 답과 정답 사이 한 글자의 스펠과 위치가 같은 경우 `초록색 타일`로 나타낸다.
- [x] 플레이어 답과 정답 사이 한 글자의 스펠은 같지만 위치가 다른 경우 `노란색 타일`로 나타낸다.
- [x] 플레이어 답과 정답 사이 한 글자의 스펠과 위치가 모두 다른 경우 `회색 타일`로 나타낸다.
- [x] 타일
- [x] 초록색, 노란색, 회색
- [x] 단어
- [x] 단어는 5글자이다.
- [x] 단어는 영단어이다.
- [x] 게임
- [x] 최대 6번까지 답안을 제출할 수 있다.
- [x] 정답은 `words.txt`의 ((현재 날짜 - 2021년 6월 19일) % `words.txt`의 단어 개수) 번째의 단어이다.
- [x] 단어는 `words.txt`에 포함된 단어여야 한다.
- [x] 답안을 6번 제출하면 게임을 종료한다.
- [x] 6번 안에 정답을 맞추면 종료한다.
- [x] 플레이어는 답을 입력한다.
- [x] 답을 입력할때마다 매칭된 누적 타일을 반환한다.
- [x] 게임이 종료되면 시도횟수를 반환한다.

## 🚀 기능 요구 사항

선풍적인 인기를 끌었던 영어 단어 맞추기 게임이다.
Expand Down
35 changes: 35 additions & 0 deletions src/main/kotlin/wordle/Application.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package wordle

import wordle.domain.Game
import wordle.domain.GameResult
import wordle.domain.Word
import wordle.domain.Words
import wordle.domain.WordsReader
import wordle.view.InputView
import wordle.view.OutputView
import java.time.LocalDate

fun main() {

val wordsReader = WordsReader("words.txt")
val words = Words(wordsReader.words)
val game = Game(words, LocalDate.now())
val gameResult = GameResult(Word.SIZE)

OutputView.printInitMessage(Game.MAX_ROUND)
play(game, gameResult)
}

private fun play(game: Game, gameResult: GameResult) {
return try {
while (!game.isOver) {
val playerWord = Word(InputView.requestAnswer())
val matchResult = game.matchResult(playerWord)
gameResult.add(matchResult)
OutputView.printGameResult(game.isOver, game.count, Game.MAX_ROUND, gameResult)
}
} catch (exception: IllegalArgumentException) {
OutputView.printErrorMessage(exception.message)
play(game, gameResult)
}
}
42 changes: 42 additions & 0 deletions src/main/kotlin/wordle/domain/Game.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package wordle.domain

import java.time.LocalDate

data class Game(val words: Words, val date: LocalDate) {

var count: Int = 0
private set
var isOver: Boolean = false
private set

fun matchResult(playerWord: Word): Tiles {
require(words.contains(playerWord)) { "[ERROR] words.txt에 있는 단어를 입력해주세요." }
val tiles = playerWord.value.withIndex()
.mapIndexedNotNull { index, tile -> matchSpell(tile.value, index) }
count++
val newTiles = Tiles(tiles)
updateIsOver(newTiles)
return newTiles
}

private fun matchSpell(spell: Char, index: Int): Tile {
val answer = words.findAnswer(date)
if (answer.isSameIndexAndSpell(index, spell)) {
return Tile.GREEN
}
if (answer.contains(spell)) {
return Tile.YELLOW
}
return Tile.GRAY
}

private fun updateIsOver(newTiles: Tiles) {
dongho108 marked this conversation as resolved.
Show resolved Hide resolved
if (count >= MAX_ROUND || newTiles.isAllGreen()) {
isOver = true
}
}

companion object {
const val MAX_ROUND = 6
}
}
11 changes: 11 additions & 0 deletions src/main/kotlin/wordle/domain/GameResult.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package wordle.domain

class GameResult(size: Int) {

var gameResult: MutableList<Tiles> = ArrayList(size)
private set

fun add(tiles: Tiles) {
this.gameResult.add(tiles)
}
}
12 changes: 12 additions & 0 deletions src/main/kotlin/wordle/domain/Tile.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package wordle.domain

enum class Tile(val symbol: String) {

GRAY("⬜"),
GREEN("\uD83D\uDFE9"),
YELLOW("\uD83D\uDFE8");

fun isGreen(): Boolean {
return this == GREEN
}
}
8 changes: 8 additions & 0 deletions src/main/kotlin/wordle/domain/Tiles.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package wordle.domain

data class Tiles(val tiles: List<Tile>) {
dongho108 marked this conversation as resolved.
Show resolved Hide resolved

fun isAllGreen(): Boolean {
return tiles.all { it.isGreen() }
}
}
22 changes: 22 additions & 0 deletions src/main/kotlin/wordle/domain/Word.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package wordle.domain

data class Word(val value: String) {

init {
require(value.isRightSize()) { "[ERROR] ${SIZE}글자의 단어를 입력하세요." }
require(value.isAlphabet()) { "[ERROR] 영어 단어를 입력하세요." }
}

private fun String.isRightSize(): Boolean = value.length == SIZE

private fun String.isAlphabet(): Boolean = PATTERN.matches(value)

fun isSameIndexAndSpell(index: Int, spell: Char): Boolean = value[index] == spell

fun contains(spell: Char): Boolean = value.contains(spell)

companion object {
const val SIZE = 5
private val PATTERN = Regex("^[a-zA-Z]*$")
}
}
20 changes: 20 additions & 0 deletions src/main/kotlin/wordle/domain/Words.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package wordle.domain

import java.time.LocalDate
import java.time.temporal.ChronoUnit

class Words(private val words: List<Word>) {

fun findAnswer(current: LocalDate): Word {
val answerIndex = ChronoUnit.DAYS.between(BASE_DATE, current)
return words[answerIndex.toInt()]
}

fun contains(word: Word): Boolean {
return words.contains(word)
}

companion object {
private val BASE_DATE = LocalDate.of(2021, 6, 19)
}
}
16 changes: 16 additions & 0 deletions src/main/kotlin/wordle/domain/WordsReader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package wordle.domain

import java.io.File

class WordsReader(private val path: String) {

val words: List<Word>
get() = getWords(path)

companion object {
private fun getWords(path: String): List<Word> {
return File(ClassLoader.getSystemResource(path).file).readLines()
.map { Word(it) }
}
}
}
11 changes: 11 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/Person.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package wordle.study.dsl.person

import wordle.study.dsl.person.language.Languages
import wordle.study.dsl.person.skill.Skills

data class Person(
val name: String,
val company: String,
val skills: Skills,
val languages: Languages
)
33 changes: 33 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/PersonBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package wordle.study.dsl.person

import wordle.study.dsl.person.language.Languages
import wordle.study.dsl.person.language.LanguagesBuilder
import wordle.study.dsl.person.skill.Skills
import wordle.study.dsl.person.skill.SkillsBuilder

class PersonBuilder {
private lateinit var name: String
private lateinit var company: String
private lateinit var skills: Skills
private lateinit var languages: Languages

fun name(value: String) {
name = value
}

fun company(value: String) {
company = value
}

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)
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/language/Language.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.language

data class Language(val language: String, val level: Int)
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/language/Languages.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.language

data class Languages(val languages: MutableList<Language>)
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package wordle.study.dsl.person.language

class LanguagesBuilder {
private var languages: MutableList<Language> = mutableListOf()

infix fun String.level(level: Int) {
languages.add(Language(this, level))
}

fun build(): Languages {
return Languages(languages)
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/skill/Hard.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.skill

data class Hard(override val name: String) : Skill(name)
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/skill/Skill.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.skill

abstract class Skill(open val name: String)
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/skill/Skills.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.skill

data class Skills(val skills: MutableList<Skill>)
17 changes: 17 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/skill/SkillsBuilder.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package wordle.study.dsl.person.skill

class SkillsBuilder {
private var skills: MutableList<Skill> = mutableListOf()

fun soft(value: String) {
skills.add(Soft(value))
}

fun hard(value: String) {
skills.add(Hard(value))
}

fun build(): Skills {
return Skills(skills)
}
}
3 changes: 3 additions & 0 deletions src/main/kotlin/wordle/study/dsl/person/skill/Soft.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package wordle.study.dsl.person.skill

data class Soft(override val name: String) : Skill(name)
10 changes: 10 additions & 0 deletions src/main/kotlin/wordle/view/InputView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package wordle.view

object InputView {

fun requestAnswer(): String {
println()
println("정답을 입력해 주세요.")
return readln()
}
}
33 changes: 33 additions & 0 deletions src/main/kotlin/wordle/view/OutputView.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package wordle.view

import wordle.domain.GameResult
import wordle.domain.Tiles

object OutputView {

fun printInitMessage(maxRound: Int) {
println("WORDLE을 ${maxRound}번 만에 맞춰 보세요.")
println("시도의 결과는 타일의 색 변화로 나타납니다.")
}

fun printGameResult(isOver: Boolean, count: Int, maxRound: Int, gameResult: GameResult) {
if (isOver) {
println("$count/$maxRound")
}
println()
gameResult.gameResult
.forEach {
printTiles(it)
println()
}
}

private fun printTiles(tiles: Tiles) {
tiles.tiles
.forEach { print(it.symbol) }
}

fun printErrorMessage(message: String?) {
println(message)
}
}
22 changes: 22 additions & 0 deletions src/test/kotlin/study/data/DataClassTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package study.data

import org.junit.jupiter.api.Test

class DataClassTest {
@Test
fun getter() {
val noDataClass = NoDataClass("NoDataClass")
val dataClass = DataClass("DataClass")

println(noDataClass.name)
println(dataClass.name)
}
}

class NoDataClass(val name: String) {
}


data class DataClass(val name:String) {
}

Loading