ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 019. 클래스와 인스턴스 : 접근지시제어자 활용, 메소드 중복정의(오버로딩) + 만년 달력, 주민등록번호 유효성 검사
    SsY/Class 2023. 3. 9. 00:53
    728x90

    2023.02.20 (월)

    클래스와 인스턴스
    - 클래스와 인스턴스 활용
    • Test102
      - 클래스와 인스턴스 활용
      - 가위,바위, 보 게임 만들기
    더보기
    /*=============================================
               ■■■ 클래스와 인스턴스 ■■■
               - 클래스와 인스턴스 활용
    ==============================================*/
    
    // 1 ~ 3 사이의 난수를 발생시켜서
    // 가위, 바위, 보 게임 프로그램을 구현한다.
    // 단, 클래스의 개념을 활용하여 처리할 수 있도록 한다.
    // (→RpsGame 클래스 설계)
    // 또한, 배열을 활용하여 처리할 수 있도록 한다.
    
    // ※ 기준 데이터 → 1:가위, 2:바위, 3:보
    
    // 실행 예)
    // 1:가위, 2:바위, 3:보 중 입력(1~3) : 4
    // 1:가위, 2:바위, 3:보 중 입력(1~3) : -2
    // 1:가위, 2:바위, 3:보 중 입력(1~3) : 2
    
    // - 유저	: 바위
    // - 컴퓨터 : 보
    
    // >> 최종 게임 결과 : 컴퓨터가 이겼습니다~!!!
    // 계속하려면 아무 키나 누르세요...
    
    import java.util.Random;
    import java.util.Scanner;
    
    class RpsGame
    {
    	private int c, u; // 컴퓨터의 난수, 유저의 난수
    	private String[] res = {"가위","바위","보"};
    
    	private void runC()	//컴퓨터 난수 발생시키는 메소드
    	{
    		Random rd = new Random();
    		c = rd.nextInt(3)+1;		// 0~2 → 1~3 사이 난수 발생
    	}
    
    	public void input()
    	{
    		runC(); // 공정성을 위해 컴퓨터의 난수 먼저 발생
    		Scanner sc = new Scanner(System.in);
    		do
    		{
    			System.out.print("1:가위, 2:바위, 3:보 중 입력(1~3) : ");
    			u = sc.nextInt();
    		}
    		while (u<1 || u>4);
    	}
    
    	public String cal()
    	{
    		String str = "오류입니다";
    
    		if (u==c)
    			str = "비겼습니다";
    		else if ((u==1&&c==3) || (u==2&&c==1) || (u==3&&c==2))
    			str = " 유저가 이겼습니다~!!!";
    		else 
    			str = "컴퓨터가 이겼습니다~!!!";
    		return str;
    	}
    
    	public void print(String a)
    	{
    		System.out.println("- 유저   : " + res[u-1]);
    		System.out.println("- 컴퓨터 : " + res[c-1]);
    		System.out.println();
    		System.out.println(">> 최종 게임 결과 : " + a);
    	}
    }
    
    public class Test102re
    {
    	public static void main(String[] args)
    	{
    		RpsGame rps = new RpsGame();
    		rps.input();
    		String res = rps.cal();
    		rps.print(res);
    	}
    }
    ※ java.util.Random;
      - 랜덤 클래스로 정수형 난수 발생 하는 메소드
     1) nextInt();
      - Int 형의 범위 (약 ± 21억) 내에서 난수를 1개 발생 시키는 메소드
     2) nextInt(int bound);
      - bound 는 정수이며, 이 때, 0 이상 bound 미만의 범위의 정수 내에서 난수를 1개 발생 시키는 메소드
      - nextInt(int bound) + n            //-- n은 정수형태의 증감 값
        n을 더하여 (0+n) 이상 (bound+n) 미만의 범위의 정수 내에서 난수를 1개 발생 시킬 수 있다.
    ex) nextInt(100)+1;
    →  0 ~ 99 까지의 범위 + 1
    →  1 ~ 100 까지의 범위

    + public 과 private 접근지시자를 구분하여 작성
      사용자가 호출하여 사용해야하는 메소드 혹은 접근해서 변경해야하는 변수라면 → public
      사용자가 호출할 필요가 없는 메소드 혹은 접근해서는 안되는 변수라면              → private 


    클래스와 인스턴스
    - 메소드 중복정의 (Method Overloading) == 메소드 오버로딩 
    ○ 메소드 오버로딩(Method Overloading)의 개요
    -  메소드 오버로딩이란 메소드가 처리하는 기능은 같고,
       메소드 괄호 속에 오는 인수(인자, 매개변수, 파라미터)의 갯수가 다르거나 자료형이(Data type)이 다른 경우
       메소드의 이름을 동일한 이름으로 부여하여 메소드를 정의 할 수 있도록 문법적으로 허용하게 되는데,
       이를 메소드 오버로딩(Method overloading) 이라고 한다.
    • Test103
      - 메소드 중복 정의(Method Overloading)
      - 관찰
    더보기
    public class Test103
    {
    	// 선을 그리는 메소드 정의
    	public static void drawLine()	// 클래스 메소드
    	{
    		System.out.println("====================");
    	}
    
    	// 선을 그리는 메소드 정의 → 선의 형태를 바꾸어 그리는 메소드
    
    	//public static void drawLine()
    	//public static void drawLine2()
    	public static void drawLine(char c)
    	{
    		for (int i=0; i<20; i++)
    			System.out.print(c);
    		System.out.println();
    	}
    
    	// 선을 그리는 메소드 정의 → 선의 형태와 길이를 바꾸어 그리는 메소드
    	public static void drawLine(char c, int n)
    	{
    		for (int i=0; i<n; i++)
    			System.out.print(c);
    		System.out.println();
    	}
    	public static void main(String[] args)
    	{
    		/*
    		Test103 ob = new Test103();	// 클래스 메소드이기 때문에 인스턴스 구문 필요X
    		ob.drawLine();
    		*/
    		//Test103.drawLine();	// 클래스 메소드이기 때문에 __ 생략가능
    		
            drawLine();
    		//--==>> ====================
    
    		drawLine('-');
    		//--==>> --------------------
    
    		drawLine('/');
    		//--==>> ////////////////////
    
    		drawLine('*');
    		//--==>> ********************
    
    		drawLine('<', 30);
    		//--==>> <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    
    		drawLine('#', 50);
    		//--==>> ##################################################
    	}
    }

    - 메소드는 스코프 내에서 식별자 역할을 하기 때문에 동일한 이름을 가져서는 안되나,
      위의 관찰 결과와 같이, 선을 그리는 같은 기능의 메소드를 여러개 만들기 위해서
      매번 draw1(), draw2(), draw3() .... 이와 같이 이름을 바꿔야만한다면,
      사용자가 모든 메소드의 이름을 매번 기억해가며 사용해야하는 불편함이 생길 것 이다.
      이를, 동일한 이름을 사용하는 대신, 넘겨주는 변수의 갯수나 데이터타입을 통해서 구분을 시켜주는 문법이다.  

    ※ 추후 나올 메소드 오버 라이딩과 구분을 잘 해야한다 (면접질문으로 둘을 비교하는 것이 자주 나옴) ※


    • Test104
      - 메소드 중복 정의(Method Overloading가 가능한 형태와 불가능한 형태
      - 특징과 주의사항 관찰 
    더보기

    ※ 메소드의 정의된 순서는 중요도에 영향을 미치지 않는다 ※

    /*======================================================================
                          ■■■ 클래스와 인스턴스 ■■■
      - 메소드 중복 정의(Method Overloading가 가능한 형태와 불가능한 형태
    ======================================================================*/
    
    public class Test104
    {
    	public static void main(String[] args)
    	{
    		//print('A');		// char 타입 구성을 하지 않아도 자동 형 변환 규칙에 의해 정수형으로 print 가능!
    
    		print(3.14);
    		double result = print(5.67);						// 문번호 24번
    	}
    
    	public static void print() {}
    	//public static void print() {}			//--(X) 16번 or 17번 문번 둘 중에 하나만 있으면 된다. 어떤 것이든!
    	public static void print(char c) {}			//-- 자동 형 변환 규칙 check!
    	public static void print(int i) {}	
    	//public static void print(int j) {}		//--(X) 메소드를 처리하는 과정에서 매개변수의 이름은 확인X (매개변수 타입과 갯수만 확인)
    	public static void print(int i, int j) {}
    	public static void print(double d) {}		//-- 자동 형 변환 규칙 check!
    	//public static void print(double e) 
     	//{
    	//	return 10.0;			//-- (X) return 인데 자료형이 void 이므로 불가능
     	//}
    	//public static double print(double e) 
    	//{
    	//	return 10.0;		//-- (X) 대입연산자 오른쪽부터 확인, 자바는 둘 다 똑같은 것으로 확인하게 됨
    	//}				//check  return 자료형의 변경은 오버로딩에 해당되지 않는다!
    }

    만년달력 만들기
    • Test105
      - 만년 달력 만들기 (calendar 클래스 미사용)
    더보기
    /*=============================================
                   ■■■ 만년 달력 ■■■
        - 다음과 같은 기능의 프로그램을 구현한다
    ==============================================*/
    
    // 실행 예)
    // 『연도』를 입력하세요 : 2023
    // 『월』을 입력하세요   : 2
    /*
    	[ 2023년 2월 ]
     일	 월	 화	 수	 목	 금	 토
    ============================
    			  1   2   3   4
      5   6   7   8   9  10  11
     12  13  14  15  16  17  18
     19  20  21  22  23  24  25
     26  27  28
    ============================
    계속하려면 아무 키나 누르세요...
    */
    
    /*
    ○	문제 인식 및 분석
    	- 서기 1년 1월 1일 : 월요일
    	- 연도가 4의 배수이면서 100의 배수가 아니거나.
    	  400의 배수이면 2월은 29일(윤년),
    	  나머지 2월은 28일(평년)
    	- 만약... 2023년 2월 달력을 그린다고 가정하면
    	  1년 1월 1일 ~ 2023년 1월 31일 까지의 날 수를 구한 다음
    	  -----------------------------
    	  (1년 1월 1일 ~ 202년 12월 31일) + (2023년 1월 1일 ~ 2023년 1월 31일)
    	  그 날수에 『+1』연산을 수행하면...
    	  2023년 2월 1일의 요일을 확인할 수 있다.
    	  ----------------------------------------------여기까지 수행하면 달력 그릴 준비 끝
    	- 요일 = 전체날수 % 7
    	- 요일 = 0 → 일요일
    			 1 → 월요일
    			 :      :
    			 6 → 토요일
    */
    
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.IOException;
    
    public class Test105
    {
    	public static void main(String[]args) throws IOException
    	{
    		//BufferedReader 인스턴스 생성
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    
    		// 배열 선언 및 초기화
    		//-- 각 달이 담고 있는 마지막 날짜 (매 월의 최대 날짜)
    		int[] days = {31,28,31,30,31,30,31,31,30,31,30,31};
    		// 배열인덱스  0  1  2  3  4  5  6  7  8  9 10 11
    		// 월         1  2  3  4  5  6  7  8  9 10 11 12
    
    		//테스트(확인)
    		//System.out.println("배열의 길이 : " + days.length);
    		//--==>> 배열의 길이 : 12
    
    		//주요 변수 선언
    		int nalsu, y, m, w;		//-- 날 수, 연, 월, 요일
    
    		do
    		{
    			System.out.print("『연도』를 입력하세요 : ");
    			y = Integer.parseInt(br.readLine());
    		}
    		while (y<1);
    		//-- 사용자로부터 입력받은 연도가 1보다 작을 경우 다시 입력받기~
    
    		do
    		{
    			System.out.print("『월』을 입력하세요   : ");
    			m = Integer.parseInt(br.readLine());
    		}
    		while (m<1 || m>12);
    		//-- 사용자로부터 입력받은 월이 1보다 작거나 12보다 클 경우 다시 입력받기~!!!
            
    		//-------- 여기까지 수행하면 유효한 연도와 월을 사용자로부터 입력받은 상태
    
    		// 입력받은 연도에 해당하는 2월의 마지막 날 계산
    		if ((y%4==0 && y%100!=0) || y%400==0)	// 윤년이라면...
    			days[1] = 29;
    
    		// 1년 1월 1일 ~ 입력받은 연도의 이전연도 12월 31일 까지의 날 수 계산
    		 nalsu = (y-1)*365 + (y-1)/4 - (y-1)/100 + (y-1)/400;
    
    		// 입력받은 연도(해당 연도) 1월 1일 ~ 입력한 월의 이전 월까지의 날 수 계산
    		for (int i=0; i<m-1; i++)
    		{
    			// nalsu 를 월의 최대값으로 누적합 연산
    			nalsu += days[i];
    		}
    
    		// 입력 받은 월의 1일을 날 수 누적 연산
    		nalsu += 1;		// ++nalsu;
    		//------- 여기까지 수행하면 모든 날 수에 대한 종합 처리 완료~!!!
    		//		  (1년 1월 1일 부터 입력연도 입력월의 1일 까지)
    
    		// 요일 확인
    		//-- 입력받은 연의 입력받은 월의 1일이 무슨 요일인지 확인하기 위한 연산 수행
    		w = nalsu % 7;
    		// w:0 → 일요일
    		//      :
    		// w:6 → 토요일
    
    		// 출력 (달력 그리기)
    		System.out.println();
    		System.out.printf("\t[ %d년 %d월]\n", y, m);
    		System.out.println();
    		System.out.println("  일  월  화  수  목  금  토"); // 하루 4칸
    		System.out.println("============================");
    		
    		// 특정 요일부터 1일이 출발(시작) 할 수 있도록 공백 발생(지정)
    		for (int i=1; i<=w; i++)
    			System.out.print("    ");	// 공백 4칸 지정
    		
    		// 해당 월(입력한 월)의 날짜만 출력될 수 있도록 반복문 구성
    		for (int i=1; i<=days[m-1]; i++)
    		{
    			System.out.printf("%4d", i);
    			w++;
    			//-- 반복문을 통해 날짜를 처리하는 만큼
    			//	 요일도 함께 증가할 수 있도록 처리
    
    			// 일요일을 구성하려는 경우...
    			// (즉, 이번에 출력하고자 하는 날짜가 일요일인 경우)
    			if (w%7==0)
    				System.out.println(); //개행
    		}
    		// 달의 마지막 날짜가 출력 형식을 모두 채웠을 경우
    		// (즉, 토요일까지 라인 전체가 출력되었을 경우)
    		// 이미 일요일 개행이 이루어졌기 때문에
    		// 이 경우에는 추가 개행을 하지 않도록 처리~!!!
    		if (w%7!=0)
    			System.out.println();
    		System.out.println("============================");
    	}
    }
    
    // 실행결과
    
    /*
            [ 2023년 2월]
    
      일  월  화  수  목  금  토
    ============================
                   1   2   3   4
       5   6   7   8   9  10  11
      12  13  14  15  16  17  18
      19  20  21  22  23  24  25
      26  27  28
    ============================
    계속하려면 아무 키나 누르십시오 . . .
    */
    /*
            [ 2023년 9월]
    
      일  월  화  수  목  금  토
    ============================
                           1   2
       3   4   5   6   7   8   9
      10  11  12  13  14  15  16
      17  18  19  20  21  22  23
      24  25  26  27  28  29  30
    ============================
    계속하려면 아무 키나 누르십시오 . . .
    */
    /*
    『연도』를 입력하세요 : 2024
    『월』을 입력하세요   : 2
    
            [ 2024년 2월]
    
      일  월  화  수  목  금  토
    ============================
                       1   2   3
       4   5   6   7   8   9  10
      11  12  13  14  15  16  17
      18  19  20  21  22  23  24
      25  26  27  28  29
    ============================
    계속하려면 아무 키나 누르십시오 . . .
    */

    주민등록번호 유효성 검사
    • Test106
      - 주민등록번호 유효성 검사
      - 지금은 활용되고 있지 않지만 수식 구성 연습용으로 진행
    // ※ 문제 해결을 위한 추가 팁
    // 배열.length        → 배열의 길이(배열방의 갯수) 반환         //.length 속성
    // 문자열.length()  → 문자열의 길이 반환                              //.length() 메소드

    // (메소드 오버로딩)
    // 문자열.substring()        → 문자열 추출
    // 문자열.substring(m,n)  → 문자열 m 번째 위치에서 n-1번째 위치까지 추출(인덱스는 0부터)
    // 문자열.substring(m)     → 문자열 m 번째 위치에서 문자열의 끝까지 추출(인덱스는 0부터)

    추가 팁 관찰)

    더보기
    		// 테스트
    		/*
    		String strTemp = "행성c"; 
    		System.out.println(strTemp.length());
    		//--==>> 3
    
    		strTemp = "동해물과 백두산이 마르고 닳도록";
    		System.out.println(strTemp.length());
    		//--==>> 17
    
    		System.out.println("1234567890".length());
    		//--==>> 10
    
    		strTemp = "412-120";
    		System.out.println(strTemp.length());
    		//--==>> 7
    		*/
    
    		/*
    		String strTemp = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    		System.out.println(strTemp.substring(13,17));
    		//--==>> NOPQ
    
    		//System.out.println(strTemp.substring(13,57));
    		//--==>> 에러발생 (런타임 에러)
    		//		 StringIndexOutOfBoundsException
    
    		System.out.println(strTemp.substring(13));
    		//--==>> NOPQRSTUVWXYZ
    		
    		System.out.println(strTemp.substring(13,strTemp.length()));
    		//--==>> NOPQRSTUVWXYZ
    		*/

    문제)

    더보기
    /*=============================================
    	■■■ 주민등록번호 유효성 검사 ■■■
    ==============================================*/
    
    /*
    ○	주민등록번호 검증 공식
    
    	① 마지막 자리를 제외한 앞 자리 수를 규칙에 맞게 곱한다.
    
    		123456-1234567 (주민번호)
    		****** ******* ---------- 각 자릿수에 곱하기
    		234567 892345
    
    	② 규칙에 맞게 곱셈 연산을 수행한 결과를 모두 더한다.
    
    	ex) 7 5 0 6 1 5 - 1 8 6 2 1 3 3 
    		* * * * * *   * * * * * *
    		2 3 4 5 6 7   8 9 2 3 4 5
    		----------------------------
    	→ 14 + 15 + 0 + 30 + 6 + 35 + 8 + 72 + 12 + 6 + 4 + 15
    	== 217
    
    	③ 더해진 결과 값을 11로 나누어 『나머지』를 취한다.
    
    		217 % 11 = (몫 (X)19...) 8(나머지O)
    
    	④ 11에서 나머지 8을 뺀 결과 값을 구한다.
    		11 - 8 → 3
    
    		※  3의 처리 과정에서 나머지가 0인 경우 → 11 - 0 → 11
    		                      나머지가 1인 경우 → 11 - 1 → 10
    
    			이를 다시 10으로 나누어 나머지를 취한다.	11 → 1
    													  10 → 0
    
    	⑤ ④의 연산 결과가 주민번호를 구성하는 마지막 숫자와
    		일치하는지의 여부를 비교하여 확인한다.
    
    		일치   → 유효한 주민번호
    		불일치 → 잘못된 주민번호
    */
    
    // 실행 예)
    // 주민번호 입력(xxxxxx-xxxxxxx) : 123456-12345678	//→ 입력 갯수 초과
    // >> 입력 오류~!!!
    // 계속하려면 아무 키나 누르세요...
    
    // 주민번호 입력(xxxxxx-xxxxxxx) : 123456-123456	//→ 입력 갯수 미달
    // >> 입력 오류~!!!
    // 계속하려면 아무 키나 누르세요...
    
    // 주민번호 입력(xxxxxx-xxxxxxx) : 750615-1252085	//→ 유효한 주민번호
    // >> 정확한 주민번호~!!!
    // 계속하려면 아무 키나 누르세요...
    
    // 주민번호 입력(xxxxxx-xxxxxxx) : 750615-1252086	//→ 잘못된 주민번호
    // >> 잘못된 주민번호~!!!
    // 계속하려면 아무 키나 누르세요...

    풀이)

    더보기
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.IOException;
    
    public class Test106
    {
    	public static void main (String[] args) throws IOException
    	{
    		// 입력받은 주민등록번호를 담을 배열
    		String[] arr = new String[14];
    		// 입력받은 주민등록번호의 유효성 검사를 할 때 곱할 수 -- 13개
    		int[] mul = {2,3,4,5,6,7,0,8,9,2,3,4,5};
    		// 곱한 수의 합을 담을 변수
    		int sum=0;
    
    		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));	// 문자열 추출 메소드 사용
    
    		// 주민번호 입력받기
    		System.out.print("주민번호 입력(xxxxxx-xxxxxxx) : ");
    		String str = br.readLine();
    		int n = str.length();	// 입력받은 문자열 길이 확인
    
    		if (n != 14)
    		{
    			System.out.println(">> 입력오류~!!!");
    			return;	// 14자리가 안되면 입력오류 출력 후 메소드 종료 → main() 메소드 종료 → 프로그램 종료
    		}
    		//-------------이까지 수행 시 14자리 입력 받음
    
    		// 입력받은 문자열 배열의 방에 한자리씩 출력하여 담기
    		for (int i=0; i<str.length(); i++)	// 인덱스도 배열도 0번부터 시작!
    			arr[i] = str.substring(i,i+1);
    
    		// 주민등록번호 유효성 검사
    		// ① 각 자릿수 곱하여 합하기
    		for (int i=0; i<mul.length; i++)
    		{
    			if (i==6)
    				continue;	// 6번째 방은 "-" 의 방이므로, (해당 차순을 무시하고) 반복문을 계속한다
    			sum += Integer.parseInt(arr[i])*mul[i];
    		}
    		// ② 더해진 결과 값을 11로 나누어 『나머지』를 구한다.
    		// ③ 11에서 나머지를 뺀 결과 값이 0 또는 1 일 때, 나머지를 10으로 다시 나누어 나머지가 13번째와 동일한지 확인한다.
    		//    11에서 나머지를 뺀 결과 값이 2 ~ 9 일 때, 나머지가 13번째와 동일한지 확인한다. 
    		//    (2 ~ 9 인 경우는 다시 한 번 10으로 나눠도 똑같으므로)
    		int res = 11- (sum % 11);
    		res = res % 10;
    
    		if (Integer.parseInt(str.substring(13)) == res)
    			System.out.println("정확한 주민번호 ~");
    		else
    			System.out.println("잘못된 주민번호 ~");
    	}
    }

     

    //  개인적 감상

    더보기

    최근에 Java API Document 를 찾고 메소드를 사용하는 연습을 하는데,
    아직까지 클래스의 패키지나 적절한 메소드의 사용법을 찾는것이 쉽지는 않다.
    다만, 이렇게 API Document 를 찾다보니 헛다리를 짚더라도 많은 메소드 들을 접하고 테스트 할 기회가 생긴 것 같다.  틈틈이 API Documet 를 들여다보고 여기 저기 메소드를 기웃거려봐야할 필요성을 깨달아간다.

    728x90
Designed by planet-si