Skip to content

숫자야구게임 제출합니다! #2

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

Open
wants to merge 21 commits into
base: chae-heechan
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
a5a90c3
Initial commit
pobiconan Mar 6, 2019
cb411a6
initial commit
pobiconan Mar 15, 2019
0dc3517
remove html templates
pobiconan Mar 15, 2019
0c9d817
remove spark.java dependency
pobiconan Mar 15, 2019
321a971
refactor: update junit, assertj version
pobiconan Nov 22, 2019
322f4cb
Create README.md
gracefulBrown Nov 24, 2020
2efe851
Update README.md
gracefulBrown Nov 25, 2020
ef779f4
feat(build): update gradle version to 6.5.1
woowahan-pjs Nov 24, 2020
6a9b002
feat(baseball): add the skeleton code
woowahan-pjs Nov 24, 2020
83a7c97
fix(random-util)
gracefulBrown Nov 25, 2020
6da84a4
docs(README): 구현할 기능 목록 추가
chae-heechan Feb 17, 2021
716c21e
feat(Number): 임의의 수 생성 기능 추가
chae-heechan Feb 17, 2021
ea4473c
feat(Number): 사용자 입력 및 배열 변환 기능 추가
chae-heechan Feb 17, 2021
c9c11d5
feat(*): 게임 시작 기능 추가
chae-heechan Feb 17, 2021
da207b8
feat(*): 비정상적인 입력 처리 기능 추가
chae-heechan Feb 18, 2021
f999fb8
feat(Number, GamePlayer): 비정상적인 입력 처리 기능 추가
chae-heechan Feb 18, 2021
aa71193
feat(Referee, GamePlayer): 사용자 입력과 임의의 수 비교와 판정 결과 출력 기능 추가
chae-heechan Feb 18, 2021
025400d
feat(Application, GamePlayer): 재시작 기능 추가
chae-heechan Feb 18, 2021
03ace49
Merge remote-tracking branch 'origin/master'
chae-heechan Feb 18, 2021
2d75f43
feat(Application, GamePlayer): 재시작 기능 추가
chae-heechan Feb 18, 2021
7b3b130
merge
chae-heechan Feb 22, 2021
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
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 woowacourse

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
25 changes: 21 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
# 미션 - 숫자 야구 게임

## 구현할 기능
- 게임 시작
- 3개의 임의의 수 생성
- 사용자 입력 요구문 출력
- 사용자 입력
- 비정상적인 입력 처리
- 세자리 수가 아닐 경우
- 중복 수가 입력될 경우
- 0이 입력될 경우
- 사용자 입력과 임의의 수 비교
- 스트라이크 판정
- 볼 판정
- 낫싱 판정
- 판정 결과 출력
- 재시작 여부 확인

## 🚀 기능 요구사항
- 이 게임은 프로그램이 1에서 9까지 서로 다른 임의의 수 3개를 정하고 이를 플레이어가 맞추는 게임이다.
- 정답을 맞추기 위해 3자리수를 입력하고 힌트를 받는다.
Expand Down Expand Up @@ -56,7 +72,7 @@

