본문 바로가기
프로젝트/기타

숫자 야구게임 1

by 넬준 2021. 6. 1.

어렸을 때 학교에서 했던 숫자 야구게임을 Java로 구현해보고자 한다.

4개의 숫자를 중복없이 0~9까지 고르고, 상대방이 4개의 숫자를 부른다.

이 때, 같은 숫자가 있을 때 위치가 다르면 1ball, 위치까지 같으면 1strike, 같은 숫자가 없다면 out이다.

이를 토대로 처음에 어떤 4개의 숫자를 어디에 위치시켰는지 추론해나가는 게임이다.  

 

기본 컨셉

게임이 시작되면 컴퓨터가 0~9까지 숫자 중 4개를 중복없이 순서대로 뽑는다.

그 뒤, 유저가 똑같이 0~9까지 숫자 중 4개를 중복없이 적으면, 컴퓨터가 뽑은 4개의 숫자와 비교한다.

비교한 결과(strike, ball갯수, out 여부)값을 리턴해주고, 유저는 결과를 보고 다시 입력한다.

이러한 과정을 반복한 뒤, 4개의 숫자와 위치까지 전부 맞으면 게임을 종료하고 재시작 여부를 물어본다.

 

일단 야구게임에서 일어나는 일들과 여러 값들을 가진 Baseball 클래스를 만든다.

필드

처음 컴퓨터가 뽑은 숫자 4개를 차례대로 담을 int[]형 필드

유저가 입력한 숫자 4개를 담을 int[]형 필드

두 그룹을 비교한 뒤 리턴할 결과값 배열 담을 int[] 필드

//컴퓨터가 생성한 숫자 배열
private int[] numArr;
//유저가 입력한 4개의 숫자 배열
private int[] userInputNumArr = new int[4];
//체크 후 결과값 배열 [strike, ball, out]
private int[] resultArr = new int[3];

 

메소드

1. 게임 시작 시 숫자 4개를 중복없이 뽑아 배열에 담는 메소드

2. 두 숫자 그룹을 비교해 strike, ball, out결과값을 리턴하는 메소드

3. 게임의 전체적인 로직이 들어가 있는 메소드

 

1. makeNumArr() 

private int[] makeNumArr() {
	int[] numArr = new int[4];
		
	for(int arrIndex=0; arrIndex<numArr.length; arrIndex++) {
		numArr[arrIndex] = (int)(Math.random()*10);//0~9까지 랜덤한 수 뽑은 후 대입
			
		for(int searchIndex=0; searchIndex<arrIndex; searchIndex++) {
			//이전까지 뽑힌 수와 현재 뽑힌 수 중복 비교
			if(numArr[searchIndex]==numArr[arrIndex]) {
			//현재 뽑힌 수가 전에 뽑혔던 수 중에 중복된 값이 있다면
			//arrIndex를 낮춰 현재 자리의 숫자를 다시 뽑게끔 한다.
                	   arrIndex--;
			}//if end
		}//for end
        
	}//for end

	return numArr;
}//makeNumArr() end

 

2. check() : 유저가 입력한 값을 int[]형으로 받고, 컴퓨터가 뽑은 숫자배열과 비교하여 결과값[strike, ball, out]을 int[]형으로 리턴하는 메소드

private int[] check(int[] userInputNumArr) {
		
	int strike = 0;
	int ball = 0;
	int out = 0;
		
    //유저 숫자배열과 컴퓨터 숫자배열을 이중for문으로 비교
	for(int userInputNumArrIndex=0; 
		userInputNumArrIndex<userInputNumArr.length; 
		userInputNumArrIndex++) {
		for(int numArrIndex=0; 
				numArrIndex<numArr.length; 
				numArrIndex++) {
			//숫자가 같을 때 true
			if(userInputNumArr[userInputNumArrIndex]==numArr[numArrIndex]) {
				
				if(userInputNumArrIndex==numArrIndex) {
					//index값, 다시 말해 숫자위치까지 같다면
					strike++;
				} else {
					//숫자는 같고, index값(위치)은 다를 때
					ball++;
				}//if~else end
			}//if end
				
		}//for end
			
	}//for end
		
	//strike, ball 하나도 없을 시 (out)
	if(strike==0 && ball==0) {
		out = 1;
	}//if end
		
	resultArr[0] = strike;
	resultArr[1] = ball;
	resultArr[2] = out;
		
	return this.resultArr;
}//check() end

 

3. startGame() : 게임이 시작되면 컴퓨터가 새로운 숫자 4개를 담은 배열을 생성한다.

유저가 console에 숫자 4개를 입력하면 이를 String 문자열로 받은 뒤, 이를 각각 잘라 int형으로 변환한 뒤 배열에 담는다. 이 두 숫자그룹을 비교해서 (check() 호출) 결과값을 console에 띄워준다.

