Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
STUDY.md
HELP.md
.gradle
build/
Expand Down
55 changes: 55 additions & 0 deletions docs/STUDY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Leets 2주차 미션
## Up - Down Game

### 기능
- 버전 분리(영어, 숫자)
- 입력값과 비교해 결과를 반환
- 사용자 입력 횟수를 기억하고, 범위를 최신화하여 다시 입력받을 수 있어야함
- 숫자 버전과 영어 버전을 나눌 때 입력과 출력을 하나로 하려면 어떻게 해야할까
- 영어 -> 숫자로 변환하여 전달?

### 구현
[Domain]
- 도메인이 필요할까 고민
- -> dto 느낌?

[Service]
- 숫자, 영어 버전을 구현체로 나누기
- or 내부 클래스 안에서 버전 선택하기

[View]
- InputView: 사용자에게 입력을 받고 컨트롤러로 전달
- 버전, 정답을 입력받음
- 잘못된 입력시 예외처리
- OutputView: 결과를 사용자에게 출력
- 영어, 숫자 버전 별로 받은 중간 결과를 어떻게 출력할까?

[Controller]
- 입력을 받아 서비스에 전달
- 서비스 결과를 받아 출력에 전달
- 입력을 반복적으로 받아야하는 프로그램의 입장에서 view -> controller -> service -> controller -> output의 구조가 효율적일까?
- 게임이 계속 추가된다면 서비스만 추가하면 되니까 괜찮을 거 같기도 함

[예외처리]
- [ERROR] 범위 내의 숫자를 입력하세요.
- [ERROR] 범위 내의 알파벳을 입력하세요.
- 이 두 예외는 어디서 처리? InputView?

[개인내용]
- commit 메시지
- feat: 새로운 기능
- fix: 버그 수정
- docs: 문서 변경
- 스타일: 코드의 의미에 영향을 주지 않는 변경 사항(예: 서식 지정)
- refactor: 코드 리팩토링
- test: 테스트 추가 또는 수정
- chore: 빌드 프로세스, CI 구성 등이 변경됩니다.

[실제구현]
- InputView와 OutputView로 View를 구성
- InputView에서 프로그램 구동에 필요한 입력을 받아 GameController로 전달
- GameController에서는 게임 버전을 구분해 숫자 버전, 영어 버전을 따로 호출해서 게임 진행, OutputView에 Count를 전달해 출력
- Domain에 뭐가 들어가야할 지 모르겠음.
- 게임을 버전별로 구분해 따로 패키지를 구성하고 싶은데 더 고민해보겠음 -> 입력이 반복되는 데 계속 객체로 넘겨주는 게 오히려 일하는 단계를 늘리느 느낌
- 로직 테스트.
- view - controller - game의 3층 구조는 비효율 적인 거 같아 game 로직을 controller에 구현하고, match 해주는 컨트롤러를 따로 구성하였음
16 changes: 14 additions & 2 deletions src/main/java/leets/land/UpdownApplication.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
package leets.land;


import leets.land.controller.MatchController;
import leets.land.view.InputView;

