
얼마 전 '코드 스쿼드' 라는 교육 기관에서 출제한 숫자 야구 문제를 풀어보았다.
우리가 흔히 알고 있는 그 숫자 야구 게임이다.
단순 구현으로 생각한다면 조건문과 반복문을 적절히 사용하면 어렵지 않을 것이다.
그러나 문제엔 몇 가지 제약 사항이 있기 때문에 조금 더 신중히 생각해야 한다.
다음은 문제와 제약 사항이다.
[ 문제 ]
기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.
같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이라는 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방의 수를 맞추면 승리한다.
[예] 상대방의 수가 425일 떄, 123을 제시한 경우 : 1 스트라이크 / 456을 제시한 경우 : 1 스트라이크 1 볼 / 789을 제시한 경우 : 낫싱
위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다.
게임 플레이어는 컴퓨터가 생각한 3개의 숫자를 입력하고, 컴퓨터는 그 결과를 출력한다.
이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
[ 제약 사항 ]
- 함수 (또는 메소드) 하나의 크기가 최대 10라인을 넘지 않도록 구현한다.
- 함수 (또는 메소드) 가 한 가지 일만 하도록 최대한 작게 만들어라.
- indent (인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다. 예를 들어 while 문 안에 if 문이 있으면들여쓰기는 2이다.
- 전역 변수를 사용하지 않는다.
[ 풀이 방법 ]
우선 숫자 야구는 친숙하여 아무런 제약 없이 구현한다면 금방 문제를 풀었을 것 같다.
그러나 모든 함수가 10줄 이내여야 한다는 제약 조건때문에 모든 기능을 최대한 쪼개야겠다고 생각했다.
우선 나는 main 함수를 포함하여 총 8개의 함수를 만들었다.
결론적으로 main 함수만 10줄, 나머진 10줄 이하가 되게 하였는데, 다음은 함수와 함수명 목록이다.
- 세 자리 난수 생성 : Create_Num()
- 난수 숫자 중복 체크 : is_Duplicate
- 사용자로부터 숫자를 입력 받음 : Input_Num()
- 입력값 체크 : check()
- 스트라이크, 볼 체크 : sb()
- 출력 : print()
- 게임 종료 : exit()
- 메인 함수 : main()
1. 세 자리 난수 생성
우선 나는 세 자리 숫자를 프로그램상에서 사용하기 용이하도록 정수형이 아닌 문자열로 만들어야겠다고 생각했다.
정수로 저장하면 각 자릿수마다 계산하기 귀찮아서 그냥 문자열로 받고 인덱스로 처리하기 위함이다.
이는 Java.util.Random 을 import 하여 자릿수가 3자리가 될 때 까지 난수를 생성, 문자열에 추가하였다.
2. 난수 숫자 중복 체크
사실 문제를 다 풀고 느낀건데 굳이 필요 없었다. Java Collection 중 중복을 허용하지 않는 'Set' 을 사용하면
되는데, 이 생각을 못했다. 아무튼 새로운 난수를 기존 문자열과 contain 메소드를 통해 false 값을 반환할 때만
난수를 문자열에 추가하였다.
3. 사용자로부터 숫자 입력 받음
main 함수에서 while 문으로 사용자에게 숫자를 입력받으면 10줄이 초과되어 조건에 어긋난다.
최대한 모든 기능을 세분화하기 위해 사용자에게 입력 받는 함수도 만들어주었다.
4. 입력값 체크
이 함수는 스트라이크, 볼을 판별하는 'sb' 함수와 연계되어 sb 함수에서 반환한 값을 통해
스트라이크와 볼의 갯수를 갱신한다.
여기서 sb 함수가 1을 반환하면 스트라이크 1 증가, 2면 볼 1 증가, 3이면 continue 이다.
5. 스트라이크, 볼 체크
단순히 인덱스 값과 해당 값이 같다면 스트라이크 (1) , 인덱스 값은 다르지만 해당 값이 있다면 볼 (2),
값이 없다면 아무것도 아님(3) 을 반환하도록 하였다. 비교적 간단한 구조다.
6. 출력
스트라이크와 볼의 갯수를 사용자에게 출력한다. 역시 main 함수에서 따로 빼서 함수로 만들어주었다.
7. 종료
main 함수 내에서 조건이 발동하는데, 만약 사용자가 정답을 입력하면 종료함수가 실행되어 문구 출력 후
프로그램이 종료된다. 이 때 System.exit(0) 명령어를 처음 알게 되었다.
[ 느낀 점 ]
아무래도 제약 조건을 지키며 구현하려니 쉽지 않았다. 그래서 종이에 대충 프로그램의 흐름과 함수들과의 관계를
정리하고 코드를 짰더니 엄청 크게 막히진 않았다. 한 25분? 정도 걸린 듯.
그래도 평소 숫자 게임을 해봤던 나는 코드로 구현하는 것이 재밌었다. 실제로 코드 다 짜고 몇 판 해봤더니 재밌었다.
사실 각 함수별로 오류가 나는지 테스트를 하면서 코딩하고싶었는데 아직은 부족한 실력이라 그냥 막무가내로 짰다.
점점 나도 짧고 간결하게 효율적으로 코드를 작성하는 방법을 찾는데 관심이 간다.
물론 이런 단순 구현 문제 말고 알고리즘 공부도 열심히 해야겠다는 생각이 들었다.
아 자료구조도 열심히 해야겠다.
[ 전체 코드 ]
package example;
import java.util.Random;
import java.util.Scanner;
public class Main{
//숫자 중복 체크
public static boolean is_Duplicate(String num,String s) {
if(num.contains(s)) return true;
else return false;
}
//랜덤으로 숫자 생성
public static String Create_Num() {
String number="";
while(number.length()!=3) {
Random rand=new Random();
String s=Integer.toString(rand.nextInt(1,10));
if(!is_Duplicate(number,s)) number+=s;
}
return number;
}
//사용자로부터 숫자 입력 받음
public static String Input_Num() {
Scanner sc=new Scanner(System.in);
System.out.print("숫자를 입력해주세요 ex)123 : ");
String result=sc.next();
return result;
}
//게임 종료
public static void exit() {
System.out.println("3 스트라이크");
System.out.print("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
System.exit(0);
}
//출력
public static void print(int strike,int ball) {
if(strike==0 && ball==0) System.out.println("낫싱");
else if(strike!=0 && ball==0) System.out.println(strike+" 스트라이크");
else if(strike==0 && ball!=0) System.out.println(ball+"볼");
else System.out.println(strike+" 스트라이크 "+ball+"볼");
}
//스트라이크,볼 확인
public static int sb(String number,Character input,int idx) {
if(input.equals(number.charAt(idx))) return 1;
else if(!input.equals(number.charAt(idx)) && number.contains(String.valueOf(input))) return 2;
else return 3;
}
//입력값 체크
public static void check(String number,String input) {
int strike=0, ball=0;
for(int i=0;i<3;i++) {
if(sb(number,input.charAt(i),i)==1) strike++;
else if(sb(number,input.charAt(i),i)==2) ball++;
else continue;
}
print(strike, ball);
}
//Main 함수
public static void main(String[] args){
String number=Create_Num();
Scanner sc=new Scanner(System.in);
System.out.println("정답: "+number);
while(true) {
System.out.print("숫자를 입력해주세요 ex)123 : ");
String result=sc.next();
if(result.equals(number)) exit(); //만약 맞힌다면 종료
else check(number,result);
}
}
}

얼마 전 '코드 스쿼드' 라는 교육 기관에서 출제한 숫자 야구 문제를 풀어보았다.
우리가 흔히 알고 있는 그 숫자 야구 게임이다.
단순 구현으로 생각한다면 조건문과 반복문을 적절히 사용하면 어렵지 않을 것이다.
그러나 문제엔 몇 가지 제약 사항이 있기 때문에 조금 더 신중히 생각해야 한다.
다음은 문제와 제약 사항이다.
[ 문제 ]
기본적으로 1부터 9까지 서로 다른 수로 이루어진 3자리의 수를 맞추는 게임이다.
같은 수가 같은 자리에 있으면 스트라이크, 다른 자리에 있으면 볼, 같은 수가 전혀 없으면 포볼 또는 낫싱이라는 힌트를 얻고, 그 힌트를 이용해서 먼저 상대방의 수를 맞추면 승리한다.
[예] 상대방의 수가 425일 떄, 123을 제시한 경우 : 1 스트라이크 / 456을 제시한 경우 : 1 스트라이크 1 볼 / 789을 제시한 경우 : 낫싱
위 숫자 야구 게임에서 상대방의 역할을 컴퓨터가 한다. 컴퓨터는 1에서 9까지 서로 다른 임의의 수 3개를 선택한다.
게임 플레이어는 컴퓨터가 생각한 3개의 숫자를 입력하고, 컴퓨터는 그 결과를 출력한다.
이 같은 과정을 반복해 컴퓨터가 선택한 3개의 숫자를 모두 맞히면 게임이 종료된다.
[ 제약 사항 ]
- 함수 (또는 메소드) 하나의 크기가 최대 10라인을 넘지 않도록 구현한다.
- 함수 (또는 메소드) 가 한 가지 일만 하도록 최대한 작게 만들어라.
- indent (인덴트, 들여쓰기) depth를 3이 넘지 않도록 구현한다. 2까지만 허용한다. 예를 들어 while 문 안에 if 문이 있으면들여쓰기는 2이다.
- 전역 변수를 사용하지 않는다.
[ 풀이 방법 ]
우선 숫자 야구는 친숙하여 아무런 제약 없이 구현한다면 금방 문제를 풀었을 것 같다.
그러나 모든 함수가 10줄 이내여야 한다는 제약 조건때문에 모든 기능을 최대한 쪼개야겠다고 생각했다.
우선 나는 main 함수를 포함하여 총 8개의 함수를 만들었다.
결론적으로 main 함수만 10줄, 나머진 10줄 이하가 되게 하였는데, 다음은 함수와 함수명 목록이다.
- 세 자리 난수 생성 : Create_Num()
- 난수 숫자 중복 체크 : is_Duplicate
- 사용자로부터 숫자를 입력 받음 : Input_Num()
- 입력값 체크 : check()
- 스트라이크, 볼 체크 : sb()
- 출력 : print()
- 게임 종료 : exit()
- 메인 함수 : main()
1. 세 자리 난수 생성
우선 나는 세 자리 숫자를 프로그램상에서 사용하기 용이하도록 정수형이 아닌 문자열로 만들어야겠다고 생각했다.
정수로 저장하면 각 자릿수마다 계산하기 귀찮아서 그냥 문자열로 받고 인덱스로 처리하기 위함이다.
이는 Java.util.Random 을 import 하여 자릿수가 3자리가 될 때 까지 난수를 생성, 문자열에 추가하였다.
2. 난수 숫자 중복 체크
사실 문제를 다 풀고 느낀건데 굳이 필요 없었다. Java Collection 중 중복을 허용하지 않는 'Set' 을 사용하면
되는데, 이 생각을 못했다. 아무튼 새로운 난수를 기존 문자열과 contain 메소드를 통해 false 값을 반환할 때만
난수를 문자열에 추가하였다.
3. 사용자로부터 숫자 입력 받음
main 함수에서 while 문으로 사용자에게 숫자를 입력받으면 10줄이 초과되어 조건에 어긋난다.
최대한 모든 기능을 세분화하기 위해 사용자에게 입력 받는 함수도 만들어주었다.
4. 입력값 체크
이 함수는 스트라이크, 볼을 판별하는 'sb' 함수와 연계되어 sb 함수에서 반환한 값을 통해
스트라이크와 볼의 갯수를 갱신한다.
여기서 sb 함수가 1을 반환하면 스트라이크 1 증가, 2면 볼 1 증가, 3이면 continue 이다.
5. 스트라이크, 볼 체크
단순히 인덱스 값과 해당 값이 같다면 스트라이크 (1) , 인덱스 값은 다르지만 해당 값이 있다면 볼 (2),
값이 없다면 아무것도 아님(3) 을 반환하도록 하였다. 비교적 간단한 구조다.
6. 출력
스트라이크와 볼의 갯수를 사용자에게 출력한다. 역시 main 함수에서 따로 빼서 함수로 만들어주었다.
7. 종료
main 함수 내에서 조건이 발동하는데, 만약 사용자가 정답을 입력하면 종료함수가 실행되어 문구 출력 후
프로그램이 종료된다. 이 때 System.exit(0) 명령어를 처음 알게 되었다.
[ 느낀 점 ]
아무래도 제약 조건을 지키며 구현하려니 쉽지 않았다. 그래서 종이에 대충 프로그램의 흐름과 함수들과의 관계를
정리하고 코드를 짰더니 엄청 크게 막히진 않았다. 한 25분? 정도 걸린 듯.
그래도 평소 숫자 게임을 해봤던 나는 코드로 구현하는 것이 재밌었다. 실제로 코드 다 짜고 몇 판 해봤더니 재밌었다.
사실 각 함수별로 오류가 나는지 테스트를 하면서 코딩하고싶었는데 아직은 부족한 실력이라 그냥 막무가내로 짰다.
점점 나도 짧고 간결하게 효율적으로 코드를 작성하는 방법을 찾는데 관심이 간다.
물론 이런 단순 구현 문제 말고 알고리즘 공부도 열심히 해야겠다는 생각이 들었다.
아 자료구조도 열심히 해야겠다.
[ 전체 코드 ]
package example;
import java.util.Random;
import java.util.Scanner;
public class Main{
//숫자 중복 체크
public static boolean is_Duplicate(String num,String s) {
if(num.contains(s)) return true;
else return false;
}
//랜덤으로 숫자 생성
public static String Create_Num() {
String number="";
while(number.length()!=3) {
Random rand=new Random();
String s=Integer.toString(rand.nextInt(1,10));
if(!is_Duplicate(number,s)) number+=s;
}
return number;
}
//사용자로부터 숫자 입력 받음
public static String Input_Num() {
Scanner sc=new Scanner(System.in);
System.out.print("숫자를 입력해주세요 ex)123 : ");
String result=sc.next();
return result;
}
//게임 종료
public static void exit() {
System.out.println("3 스트라이크");
System.out.print("3개의 숫자를 모두 맞히셨습니다! 게임 종료");
System.exit(0);
}
//출력
public static void print(int strike,int ball) {
if(strike==0 && ball==0) System.out.println("낫싱");
else if(strike!=0 && ball==0) System.out.println(strike+" 스트라이크");
else if(strike==0 && ball!=0) System.out.println(ball+"볼");
else System.out.println(strike+" 스트라이크 "+ball+"볼");
}
//스트라이크,볼 확인
public static int sb(String number,Character input,int idx) {
if(input.equals(number.charAt(idx))) return 1;
else if(!input.equals(number.charAt(idx)) && number.contains(String.valueOf(input))) return 2;
else return 3;
}
//입력값 체크
public static void check(String number,String input) {
int strike=0, ball=0;
for(int i=0;i<3;i++) {
if(sb(number,input.charAt(i),i)==1) strike++;
else if(sb(number,input.charAt(i),i)==2) ball++;
else continue;
}
print(strike, ball);
}
//Main 함수
public static void main(String[] args){
String number=Create_Num();
Scanner sc=new Scanner(System.in);
System.out.println("정답: "+number);
while(true) {
System.out.print("숫자를 입력해주세요 ex)123 : ");
String result=sc.next();
if(result.equals(number)) exit(); //만약 맞힌다면 종료
else check(number,result);
}
}
}