public void startGame() {
	//startGame() 호출 시 새로운 숫자 배열 생성
	this.numArr = this.makeNumArr();
		
	System.out.println("야구게임을 시작합니다.");
	System.out.println("0000~9999까지 수 중에서 각 자리의 숫자가 중복되지 않는 수를 입력하시오");
		
	while(true) {
		//유저 입력 숫자를 String으로 받아오기
		String userInputNum = Main.sc.next();
			
		//입력값을 int형 배열에 숫자 한 개씩 담음
		for(int i=0; i<userInputNumArr.length; i++) {
			//char형으로 숫자를 받아오고 이를 int형으로 그대로 저장하기 위해 문자'0'값을 빼준다
			//예를들어 1xxx를 입력했을 경우 이를 charAt()으로 자르면 char형으로 리턴되기 때문에 
			//문자'1'의 아스키코드 값인 49값이 리턴된다. 
			//원하는 int형 숫자 1을 얻기 위해 '0'문자 아스키코드 값(48)을 빼주면 된다.
			userInputNumArr[i] = userInputNum.charAt(i)-'0';
		}//for end
			
		//결과값 배열 받아올 변수
		int[] resultArr = this.check(userInputNumArr);
			
		if(resultArr[0]==4) {
			//정답일 시
			System.out.println("축하합니다! 정답은 "+userInputNum+"입니다.");
				
			//while문 종료
			break;
		}
			
		if(resultArr[2]!=0) {
			System.out.println("OUT!!");
		} else {
			System.out.println("Strike : "+resultArr[0]);
			System.out.println("Ball : "+resultArr[1]);
		}//if end
			
	}//while end
		
	
}//startGame() end

 

 

게임을 실제 실행시킬 main()가 포함된 Main클래스 생성

 

console에서 유저 입력 값을 받을 Scanner클래스 객체 생성

public static Scanner sc = new Scanner(System.in);

 

Scanner클래스형 필드sc는 Main클래스의 인스턴스 생성하지 않고도 접근하게 하기 위해, 정적메소드인 main()에서 사용하기 위해 static field로 선언

 

게임 종료 시까지 하나의 Baseball클래스 객체만 생성하고 사용할 거기 때문에 해당 객체를 참조하는 static 필드 선언

public static Baseball baseball;

 

 

 

main() : 처음에 게임 시작 여부를 묻는다.

no하면 게임이 종료되고, ok하면 게임이 쭉 진행되고, 정답을 맞추면 재시작 여부를 묻는다. 

no하면 게임이 종료되고, ok하면 게임이 쭉 진행되고, 정답을 맞추면 재시작 여부를 묻는다. 

...

no하면 게임이 종료되고, ok하면 게임이 쭉 진행되고, 정답을 맞추면 재시작 여부를 묻는다.

이렇게 반복되는 구조이기에, 해당 로직을 따로 메소드(runGame())로 만들어 main()에서 호출하게끔 한다.

 

runGame() : 유저의 입력값(yes/no)을 인자로 받는다.

yes면 게임을 진행하고(startGame()), 정답을 맞추고 나서 재시작 여부를 물어본다. 

no면 게임을 종료한다.

리턴값이 boolean인 이유는, main()에서 해당 메소드를 호출할 때 while문에서 호출하게 했으므로, runGame()이 끝난 후 다시 호출할지에 대한 값으로 true/false를 리턴한다.

Main클래스 객체 생성하지 않고 main()에서 사용하기 위해 static메소드로 선언

public static boolean runGame(String userAnswer) {
	boolean result = true;
		
	switch(userAnswer) {
	case "y":
	case "Y":
		if(baseball==null) {
			//Baseball클래스 객체 안만들어졌다면 객체 생성 (종료 시까지 총 1개)
			baseball = new Baseball();
		}//if end
			
		baseball.startGame();
			
		System.out.println("게임을 재시작하시겠습니까? Y/N");
		break;
	case "n":
	case "N":
		System.out.println("게임을 종료합니다.");
       	 	//리턴값 false
		result = false;
		break;
	}//switch end
		
	return result;
}

 

public static void main(String[] args) {

	System.out.println("야구게임을 시작하시겠습니까? Y/N");
    
    boolean isContinueGame = true;
    
    while(isContinueGame) {
    	//console에서 유저가 입력한 값을 runGame()호출 시 인자로 사용
        //runGame() 리턴값으로 while문 제어
    	isContinueGame = Main.runGame(Main.sc.next());
    }//while end
  
}//main() end

 

*실행(console창)

야구게임을 시작하시겠습니까? Y/N
y
야구게임을 시작합니다.
0000~9999까지 수 중에서 각 자리의 숫자가 중복되지 않는 수를 입력하시오
1234
Strike : 1
Ball : 1
3974
Strike : 2
Ball : 2
9374
축하합니다! 정답은 9374입니다.
게임을 재시작하시겠습니까? Y/N
y
야구게임을 시작합니다.
0000~9999까지 수 중에서 각 자리의 숫자가 중복되지 않는 수를 입력하시오
5034
축하합니다! 정답은 5034입니다.
게임을 재시작하시겠습니까? Y/N
n
게임을 종료합니다.

댓글