public class UpdownApplication {

public static void main(String[] args) {
System.out.print("hihi :D");

public static void main(String[] args) {
InputView inputView = new InputView();
int versionNum = inputView.inputVersionNum();
MatchController matchController = appConfig.gameController(versionNum);
matchController.runApp();
}
}




18 changes: 18 additions & 0 deletions src/main/java/leets/land/appConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package leets.land;

import leets.land.controller.MatchController;
import leets.land.controller.AlphabetGameController;
import leets.land.controller.NumgameController;

//자바 코드로 의존성 주입을 하기 위한 클래스
public class appConfig {

// 버전에 맞는 Game 객체를 컨트롤러로 주입
public static MatchController gameController(int versionNum){
if(versionNum==1) {
return new MatchController(new NumgameController());
} else {
return new MatchController(new AlphabetGameController());
}
}
}
47 changes: 47 additions & 0 deletions src/main/java/leets/land/controller/AlphabetGameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package leets.land.controller;

import leets.land.view.InputView;

public class AlphabetGameController implements GameController {

private final InputView inputView = new InputView();

@Override
public int generateRandomVal() {
int randomNum = (int) (Math.random() * 52);

if (randomNum < 26) {
return (char) ('a' + randomNum);
}
else {
return (char) ('A' + randomNum - 26);
}
}

@Override
public int updownGameStart(int targetAlphabet) {
char first = 'A';
char last = 'z';
int[] count = {0};
boolean isCorrect = false;
char inputAlphabet;

while(!isCorrect){
System.out.print("정답을 입력하세요(" + first + "~" + last + ") : ");
inputAlphabet = inputView.inputChar(first, last, count);

if(inputAlphabet == targetAlphabet){
System.out.println("정답입니다!");
isCorrect = true;
} else if (inputAlphabet<targetAlphabet) {
first = inputAlphabet;
System.out.println("UP");
} else {
last = inputAlphabet;
System.out.println("DOWN");
}
}
return count[0];
}

}
9 changes: 9 additions & 0 deletions src/main/java/leets/land/controller/GameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package leets.land.controller;

public interface GameController {
//난수발생
int generateRandomVal();

//게임 시작
int updownGameStart(int randomNum);
}
27 changes: 27 additions & 0 deletions src/main/java/leets/land/controller/MatchController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package leets.land.controller;

import leets.land.view.OutputView;

public class MatchController {

private final OutputView outputView = new OutputView();
private final GameController gameController;

//버전에 맞는 Game을 appConfig 클래스에서 주입
public MatchController(GameController gameController) {
this.gameController = gameController;
}

//구동부
public void runApp() {
outputView.printStartMessage();

int count = 0;// 사용자 입력횟수를 저장하기 위한 변수 초기화
int randomNum = gameController.generateRandomVal();
count = gameController.updownGameStart(randomNum);

//결과 출력
outputView.printCount(count);
}
}

39 changes: 39 additions & 0 deletions src/main/java/leets/land/controller/NumgameController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package leets.land.controller;

import leets.land.view.InputView;

public class NumgameController implements GameController {
private final InputView inputView = new InputView();

@Override
public int generateRandomVal() {
int randomNum = (int) (Math.random() * 100) + 1;
return randomNum;
}

@Override
public int updownGameStart(int targetNum) {
int low = 1;
int high = 100;
int[] count = {0};
boolean isCorrect = false;
int inputNum;

while(!isCorrect){
System.out.print("정답을 입력하세요(" + low + "~" + high + ") : ");
inputNum = inputView.inputNum(low, high, count);

if(inputNum == targetNum){
System.out.println("정답입니다!");
isCorrect = true;
} else if (inputNum<targetNum) {
low = inputNum;
System.out.println("UP");
} else {
high = inputNum;
System.out.println("DOWN");
}
}
return count[0];
}
}
96 changes: 96 additions & 0 deletions src/main/java/leets/land/view/InputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package leets.land.view;

import java.util.InputMismatchException;
import java.util.Scanner;

public class InputView {

//하나의 스캐너로 입력을 받았을 때 사소한 문제들이 발생해서 분리. [어떤 문젠지 파악하도록 하겠음]
private final Scanner numScan = new Scanner(System.in);
private final Scanner charScan = new Scanner(System.in);

/*
게임 버전 입력
*/
public int inputVersionNum(){
System.out.print("게임 버전을 입력해주세요 (숫자: 1, 영어: 2): ");
try{
int versionNum = numScan.nextInt();
validVersionNum(versionNum);
return versionNum;
} catch (IllegalArgumentException e){
System.out.print(e.getMessage());
return inputVersionNum();
} catch (InputMismatchException e){
System.out.print("[ERROR] 숫자를 입력해주세요 (숫자: 1, 영어: 2): ");
numScan.nextLine();// 개행문제 비워주기. 안 하면 StackOverFlow 발생
return inputVersionNum();
}
}

/*
버전 입력이 1과 2인지 검증
*/
public void validVersionNum(int versionNum){
if(versionNum!=1&&versionNum!=2){
throw new IllegalArgumentException("[ERROR] 버전은 1 또는 2만 입력해주세요. (숫자: 1, 영어: 2): ");
}
}

/*
숫자 버전 정답 입력
*/
public int inputNum(int low, int high, int[] count){
try{
int inputNum = numScan.nextInt();
count[0]++;
checkValidNumRange(low, high, inputNum);
return inputNum;
} catch (IllegalArgumentException e){
System.out.print(low + "~" + high + " 내의 숫자를 입력하세요: ");
return inputNum(low, high, count);
} catch (InputMismatchException e){
System.out.print("[ERROR] 숫자를 입력하세요: ");
numScan.nextLine();// 개행문제 비워주기. 안 하면 StackOverFlow
return inputNum(low, high, count);
}
}

/*
입력 범위를 벗어난 입력이 들어오면 예외 날리기
*/
public void checkValidNumRange(int low, int high, int inputNum){
if((inputNum<low)||(inputNum>high)){
throw new IllegalArgumentException("[ERROR] 범위 내의 숫자를 입력하세요 :");
}
}


/*
영어버전 입력부
*/
public char inputChar(char first, char last, int[] count){
try{
char inputAlphabet = (charScan.nextLine()).charAt(0);//한글을 입력했을 때 필터링
count[0]++;
checkValidCharRange(first, last, inputAlphabet);
return inputAlphabet;
} catch (IllegalArgumentException e){
System.out.print(first + "~" + last + " 내의 알파벳을 입력하세요: ");
return inputChar(first, last, count);
} catch (InputMismatchException e){
System.out.print("[ERROR] 영어 알파벳을 입력하세요 : ");
charScan.nextLine();// 개행문제 비워주기. 안 하면 StackOverFlow
return inputChar(first, last, count);
}
}

/*
입력 범위를 벗어난 입력이 들어오면 예외 날리기
*/
public void checkValidCharRange(char first, char last, char inputAlphabet) {
if ((inputAlphabet < first) || (inputAlphabet > last)) {
throw new IllegalArgumentException("[ERROR] 범위 내의 알파벳을 입력하세요 : ");
}
}
}
13 changes: 13 additions & 0 deletions src/main/java/leets/land/view/OutputView.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package leets.land.view;

public class OutputView {

public void printStartMessage(){
System.out.println("Up-Down 게임을 시작합니다");
}

public void printCount(int count) {
System.out.println("시도한 횟수: "+ count + "회");
}

}
30 changes: 30 additions & 0 deletions src/test/java/leets/land/game/GameControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package leets.land.game;

import leets.land.controller.AlphabetGameController;
import leets.land.controller.GameController;
import leets.land.controller.NumgameController;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;

class GameControllerTest {



@Test
void 난수_범위_확인(){
GameController gameController = new NumgameController();
assertThat(gameController.generateRandomVal()).isBetween(1, 100);
}

@Test
void 랜덤_알파벳_범위_확인() {
GameController gameController = new AlphabetGameController();
int randomValue = gameController.generateRandomVal();
assertThat(randomValue)
.satisfiesAnyOf(
value -> assertThat(value).isBetween(65, 90),
value -> assertThat(value).isBetween(97, 122)
);
}
}
Loading