Back-End

[JAVA] 기초 공부 4(문제풀기)

Minch13r 2024. 12. 31. 16:48

2024.12.31 오늘은 지금껏 배웠던 개념들을 포함한 문제를 풀기로 했다.


문제는 이와 같습니다.

정수 2개를 입력합니다. 정수1~정수2 사이의 랜덤수를 3개 출력해주세요. 단, 랜덤숫자끼리 중복X

 

import java.util.Random;
import java.util.Scanner;

public class Practice {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		System.out.println("정수 1을 입력하세요 : ");
		System.out.println(">>");
		int a = sc.nextInt();
		System.out.println("정수 2를 입력하세요(정수 1과 값이 달라야 하며 최소 차이가 2 이상이어야 합니다.) : ");
		System.out.println(">>");
		int b = sc.nextInt();

		if(a>b) {
			int tmp = a;
			a = b;
			b = tmp;
		}
		if(a == b) {  
		    System.out.println("두 수가 같습니다. 다시 입력해주세요!");
		    return; 
		} 
		if (b <= a+1) {  
		    System.out.println("범위가 너무 좁습니다! 두 수는 2 이상 차이가 나야 합니다!");
		    return;
		}

		Random rand = new Random(); 

		int num1 = rand.nextInt(b-a+1) + a; 

		int num2;
		while(true) { 
			num2 = rand.nextInt(b-a+1) + a;
			if(num1 != num2) break; 
		}

		int num3;
		while(true) { 
			num3 = rand.nextInt(b-a+1) + a;
			if(num1 != num3 && num2 != num3) break; 
		}
		System.out.println("입력된 범위 : " + a + " ~ " + b); 
		System.out.println("랜덤수 1 : " + num1); 
		System.out.println("랜덤수 2 : " + num2);
		System.out.println("랜덤수 3 : " + num3); 
	}
}

코드를 이와 같이 써봤습니다.

여러번 실행시켜보고 지적 받은 결과 첫번째 문제. 사용자 환경을 좀 더 쾌적하게 해줄 필요가 있다 생각했습니다.

뭔가 이상하다. 문제가 뭔지도 안 알려주고 냅다 입력하라고 한다. 그리고 옆에다 쓰라고 : 도 넣고 >>도 넣었는데 밑에줄에다 입력하라고 한다. 정말 이상하다.

 

두번째 문제, for문과 while문의 차이점을 정확히 알지 못하고 썼다는게 개그였다.

  • for문은 반복 횟수가 명확할 때 사용한다
  • while문은 반복 횟수가 불명확할 떄 사용한다.

이 차이점을 오늘 확실하게 알았다.

 

세번째 문제, scope라는 내용을 정의하지 못했다. 코딩공부를 조금 했다면 내부변수라는 내용을 알아 반복문을 빠져나오지 못한다고 설명이 가능하지만 다른사람한테 설명할 때는 scope라는 사용범위 개념을 알려주면서 설명하는게 더 좋은 방법이라는 것을 알았다.

 

네번째 문제, 반복되는 문장이나 내용은 상수화를 해주고 해당 내용에 변수명을 넣는게 좋다고 생각했다. 코드를 확인해보면 b-a+1이 반복되는데 이런 경우에는 final int RANDOMRANGE = b-a+1; 을 해주고 해당 내용에 RANDOMRANGE를 넣어 어떤 부분에 어떤 변수가 어떤 의도를 갖고 쓰는지 확인이 가능할 것 같았다.

 

다섯번째 문제, 아까와 같이 UI/UX 문제인데 정수2개가 같은 경우 "정수가 같습니다. 다시 입력하세요" 해놓고 프로그램을 종료시켰다. 개선해야 할 사항이다.

 

여섯번째 문제, 이 코드는 사용자가 쓸 수도 있고 개발자끼리 코드 쉐어를 할 수 있다. 이때 블록을 더 세밀하고 잘 볼 수 있게 나눠서 하면 더 좋을 것 같다.


문제점을 개선한 코드는 아래와 같다.

package day004;
import java.util.Random;
import java.util.Scanner;

