숫자 야구 게임 만들기 !
사용자가 3 ~ 5중의자릿수를 입력하면 그 입력값에 따른 자릿값의 난수 생성 메서드
// 유저가 자릿수를 입력했을 때 그 입력한 값을 받아서 그 값만큼의 자릿수를 가진 랜덤 숫자 생성하는 메서드
public String createChoiceRandomNumber(String userChoiceNumber) throws Exception{
String randomNumber = "";
if(reg.checkIngNumber(userChoiceNumber)){
int userNumber = Integer.parseInt(userChoiceNumber);
if(userNumber >= 3 && userNumber <= 5){
this.randomDigits = userNumber;
// Collections.shuffle로 배열의 값을 랜덤으로 뒤 섞은 후
// subString을 이용하여 0번째부터 유저가 입력한 자릿수만큼의 수를 잘라내어 다시 num에 대입
// 그 후 for문을 돌리면서 finerNumer에 하나하나 쌓음.
List <String> num = new ArrayList<>();
for(int i = 1; i < 10; i++){
num.add(i+"");
}
Collections.shuffle(num);
num = num.subList(0,userNumber);
for(String item : num){
randomNumber += item;
}
return randomNumber;
}
}
throw new BadInputException("3, 4, 5 중에서만 입력 했는지");
}
이후 유저가 입력한 입력한 숫자의 자릿수가 처음에 세팅한 랜덤 숫자의 자릿수와 일치한지,
또 중복된 숫자는 없는지 검사하는 메서드
// 유저가 입력한 숫자의 자릿수가 중복 숫자가 없는지와 랜덤 숫자의 자릿수와 일치한지
// 판별하는 메서드
public boolean duplicateCheck(String userInputNumber, int randomDigits) {
HashSet<String> numbers = new HashSet<>();
// set에는 중복값이 들어가면 자동으로 삭제가된다.
// 그러므로 입력받은 값중에 중복값이 있는지 확인하기 위하여
// set 컬렉션에 저장을하고나서
// 컬렉션의 저장된 데이터들의 배열 길이가 랜덤 숫자의 자릿수와 일치하면
// 중복값이 없고 자릿수의 맞는 수를 입력한것이기 떄문에
// true리턴해준다.
// 아니라면 false가 리턴.
for(int i = 0; i < userInputNumber.length(); i++){
numbers.add(userInputNumber.substring(i, i+1));
}
return numbers.size() == randomDigits;
}
올바른 값이 들어왔다면 정답인지 판별 후 스트라이크의 개수와 볼 개수를 구한다.
// 랜덤숫자와 유저가 입력한 숫자를 비교하여
// 정답인지 확인하는 메서드
public boolean filterNum(String randomNumber,String userInputNumber) throws Exception{
List <String> userInputList = new ArrayList<>();
List <String> randomList = new ArrayList<>();
int strikeCount = 0;
int ballCount= 0;
// 유저가 입력한 숫자가 숫자로만 이루어져있는지, 또 랜덤 숫자의 자릿수와 같은지
// 판별 후 맞다면 각각 스트라이크의 수와 볼의 수를 센다.
if(reg.checkIngNumber(userInputNumber) && reg.duplicateCheck(userInputNumber, getRandomDigits())){
for(int i = 0; i < userInputNumber.length(); i++){
userInputList.add(userInputNumber.substring(i, i+1));
randomList.add(randomNumber.substring(i, i+1));
}
for(int i = 0; i < randomList.size(); i++){
for(int j = 0; j < userInputList.size(); j++){
// 랜덤 숫자 배열의 각방마다 유저가 입력한 값을 하나 씩 넣은 배열의
// 0번부터 자릿수길이만큼 돌면서 일치하는게 있다면
if(randomList.get(i).equals(userInputList.get(j))){
//이 if문을 들어와서 그 일치하는 값이 자릿수까지도 일치하는지 확인후
if(randomList.get(i).equals(userInputList.get(i))){
// 자릿수도 일치하면 스트라이크 값 증가
strikeCount++;
}
// 아니라면 볼 값 증가
else{
ballCount++;
}
}
}
}
// 스트라이크의 갯수가 자릿수보다 작다면 정답을 맞추지 못했다는 것을 의미.
if(strikeCount < randomDigits){
// 스트라이크의 갯수를 저장.
this.strike = strikeCount;
// 볼 갯수 저장
this.ball = ballCount;
}
else{
// 정답이라면 만들어둔 리스트의 저장 해주면서 true 리턴.
this.result.add(Integer.parseInt(userInputNumber));
return true;
}
}
else{
throw new BadInputException("알맞게 입력했는지");
}
return false;
}
실행 화면
위 사진에선 테스트를 위해 sout를 통해 콘솔에 정답인 랜덤숫자를 미리 출력하게해놨다.
이번 숫자 야구게임을 만들면서 난수를 생성하기 위해 ThreadLocalRandom을 사용해봤다.
Random 클래스는 원래 알고 있었지만 ThreadLocalRandom은 처음 보는거라 검색해봤는데
thread 별로 격리된 random number generator라고 한다.
Random은 멀티쓰레드 환경에서 하나의 인스터스에서도 전역적으로 의사난수를 반환하기에
같은시간에 동시 요청이 들어올 경우 경합 상태에서 성능에 문제가 생길 수 있다고한다.
그렇지만 ThreadLocalRandom은 멀티 쓰레드 환경에서 서로 다른 인스턴스들에 의해 의사 난수를
반환하기 때문에 동시성 문제에도 안전하다고한다. 이러한 차이로 Random보다는
ThreadLocalRandom을 쓰는 것이 더 좋다고한다
의사난수 : 처음에 주어지는 초기값을 이용하여 이미 결정되어 있는 메커니즘에 의해 생성되는 수
경합 상태 : 다중 프로그래밍 또는 다중 처리기 시스템에서 두 명령어가 동시에 같은 기억 장소를
엑세스할 때 그들 사이의 경쟁에 의해 수행 결과를 예측할 수 없게 되는 것이다.
평소에 List와 ArrayList를 자주 이용했지만
이번에 중복값을 허용하지 않는다는 요구사항에는 도움이 될 것 같지않아서
잘 사용하지 않아봤던 HashSet을 이용해봤는데 중복체크와 중복 없는
난수 만드는데 정말 많은 기여를 했다 다음에도 이러한 요구사항이나
로직이 필요하면 Set부터 찾을 것 같다.
또한 보통은 리스트에서 .get() 메서드를 통해 데이터를 뽑아왔지만
Set은 .get()이 없었다... 그래서 찾아봤더니 Iterator 인터페이스라는게 있었다.
Iterator는 자바의 컬렉션 프레임워크에서 컬렉션에 저장되어 있는 요소들을 읽어오는 방법을
Iterator 인터페이스로 표준화했다고한다.
Iterator 인터페이스의 메서드는 세가지가 있는데
hasNext() : 읽어올 요소가 있으면 true, 없으면 false.
next() : 컬렉션에서 하나의 객체를 가져온다.
remove() : 컬렉션에서 객체를 제거한다.
이중에 hasNext()와 next() 메서드를 이용하여 HashSet에 있는 데이터들을 이용하였다.
public String randomNumber(int number){
HashSet <Integer> hs = new HashSet<>();
String randomNumber = "";
while(true){
int num = ThreadLocalRandom.current().nextInt(1,10);
hs.add(num);
if(hs.size() == number){
break;
}
}
Iterator <Integer> iterator = hs.iterator();
while(iterator.hasNext()){
randomNumber += iterator.next();
}
return randomNumber;
}
이렇게 이번에 만들면서 평소에 잘 사용하지 않았던 컬렉션을 이용해보면서 처음 알게된
인터페이스도 사용해봤는데 정말 재미있었다
이번 야구만들기 과제는 생각보다 빨리 완성한 것 같은데
저번 계산기 과제가 도움이 많이 된 것 같다.
자세한 코드는 아래 링크로 봐주세요 !!
https://github.com/HaSeung2/baseball-game
'TIL' 카테고리의 다른 글
Database - DBMS, SQL (1) | 2024.09.26 |
---|---|
SRP - 단일 책임 원칙 (2) | 2024.09.25 |
[TIL] 9월 13일 (1) | 2024.09.13 |
[TIL] 숫자 야구 게임 만들기 (2) | 2024.09.12 |
[TIL] 계산기 3레벨 마무리 (1) | 2024.09.10 |