## 🎱 프로그래밍 요구사항
- 자바 코드 컨벤션을 지키면서 프로그래밍한다.
- 기본적으로 [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html) 문서와 [네이버 핵데이 Java 컨벤션](https://naver.github.io/hackday-conventions-java/)을 원칙으로 한다.
- 기본적으로 [Google Java Style Guide](https://google.github.io/styleguide/javaguide.html)을 원칙으로 한다.
- 단, 들여쓰기는 '2 spaces'가 아닌 '4 spaces'로 한다.
- indent(인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다.
- 예를 들어 while문 안에 if문이 있으면 들여쓰기는 2이다.
Expand All @@ -69,13 +85,13 @@
### 프로그래밍 요구사항 - Application
- Application 클래스를 활용해 구현해야 한다.
- Application의 패키지 구조와 구현은 변경하지 않는다.
- `Scanner scanner = new Scanner(System.in);`는 변경하지 않는다.
- `final Scanner scanner = new Scanner(System.in);`는 변경하지 않는다.
- `// TODO 구현 진행` 이 후 부터 구현한다.

```java
public class Application {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
final Scanner scanner = new Scanner(System.in);
// TODO 구현 진행
}
}
Expand All @@ -96,10 +112,11 @@ private static final Random RANDOM = new Random();
<br>

## 📈 진행 요구사항
- 미션은 현재 저장소를 fork & clone해서 시작한다.
- 미션은 [java-baseball-precourse 저장소](https://github.com/woowacourse/java-baseball-precourse) 를 fork/clone해 시작한다.
- 기능을 구현하기 전에 java-baseball-precourse/README.md 파일에 구현할 기능 목록을 정리해 추가한다.
- git의 commit 단위는 앞 단계에서 README.md 파일에 정리한 기능 목록 단위로 추가한다.
- [AngularJS Commit Message Conventions](https://gist.github.com/stephenparish/9941e89d80e2bc58a153) 참고해 commit log를 남긴다.
- [프리코스 과제 제출 문서](https://github.com/woowacourse/woowacourse-docs/tree/master/precourse) 절차를 따라 미션을 제출한다.

<br>

Expand Down
16 changes: 8 additions & 8 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
plugins {
id 'java'
}
apply plugin: 'java'
apply plugin: 'eclipse'

group 'org.example'
version '1.0-SNAPSHOT'
version = '1.0.0'
sourceCompatibility = 1.8

repositories {
mavenCentral()
}

dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.6.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
testImplementation('org.junit.jupiter:junit-jupiter:5.7.0')
testImplementation('org.assertj:assertj-core:3.18.1')
testImplementation('org.mockito:mockito-inline:3.6.0')
}

test {
useJUnitPlatform()
}
}
4 changes: 4 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
<<<<<<< HEAD
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-bin.zip
=======
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5.1-bin.zip
>>>>>>> 2d75f4343ccfdead02994a6674392d6353b04a19
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
55 changes: 23 additions & 32 deletions gradlew
Original file line number Diff line number Diff line change
@@ -1,21 +1,5 @@
#!/usr/bin/env sh

#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

##############################################################################
##
## Gradle start up script for UN*X
Expand Down Expand Up @@ -44,7 +28,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
DEFAULT_JVM_OPTS='"-Xmx64m"'

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
Expand Down Expand Up @@ -82,7 +66,10 @@ esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

<<<<<<< HEAD

=======
>>>>>>> 2d75f4343ccfdead02994a6674392d6353b04a19
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
Expand Down Expand Up @@ -126,11 +113,10 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
Expand All @@ -156,19 +142,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
i=$((i+1))
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi

Expand All @@ -177,9 +163,14 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
APP_ARGS=$(save "$@")

# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"

# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi

exec "$JAVACMD" "$@"
43 changes: 19 additions & 24 deletions gradlew.bat
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem

@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
Expand All @@ -29,18 +13,15 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
set DEFAULT_JVM_OPTS="-Xmx64m"

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Expand All @@ -54,7 +35,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute
if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
Expand All @@ -64,14 +45,28 @@ echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windows variants

if not "%OS%" == "Windows_NT" goto win9xME_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
Expand Down
13 changes: 11 additions & 2 deletions src/main/java/baseball/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,16 @@

public class Application {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// TODO 구현 진행
final Scanner scanner = new Scanner(System.in);
GamePlayer gamePlayer = new GamePlayer();

//게임 시작
while(true){
gamePlayer.play(scanner);
Copy link
Contributor

Choose a reason for hiding this comment

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

지금의 코드는 인스턴스(gamePlayer)를 통해 메소드(play)를 호출하고있어요.
하지만 play는 static 메소드이고, static 메소드는 인스턴스를 생성 할 필요가 없이 Gameplayer.play로 호출이 가능해요.
GamePlayer.playgamePlayer.play는 무슨 차이가 있을까요?

System.out.println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.");
if(scanner.nextInt()==1)
Copy link
Contributor

Choose a reason for hiding this comment

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

여기서 1만 보고 게임 시작이란 것을 알 수 있을까요?
상수를 통해 값에 의미를 부여하면 어떨까요?

continue;
Comment on lines +13 to +15
Copy link
Member

Choose a reason for hiding this comment

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

다른 코드에서 try~catch로 예외처리를 해주셨는데 이 코드에서만 안해주고 있습니다.

이런 비일관성이 발생한 이유가 연관된 상태와 행위를 결정하는 기능을 묶어주는 캡슐화를 하지 않은 것으로부터 발생한 것으로 보입니다. 입력을 받는 모든 행위와 그와 관련된 상태(변수)들을 클래스를 이용해 캡슐화를 해보세요! 😃

위와 같은 이유로 게임의 비즈니스 로직과 사용자 입력을 받고, 필요한 문장을 출력하는 일이 혼재되어 있습니다.
이런 코드를 생산시 유지보수하기 어렵고 코드의 가독성을 떨어뜨립니다.
이런 문제를 해결하는 솔루션으로 MVC 패턴이 있습니다. 링크를 참고해보세요 👍

break;
}
}
}
36 changes: 36 additions & 0 deletions src/main/java/baseball/GamePlayer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package baseball;

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

import static baseball.Number.*;

public class GamePlayer {

public static void play(Scanner Input){
Number random = new Number();
Copy link
Contributor

Choose a reason for hiding this comment

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

Number 객체를 만든것 👍🏻
이런것을 값 객체(Value Object) 라고 해요.
VO에 대해서도 한번 학습해보세요.

객체로 감싼 것은 잘 했지만 Number라는 것만 보고는 이 숫자는 무슨 숫자인지 파악할 수가 없어요.
조금 더 명확한 이름으로 변경하는 것은 어떨까요?
ex) PhoneNumber, LottoNumber 등등

Number player = new Number();
Integer temp;
Copy link
Member

Choose a reason for hiding this comment

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

사용자 입력을 받아서 그 상태를 가지고 있는 변수가 temp라는 이름으로 그 의도를 드러내지 못하고 있습니다.

클린코드라는 책에서는 한 챕터를 의미 있는 이름으로 할당할 만큼 의도가 분명한 이름의 중요성은 아무리 강조해도 지나치지 않은 것 같습니다! 코딩할 때 힘들더라도 의미 있는 이름을 지어주려고 노력해보세요. 😃

Suggested change
Integer temp;
Integer userInputNumber;

Copy link
Contributor

Choose a reason for hiding this comment

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

int가 아닌 Integer 클래스를 사용한 이유는 무엇인가요? 두개는 무슨 차이가 있을까요?


//랜덤 수 생성
random.setNumber(random.createNumber());
Copy link
Contributor

Choose a reason for hiding this comment

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

random이란 Number클래스의 인스턴스에 값을 Number 내부가 아닌 외부에서 set해주고 있네요.
객체들의 값은 본인만 변경할 수 있도록 하는 것이 좋아요.
여기저기서 객체의 값을 바꾸면 관리할 포인트도 늘어나고 매번 값을 추적해야 하는 단점이 있어요.
set메소드를 지양하라는 것도 같은 이유에요.

위와 같은 경우는 random이라는 인스턴스가 생성될 때 createNumber를 하면 되는 것이니 생성자를 활용해보는건 어떨까요?


//게임 내 n트
while(true) {
//입력 받고 비정상적인 입력 처리하고 저장
System.out.print("숫자를 입력해 주세요 : ");
try {
temp = Input.nextInt();
}catch (InputMismatchException e) {
Copy link
Contributor

Choose a reason for hiding this comment

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

구체적인 Exception 클래스 사용 👍🏻

throw new IllegalArgumentException("올바른 입력이 아닙니다!");
}
Comment on lines +22 to +26
Copy link
Member

Choose a reason for hiding this comment

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

try~catch로 예외 처리를 시도해주셨지만 catch 문에서 발생한 예외 상황에 예외 객체를 던지기만 할뿐 어떤 처리도 해주고 있지 않고 있습니다.
이렇게 되면 프로그램이 함수 스택을 따라 예외 처리를 던지고, main에서도 처리를 해주고 있지 않기 때문에 프로그램을 종료하게 됩니다.

숫자를 다시 입력받거나 다른 처리를 해주는 것이 낫지 않을까요?


inputCheck(temp);
Copy link
Member

Choose a reason for hiding this comment

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

2.10. 메서드 이름은 동사/전치사로 시작

코딩 컨벤션에 따르면 checkInput이 어울릴 것 같아요!

player.setNumber(splitNumber(temp));

Referee referee = new Referee();
if (referee.judgement(random.getNumber(), player.getNumber()))
Copy link
Member

Choose a reason for hiding this comment

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

2.10. 메서드 이름은 동사/전치사로 시작

컨벤션이 안지켜지고 있네요.

break;
}
}
}
Loading