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

[4기][3주차] Wordle 과제 제출 - 분수 #25

Open
wants to merge 23 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 21 commits
Commits
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
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,41 @@
# 미션 - 워들
## 기능 요구 사항
* Letter
* [x] Letter 를 생성한다.
* [x] 알파벳만 입력 가능하다.
* [x] 알파벳이 아니면 에러를 발생한다.
* Words Generator
* [X] `words.txt`에서 Words 를 읽어온다.
* Word
* [x] Word 를 생성한다.
* [x] 5글자의 알파벳만 받는다.
* [x] 5글자가 아니면 에러를 발생한다.
* [x] 알파벳이 아니면 에러를 발생한다.
* Words
* [x] Words 를 생성한다.
* [x] 주어진 Words 가 비어있으면 에러를 발생한다.
* [x] 주어진 Words 에 Word 가 없다면 에러를 발생한다.
* [x] 정답을 가져온다.
* [x] ((현재 날짜 - 2021년 6월 19일) % 배열의 크기) 번째의 단어를 가져온다.
* 정답
* [x] 입력된 답안을 존재하는 Word 인지 비교한다.
* 답안
* [ ] 사용자가 워드를 입력한다.
* [ ] 글자는 5글자까지 입력 가능하다.
* [ ] 사용자가 정답을 6번까지 입력할 수 있다.
* [ ] 입력된 답안은 `words.txt`에 존재하는 단어여야 한다.
* 출력
* [ ] 타일로 결과를 표시한다.
* [ ] 위치와 글자가 맞으면 초록색
* [ ] 위치가 틀리고, 글자가 맞으면 노란색
* [ ] 위치와 글자가 틀리면 회색
* [ ] 두 개의 동일한 문자를 입력하고 그중 하나가 회색으로 표시되면 해당 문자 중 하나만 최종 단어에 나타난다.

## 유비쿼터스 언어
* Word
* 5글자의 영문
* Words
* `words.txt`의 리스트

## 🔍 진행 방식

Expand Down
9 changes: 9 additions & 0 deletions src/main/java/Application.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Controller, Service 네이밍을 통해서 MVC 패턴을 적용했다는 의도가 한번에 느껴지네요.👍

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import controller.GameController;
import service.GameService;

public class Application {
public static void main(String[] args) {
GameController gameController = new GameController(new GameService());
gameController.start();
}
}
6 changes: 6 additions & 0 deletions src/main/java/config/FileConfig.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FileConfig 클래스에서 file 관련 설정을 관리하셨네요. 이렇게 하면 추후 파일관련 내용이 추가되더라도 응집도 높은 코드를 작성할 수 있겠네요.😃

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package config;

public class FileConfig {

public final static String FILE_PATH = "src/main/resources/words.txt";
}
22 changes: 22 additions & 0 deletions src/main/java/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package controller;

import domain.Answer;
import dto.GameHistory;
import service.GameService;

import java.util.List;

public class GameController {

private final GameService gameService;

public GameController(GameService gameService) {
this.gameService = gameService;
}

public void start() {
Answer answer = gameService.init();
List<GameHistory> gameHistories = gameService.startGame(answer);
gameService.endGame(gameHistories);
}
}
81 changes: 81 additions & 0 deletions src/main/java/domain/Answer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package domain;

import java.util.*;
import java.util.stream.Collectors;

public class Answer {

private final Word answer;

private boolean isSuccess = false;

public Answer(Word answer) {
this.answer = answer;
}

public List<Tile> compare(Word answer) {
Map<Letter, Long> letterMap = getLetterMap();

List<Tile> result = new ArrayList<>();

for (int i = 0; i < Word.WORD_LENGTH; i++) {
Long count = letterMap.get(answer.getWord().get(i));

Tile tile = getTile(count, this.answer.getWord().get(i), answer.getWord().get(i));
result.add(tile);

letterMap.put(answer.getWord().get(i), letterMap.getOrDefault(answer.getWord().get(i), 0L) - 1);
}
endGame(result);

Comment on lines +22 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

중복되는 값을 변수 선언하여 재사용을 할 수 있을것 같습니다.

Copy link
Author

@Saerang Saerang Apr 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 너무 길어져서 10줄이 넘어서 ㅋㅋㅋ 재선언 안하긴 했습니다.
다른방법으로 구현을 리팩터링 해야할 것 같네요.

return result;
}

private Map<Letter, Long> getLetterMap() {
return this.answer.getWord()
.stream()
.collect(Collectors.groupingBy(c -> c, Collectors.counting()));
}

private void endGame(List<Tile> result) {
int count = Collections.frequency(result, Tile.GREEN);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이런 Collections 메서드가 있는줄 처음 알았네요. 덕분에 배워갑니다!❤


if (count == Word.WORD_LENGTH) {
this.isSuccess = true;
}
}

private Tile getTile(Long count, Letter answerLetter, Letter letter) {
if (count == null || count <= 0) {
return Tile.GRAY;
}
if (answerLetter.equals(letter)) {
return Tile.GREEN;
}
return Tile.YELLOW;
}

public boolean isSuccess() {
return isSuccess;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Answer that = (Answer) o;
return Objects.equals(answer, that.answer);
}

@Override
public int hashCode() {
return Objects.hash(answer);
}

@Override
public String toString() {
return "Answer{" +
"answer=" + answer +
'}';
}
}
43 changes: 43 additions & 0 deletions src/main/java/domain/Letter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package domain;

