-
Notifications
You must be signed in to change notification settings - Fork 3
[1] 숫자 야구 게임 구현 #1
base: main
Are you sure you want to change the base?
Changes from all commits
b561b83
4c2a66e
efe7157
c5f7dd0
1f9d3cf
0138d10
d61e622
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 |
|---|---|---|
| @@ -1,26 +1,3 @@ | ||
| ## [NEXTSTEP 플레이그라운드의 미션 진행 과정](https://github.com/next-step/nextstep-docs/blob/master/playground/README.md) | ||
|
|
||
| --- | ||
| ## 학습 효과를 높이기 위해 추천하는 미션 진행 방법 | ||
|
|
||
| --- | ||
| 1. 피드백 강의 전까지 미션 진행 | ||
| > 피드백 강의 전까지 혼자 힘으로 미션 진행. 미션을 진행하면서 하나의 작업이 끝날 때 마다 add, commit | ||
| > 예를 들어 다음 숫자 야구 게임의 경우 0, 1, 2단계까지 구현을 완료한 후 push | ||
|
|
||
|  | ||
|
|
||
| --- | ||
| 2. 피드백 앞 단계까지 미션 구현을 완료한 후 피드백 강의를 학습한다. | ||
|
|
||
| --- | ||
| 3. Git 브랜치를 master 또는 main으로 변경한 후 피드백을 반영하기 위한 새로운 브랜치를 생성한 후 처음부터 다시 미션 구현을 도전한다. | ||
|
|
||
| ``` | ||
| git branch -a // 모든 로컬 브랜치 확인 | ||
| git checkout master // 기본 브랜치가 master인 경우 | ||
| git checkout main // 기본 브랜치가 main인 경우 | ||
|
|
||
| git checkout -b 브랜치이름 | ||
| ex) git checkout -b apply-feedback | ||
| ``` | ||
| 1. 컴퓨터가 서로 다른 임의의 숫자를 3개 선택 | ||
| 2. 플레이어가 입력한 문자열과 컴퓨터가 선택한 숫자를 비교하고 결과 반환 | ||
| 3. 입력과 출력을 처리 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package baseball; | ||
|
|
||
| import util.Terminal; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.List; | ||
|
|
||
| public class BaseballGame { | ||
| public static void main(String[] args) throws IOException { | ||
| while (true) { | ||
| Terminal.out("게임 시작!" + System.lineSeparator()); | ||
| Number targetNumber = RandomNumberGenerator.generate(); | ||
| BaseballStage stage = new BaseballStage(targetNumber); | ||
| if (proceed(stage)) { | ||
| return; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static boolean proceed(BaseballStage stage) throws IOException { | ||
| while (true) { | ||
| boolean proceed = stage.proceed(); | ||
| if (proceed) { | ||
| return askPlayEnd(stage.getHistory()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private static boolean askPlayEnd(List<Discrimination> history) throws IOException { | ||
| while (true) { | ||
| Terminal.out("세 개의 숫자를 모두 맞히셨습니다! 게임 종료" + System.lineSeparator()); | ||
|
|
||
| for (Discrimination discrimination : history) { | ||
| Terminal.out(discrimination.show()); | ||
| } | ||
|
|
||
| String in = Terminal.in("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요." + System.lineSeparator()); | ||
| if (in.trim().equals("1")) { | ||
| return false; | ||
| } | ||
|
|
||
| if (in.trim().equals("2")) { | ||
| return true; | ||
| } | ||
|
|
||
| Terminal.out("1과 2중에서 입력해주세요"); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| package baseball; | ||
|
|
||
| import util.Terminal; | ||
|
|
||
| import java.io.IOException; | ||
| import java.util.*; | ||
|
|
||
| public class BaseballStage { | ||
| private final Number targetNumber; | ||
| private final List<Discrimination> history = new ArrayList<>(); | ||
|
|
||
| public BaseballStage(Number number) { | ||
| this.targetNumber = number; | ||
| } | ||
|
|
||
| public Number getTargetNumber() { | ||
| return this.targetNumber; | ||
| } | ||
|
|
||
| public boolean proceed() throws IOException { | ||
| String in = Terminal.in("숫자를 입력해주세요 : "); | ||
| Discrimination discrimination = discriminate(Integer.parseInt(in)); | ||
| Terminal.out(discrimination.print()); | ||
|
|
||
| return discrimination.getStrike() == 3; | ||
| } | ||
|
|
||
| public Discrimination discriminate(int answer) { | ||
| Number compare = new Number(answer); | ||
| Discrimination discrimination = new Discrimination(targetNumber, compare); | ||
| history.add(discrimination); | ||
| return discrimination; | ||
| } | ||
|
|
||
| public List<Discrimination> getHistory() { | ||
| return new ArrayList<>(this.history); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,92 @@ | ||
| package baseball; | ||
|
|
||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.stream.IntStream; | ||
|
|
||
| public class Discrimination { | ||
| private final int input; | ||
| private final int strike; | ||
| private final int ball; | ||
| private final int out; | ||
| private final String[] visual = new String[3]; | ||
|
|
||
| public Discrimination(Number base, Number compare) { | ||
| int[] compareArr = compare.get(); | ||
| int input = 0; | ||
| for (int i : compareArr) { | ||
| input = input * 10 + i; | ||
| } | ||
| this.input = input; | ||
|
|
||
| int[] baseArr = base.get(); | ||
| Map<Integer, Integer> baseMap = new HashMap<>(); | ||
| IntStream.range(0, 3).forEach(i -> baseMap.put(baseArr[i], i)); | ||
|
|
||
| int strike = 0; | ||
| int ball = 0; | ||
|
|
||
| for (int i = 0; i < compareArr.length; i++) { | ||
| if (baseMap.containsKey(compareArr[i])) { | ||
| if (baseMap.get(compareArr[i]) == i) { | ||
| visual[i] = "S"; | ||
| strike++; | ||
| } else { | ||
| visual[i] = "B"; | ||
| ball++; | ||
| } | ||
|
|
||
| baseMap.remove(baseArr[i]); | ||
| } else { | ||
| visual[i] = "O"; | ||
| } | ||
| } | ||
|
|
||
| this.strike = strike; | ||
| this.ball = ball; | ||
| this.out = baseMap.size(); | ||
| } | ||
|
|
||
| public String print() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| sb.append(String.format("[입력:%d] > ", this.input)); | ||
|
|
||
| if (ball > 0) { | ||
| sb.append(String.format("%d볼 ", getBall())); | ||
| } | ||
|
|
||
| if (strike > 0) { | ||
| sb.append(String.format("%d스트라이크", getStrike())); | ||
| } | ||
|
|
||
| if (out == 3) { | ||
| sb.append("3아웃!"); | ||
| } | ||
|
|
||
| sb.append(System.lineSeparator()); | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| public String show() { | ||
| StringBuilder sb = new StringBuilder(); | ||
| sb.append(String.format("[입력:%d] > ", this.input)); | ||
| for (String s : visual) { | ||
| sb.append(s); | ||
| } | ||
|
|
||
| sb.append(System.lineSeparator()); | ||
| return sb.toString(); | ||
| } | ||
|
|
||
| public int getStrike() { | ||
| return strike; | ||
| } | ||
|
|
||
| public int getBall() { | ||
| return ball; | ||
| } | ||
|
|
||
| public int getOut() { | ||
| return out; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| package baseball; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public class Number { | ||
| private final int[] nums = new int[3]; | ||
|
|
||
| public Number(int number) { | ||
| for (int i = 2; i >= 0; i--) { | ||
| nums[i] = number % 10; | ||
| number = number / 10; | ||
| } | ||
| } | ||
|
Comment on lines
+8
to
+13
Collaborator
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. 해당 매서드는 사용하는 측에서의 활용을 모른다면(사용하는 측의 로직을 모른다면) 이해하기 힘든 로직인 것 같아요!
것은 어떨까요? |
||
|
|
||
| public int[] get() { | ||
| return Arrays.copyOf(nums, 3); | ||
| } | ||
|
|
||
| @Override | ||
| public boolean equals(Object obj) { | ||
| if (obj.getClass() != this.getClass()) { | ||
| return false; | ||
| } | ||
|
|
||
| int[] compare = ((Number) obj).get(); | ||
|
|
||
| if (nums.length != compare.length) { | ||
| return false; | ||
| } | ||
|
|
||
| for (int i = 0; i < this.nums.length; i++) { | ||
| if (nums[i] != compare[i]) { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
|
|
||
| @Override | ||
|
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. hashCode() 와 equals(Object obj) 를 오버라이드한 이유가 궁금합니다...!
Author
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.
Author
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.
해시 알고리즘은 모든 인스턴스에 대해서 완전히 중복되지 않는 고유한 값을 만들어주지는 않습니다. 알고리즘에 따라서 그 확률은 다르겠지만 해시 코드값이 중복되는 경우도 있습니다. 해시 코드를 이용하는 컬렉션들은 값을 저장, 조회할 때 일단 해시코드를 이용해서 저장하고, 만약 중복되는 해시코드 값이 이미 있다면 그 이후에는 |
||
| public int hashCode() { | ||
| int hashCode = 1; | ||
| for (int num : nums) { | ||
| hashCode = 31 * hashCode + num; | ||
| } | ||
|
|
||
| return hashCode; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package baseball; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.Collections; | ||
| import java.util.List; | ||
|
|
||
| public class RandomNumberGenerator { | ||
| public static Number generate() { | ||
| List<Integer> bucket = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9)); | ||
| Collections.shuffle(bucket); | ||
|
|
||
| int num = 0; | ||
| for (int i = 0; i < 3; i++) { | ||
| num = num * 10 + bucket.get(i); | ||
| } | ||
|
|
||
| return new Number(num); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package util; | ||
|
|
||
| import java.io.BufferedReader; | ||
| import java.io.IOException; | ||
| import java.io.InputStreamReader; | ||
|
|
||
| public class Terminal { | ||
|
|
||
| public static String in(String message) throws IOException { | ||
| BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); | ||
| System.out.print(message); | ||
| return br.readLine(); | ||
| } | ||
|
|
||
| public static void out(String str) { | ||
| System.out.print(str); | ||
| } | ||
| } |
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.
class 이름을 discrimination으로 설정하신 이유가 궁금합니다!
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.
두 숫자를 비교하는 행위를 '판별한다(discriminate)'고 표현하고 싶었습니다.
검증하다(Verify)나 판단하다(Judge)로 표현하는 게 더 자연스러웠을지 모르겠네요..
Discrimianation은 생성되는 순간 두 숫자(Number)를 판별하고 그 정보를 저장해놓았다가 표시하는 역할을 하는 클래스입니다.