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
41 changes: 41 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@


## 기능목록

여기서 게임은 숫자야구게임 1판을 의미한다 (새로운 정답을 만들고 유저가 맞출 때까지 시도)

- [x] 게임을 반복하는 기능 (유저에게 계속할지를 물어봄)
- [x] 게임을 진행하는 기능
- [x] 숫자야구게임의 볼조합을 생성하는 기능
- [x] 두 볼조합을 통해 결과를 생성하는 기능
- [x] 생성된 결과를 유저가 보기 쉬운 메세지로 만들기

## 어떻게 구현할까??

1. junit 관련 살펴보기 (간단한 예제 + 탐험)
2. mockito 를 이용한 간단한 테스트
3. README.md 작성
4. 각 기능 구현 (가능하면 테스트랑 같이)
5. 컨벤션 확인 (리뷰)

- 일단 자바 문법에 익숙해졌으면 (최소한 자주 쓸 부분은)
- 테스트코드를 작성하는 이유중 하나도 코드를 막 고쳐보기 위함 (특히 여러가지 자료구조등을 사용해보고 연습해보고 싶어서)




### test

// 테스트 객체 개념
https://medium.com/@SlackBeck/mock-object%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-85159754b2ac

// Intellij Idea junit
https://examples.javacodegeeks.com/desktop-java/ide/intellij-idea-create-test-tutorial/
https://www.jetbrains.com/help/idea/tdd-with-intellij-idea.html


### 자바 익숙해지기...
https://1nyoung.tistory.com/14
https://jdm.kr/blog/181
https://github.com/winterbe/java8-tutorial
https://www.acmicpc.net/blog/view/3
59 changes: 59 additions & 0 deletions src/main/java/BallCombiGenerator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import java.util.Arrays;
import java.util.Random;
import java.util.stream.IntStream;

import static java.lang.Integer.max;

public class BallCombiGenerator {

public int[] genBallCombi() {
Random rand = new Random();

int [] ballPnts = IntStream.range(1, 10).toArray();

// shuffle ballPnts
for (int from = 0; from < ballPnts.length; from++) {
int to = rand.nextInt(ballPnts.length);

int tmp = ballPnts[from];
ballPnts[from] = ballPnts[to];
ballPnts[to] = tmp;
}

return Arrays.copyOfRange(ballPnts, 0, 3);
}

public boolean isValid(int[] ballCombi) {
if (ballCombi.length != 3) return false;

for (int i = 0; i < ballCombi.length; i++) {
int pnt = ballCombi[i];
if (pnt <= 0 || 10 <= pnt) return false;
}

// check duplicated number
int [] pntCnt = new int[10];
Arrays.stream(ballCombi).forEach((pnt) -> pntCnt[pnt]++);

int maxPntCnt = Arrays.stream(ballCombi)
.map(pnt -> pntCnt[pnt])
.reduce((a, b) -> max(a, b))
.getAsInt();

return maxPntCnt <= 1;
}

public int[] toBallCombi(String ballCombiStr) {
if (ballCombiStr.length() != 3) return new int[0];

int [] ballCombi = new int[3];
for (int i = 0; i < ballCombiStr.length(); i++) {
char c = ballCombiStr.charAt(i);
if (c <= '0' || '9' < c) return new int[0];

ballCombi[i] = c - '0';
}

return ballCombi;
}
}
62 changes: 62 additions & 0 deletions src/main/java/Game.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import java.util.Scanner;

public class Game {

final private int STRIKE = 0;
final private int BALL = 1;

private Scanner sc;
private BallCombiGenerator generator;
private Referee referee;

public Game() {
sc = new Scanner(System.in);
generator = new BallCombiGenerator();
referee = new Referee();
}

public void play() {

int [] ansBallCombi = generator.genBallCombi();

for (int trial = 1; ; trial++) {
int [] userBallCombi;

System.out.printf("숫자를 입력해주세요: ");
String userBallCombiStr = sc.next(); //
userBallCombi = generator.toBallCombi(userBallCombiStr);
while (!generator.isValid(userBallCombi)) {
System.out.printf("잘못된 입력입니다. 숫자를 입력해주세요: ");
userBallCombiStr = sc.next(); //
userBallCombi = generator.toBallCombi(userBallCombiStr);
}

int [] judgement = referee.judge(ansBallCombi, userBallCombi);

if (judgement[STRIKE] == 3) {
System.out.printf("3개의 숫자를 모두 맞히셨습니다! 게임 종료 (%d 시도)\n", trial);
break;
}

printJudgement(judgement);
}
}

private void printJudgement(int [] judgement) {
if (judgement[STRIKE] == 0 && judgement[BALL] == 0) {
System.out.println("낫싱");
}

String str = "";

if (0 < judgement[STRIKE]) {
str += String.format("%d 스트라이크 ", judgement[STRIKE]);
}

if (0 < judgement[BALL]) {
str += String.format("%d 볼", judgement[BALL]);
}

System.out.println(str);
}
}
18 changes: 18 additions & 0 deletions src/main/java/GameExecutor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import java.util.Scanner;