public class Practice {

	public static void main(String[] args) {		
        		//입력받기 위해 scanner 객체 선언
		Scanner sc = new Scanner(System.in);
		//문제가 뭔지 명시하는 내용
		System.out.println("문제 : 정수 2개를 입력하세요. 정수1~정수2 사이의 랜덤수를 3개를 출력해주세요. 단, 랜덤숫자끼리는 중복되어서는 안됩니다.");

		//입력받을 a와 b 초기화
		int a = 0, b = 0;

		//while(true)는 어디까지 반복할지 불분명해서 사용했고 무한루프를 실행시켰습니다.
		while (true) {
			// 첫 번째 입력 받기
			System.out.print("정수 1을 입력하세요 : ");
			a = sc.nextInt();

			// 두 번째 입력 받기
			System.out.print("정수 2를 입력하세요(정수 1과 값이 달라야 하며 최소 차이가 2 이상이어야 합니다.) : ");
			b = sc.nextInt();

			// a가 b보다 큰 경우 두 수 교환
			if (a > b) {
				int tmp = a;
				a = b;
				b = tmp;
			} // a를 작은수로 가정하고 b를 큰수로 이번 코드에서 가정을 할거기 때문에 이렇게 사용

			// 입력값 검증 및 정렬
			if (a == b) { //숫자가 같으면 랜덤한 숫자 3개가 나와야 하는데 안 나옴
				System.out.println("두 수가 같습니다. 다시 입력해주세요!");
				continue; //다시 입력하라고 돌려보냄
			} else if (b <= a + 1) { //범위가 작으면 랜덤한 숫자가 3개가 안 나옴
				System.out.println("범위가 너무 좁습니다! 두 수는 2 이상 차이가 나야 합니다!");
				continue;  //다시 입력하라고 돌려보냄
			}
			break; // while문 탈출
		}

		// random 객체 선언
		Random rand = new Random();
		final int RANDRANGE = b - a + 1; //반복되는 내용 상수화
		//b는 마지막 값, a는 첫번째 값으로 범위를 지정해주고 +1을 해줘서 원하는 범위를 지정한다.
		//rand.nextINt()는 인덱스가 0부터 시작해서 10을 입력하면 0~9를 출력하기에 1~10 출력을 위해 +1을 해준다.

		// 범위 내에서 나오는 랜덤된 정수들이 저장되는 변수
		int num1 = rand.nextInt(RANDRANGE) + a;
		int num2;
		int num3;

		//num1과 num2가 같으면 다시 반복해야 하는 어디까지 반복할 줄 모르는 불명확성 때문에 while문 사용
		while (true) { //무한루프
			num2 = rand.nextInt(RANDRANGE) + a; //+a를 하는 이유는 시작점이 어딘지 몰라서 시작점을 더해주는 내용
			if (num1 != num2) { //num1과 num2가 다르면 중복은 안 된다는 조건 성립
				break; //while문 탈출
			}
		}

		//num1과 num3, num2와 num3가 같으면 다시 반복해야 하기에 반복의 불명확성 때문에 while문 사용
		while (true) { //무한루프
			num3 = rand.nextInt(RANDRANGE) + a;
			/* num1과 num3은 같지 않고 num2와 num3은 같지 않아야 하기에 AND 연산 사용
			*  AND연산은 곱하기(*)를 의미하므로 T * F = 1 * 0 = 0 = False를 의미한다.
			*  반대로 OR연산은 더하기(+)를 의미하므로 T + F = 1 + 0 = 1 = True를 의미한다.
			*  그렇기에 우리는 중복이 없어야 하므로 둘 다 참일 때만 결과가 참이 나오는 AND연산을 사용했다.*/
			if (num1 != num3 && num2 != num3) {
				break;
			}
		}

		// 결과 출력
		System.out.println("입력된 범위 : " + a + " ~ " + b);
		System.out.println("랜덤수 1 : " + num1);
		System.out.println("랜덤수 2 : " + num2);
		System.out.println("랜덤수 3 : " + num3);

	}
}