import java.util.Objects;

public class Letter {
private final String letter;

public Letter(Character letter) {
if (this.isNotAlphabet(letter)) {
throw new IllegalArgumentException(letter + "는 알파벳이 아닙니다.");
}

this.letter = String.valueOf(letter);
}

private boolean isNotAlphabet(Character letter) {
return !(letter >= 'A' && letter <= 'Z') && !(letter >= 'a' && letter <= 'z');
}

public String getLetter() {
return letter;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Letter letter1 = (Letter) o;
return Objects.equals(letter, letter1.letter);
}

@Override
public int hashCode() {
return Objects.hash(letter);
}

@Override
public String toString() {
return "Letter{" +
"letter='" + letter + '\'' +
'}';
}
}
15 changes: 15 additions & 0 deletions src/main/java/domain/Tile.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

enum을 활용해서 각각의 종류에 맞는 이모지를 할당하셨세요.
깔끔하고 명확안 코드인것 같습니다.😃

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package domain;

public enum Tile {
GREEN("\uD83D\uDFE9"), YELLOW("\uD83D\uDFE8"), GRAY("⬜");

private final String tile;

Tile(String tile) {
this.tile = tile;
}

public String getTile() {
return tile;
}
}
49 changes: 49 additions & 0 deletions src/main/java/domain/Word.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package domain;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class Word {
public static final int WORD_LENGTH = 5;

private final List<Letter> word;

public Word(String word) {
if (this.isNotMatchWord(word)) {
throw new IllegalArgumentException(word + "는 5글자의 알파벳이 아닙니다.");
}

this.word = word.chars().mapToObj(c -> (char) c)
.map(Letter::new)
.collect(Collectors.toList());
}

private boolean isNotMatchWord(String word){
return word.length() != WORD_LENGTH;
}

public List<Letter> getWord() {
return word;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Word word1 = (Word) o;
return Objects.equals(word, word1.word);
}

@Override
public int hashCode() {
return Objects.hash(word);
}

@Override
public String toString() {
return "Word{" +
"word=" + word +
'}';
}
}
34 changes: 34 additions & 0 deletions src/main/java/domain/Words.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package domain;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

public class Words {
public static final LocalDate DEFAULT_DATE = LocalDate.of(2021, 6, 19);
private final List<Word> words;

public Words(List<String> words) {
this.words = convert(words);
}

private List<Word> convert(List<String> words) {
if (words.size() == 0) {
throw new IllegalArgumentException("파일이 비어 있습니다.");
}

return words.stream().map(Word::new).collect(Collectors.toList());
}

public Answer getAnswer(LocalDate now) {
long betweenDay = ChronoUnit.DAYS.between(DEFAULT_DATE, now);

Word answer = this.words.get((int) (betweenDay % words.size()));
return new Answer(answer);
}

public List<Word> getWords() {
return words;
}
}
20 changes: 20 additions & 0 deletions src/main/java/dto/GameHistory.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일급컬렉션을 활용하셨네요!😀

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package dto;

import domain.Tile;

import java.util.List;
import java.util.stream.Collectors;

public class GameHistory {

private final List<Tile> gameHistory;

public GameHistory(List<Tile> gameHistory) {
this.gameHistory = gameHistory;
}

public String getGameResult() {
return gameHistory.stream().map(Tile::getTile)
.collect(Collectors.joining());
}
}
49 changes: 49 additions & 0 deletions src/main/java/service/GameService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package service;

import config.FileConfig;
import domain.Answer;
import domain.Tile;
import domain.Word;
import domain.Words;
import dto.GameHistory;
import support.WordsGenerator;
import view.InputView;
import view.OutputView;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class GameService {

public Answer init() {
InputView.inputStartGame();
Words words = new Words(WordsGenerator.read(FileConfig.FILE_PATH));
return words.getAnswer(LocalDate.now());
}

public List<GameHistory> startGame(Answer answer) {
List<GameHistory> gameHistories = new ArrayList<>();

int count = 0;
while (count < InputView.GAME_TOTAL_ROUND && !answer.isSuccess()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

해당 조건을 판별하는 메서드를 분리해보는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

동감합니다 :)

Word inputWord = new Word(InputView.inputWord());
List<Tile> tiles = answer.compare(inputWord);
gameHistories.add(new GameHistory(tiles));
print(answer, gameHistories);
count++;
}

return gameHistories;
}

private void print(Answer answer, List<GameHistory> gameHistories) {
if (!answer.isSuccess()) {
OutputView.outputTiles(gameHistories);
}
}

public void endGame(List<GameHistory> gameHistories) {
OutputView.outputEndGame(gameHistories);
}
}
17 changes: 17 additions & 0 deletions src/main/java/support/WordsGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package support;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;

public class WordsGenerator {

public static List<String> read(String filePath) {
try {
return Files.readAllLines(Paths.get(filePath));
} catch (IOException e) {
throw new RuntimeException("파일을 읽을 수 없습니다.", e);
}
Comment on lines +11 to +15

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

파일이 없는 경우에 발생하는 NoSuchFileException과 같이 구체적인 예외를 작성해보는건 어떨까요?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

음 이번 프로젝트에는 있는 예외를 사용하려고 했습니다.

}
}
Loading