public class GameExecutor {
public static void main(String[] args) {

Scanner sc = new Scanner(System.in);
// 지금은 아무 상태도 가지고 있지 않기에 동일한 game을 사용
Game game = new Game();

while (true) {
game.play();

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

if (2 == sc.nextInt()) break;
}
}
}
28 changes: 28 additions & 0 deletions src/main/java/Referee.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import java.util.Arrays;
import java.util.stream.IntStream;

public class Referee {

public int[] judge(int[] ansBallCombi, int[] inpBallCombi) {
int[] cnt = new int[10];

for (int ansPnt : ansBallCombi) {
cnt[ansPnt]++;
}

int strikeCnt = IntStream.range(0, inpBallCombi.length)
.map(i -> (ansBallCombi[i] == inpBallCombi[i]) ? 1 : 0)
.reduce((a, b) -> a + b)
.getAsInt();

int ballCnt = Arrays.stream(inpBallCombi)
.map(pnt -> cnt[pnt])
.reduce((a, b) -> a + b)
.getAsInt()
- strikeCnt;

int[] judgement = {strikeCnt, ballCnt};

return judgement;
}
}
124 changes: 124 additions & 0 deletions src/test/java/BallCombiGeneratorTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;

public class BallCombiGeneratorTest {

private BallCombiGenerator generator;

@Before
public void setUp() throws Exception {
generator = new BallCombiGenerator();
}

@Test
public void genBallCombi_generatedBallCombiAllValid() {
int n = 100;

for (int i = 0; i < n; i++) {
int [] ballCombi = generator.genBallCombi();
// System.out.println(Arrays.toString(ballCombi));
// System.out.flush();

boolean got = generator.isValid(ballCombi);

Assert.assertTrue(String.format("[%d] got: %b\n", i, got), got);
}
}

@Test
public void isValid_possibleValidBallCombis() {
// 입력
int [][] possibleBallCombis = genPossibleBallCombis();

for (int [] ballCombi: possibleBallCombis) {
// System.out.println(Arrays.toString(ballCombi));
// System.out.flush();
boolean got = generator.isValid(ballCombi);
Assert.assertTrue(String.format("ballCombi: %s", Arrays.toString(ballCombi)), got);
}
}


@Test
public void isValid_invalidBallCombis() {
// 입력
int [][] ballCombis = {
{1, 1, 1, 1},
{0, 1, 2},
{1, 2, 2},
{9, 9, 9},
};

for(int i = 0; i < ballCombis.length; i++) {
int [] ballCombi = ballCombis[i];

boolean got = generator.isValid(ballCombi);

Assert.assertFalse(String.format("[%d] ", i), got);
}
}

@Test
public void toBallCombi_usualInputStr() {
//
String [] strs = {
"hello",
"012344",
"adkfj",
"023",
"987",
"345",
};

int [][] wants = {
{},
{},
{},
{},
{9, 8, 7},
{3, 4, 5},
};

for (int i = 0; i < strs.length; i++) {
String str = strs[i];
int [] want = wants[i];

int [] got = generator.toBallCombi(str);

Assert.assertArrayEquals(
String.format("[%d] want: %s, got: %s", i, Arrays.toString(want), Arrays.toString(got)),
want,
got
);
}
}

private int[][] genPossibleBallCombis() {
int used[] = new int [10];

ArrayList<int[]> combis = new ArrayList<>();

for (int p1 = 1; p1 <= 9; p1++) {
used[p1]++;
for (int p2 = 1; p2 <= 9; p2++) {
if (used[p2] != 0) continue;
used[p2]++;
for(int p3 = 1; p3 <= 9; p3++) {
if (used[p3] != 0) continue;

// 생성해서 바로 넣는 방법이 없으려나??..
int [] ballCombi = {p1, p2, p3};
combis.add(ballCombi);
}
used[p2]--;
}
used[p1]--;
}

return combis.toArray(new int[combis.size()][]);
}
}
53 changes: 53 additions & 0 deletions src/test/java/RefereeTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;

public class RefereeTest {

private Referee referee;

@Before
public void setUp() throws Exception {
referee = new Referee();
}

@Test
public void judge_usualCases() {
int [] ansBallCombi = {1, 2, 3};
int [][] inpBallCombis = {
{1, 2, 3}, // 3s, 0b
{1, 3, 2}, // 1s, 2b
{2, 1, 3}, // 1s, 2b
{2, 3, 1}, // 0s, 3b
{9, 2, 5}, // 1s, 0b
{3, 4, 5}, // 0s, 1b
{4, 5, 6}, // 0s, 0b
{6, 2, 5}, // 1s, 0b
};
int [][] wants = {
{3, 0},
{1, 2},
{1, 2},
{0, 3},
{1, 0},
{0, 1},
{0, 0},
{1, 0},
};

for (int i = 0; i < wants.length; i++) {
int [] inpBallCombi = inpBallCombis[i];
int [] want = wants[i];

int [] got = referee.judge(ansBallCombi, inpBallCombi);

Assert.assertArrayEquals(String.format("[%d] want: %s, got: %s", i, Arrays.toString(want), Arrays.toString(got)),
want,
got
);
}
}
}