✿∘˚˳°∘°

8일차 : 배열 본문

국비수업/JAVA

8일차 : 배열

_HYE_ 2022. 12. 7. 23:17

2022/12/07

[ 1. 버블 정렬 ] =====================================================================

작은수부터 출력하기(정렬)

 

[ 자리바꿈로직 ]

if(arr[0] > arr[1]) {
           int tmp = arr[0];//배열 첫번째값을 임시로 넣어둘 임시공간
           arr[0] = arr[1];
           arr[1] = tmp;
}
if(arr[1] > arr[2]) {
           int tmp = arr[1];
           arr[1] = arr[2];
           arr[2] = tmp;
}
if(arr[2] > arr[3]) {
           int tmp = arr[2];
           arr[2] = arr[3];
           arr[3] = tmp;
}
if(arr[3] > arr[4]) {
           int tmp = arr[3];
           arr[3] = arr[4];
           arr[4] = tmp;
} //첫번째 정렬끝
if(arr[0] > arr[1]) {
           int tmp = arr[0];
           arr[0] = arr[1];
           arr[1] = tmp;
} ~~ 반복

 

	public void exam4() {
		//길이가 5인 정수형 배열을 생성하고 반복문을 통해 숫자 5개를 입력받는다.
		//중간에 정렬하는 코드를 만들어서 작은수부터 출력한다.(정렬)
		Scanner sc = new Scanner(System.in);
		int[] arr = new int[10];
		for(int i=0; i<arr.length; i++) {//입력for문
			System.out.print((i+1)+"번째 숫자 입력 : ");
			arr[i] = sc.nextInt();
		}
		//배열 0번째 값 과 배열 1번째 값을 비교해서 
		//배열 0번째가 더 크면 자리를 바꾸는 로직		
		for(int i=0; i<arr.length-1; i++) {
			//배열 내부값을 검사하면 검사수 : 배열길이-1 / 5칸배열(0~4) : 0-1, 1-2, 2-3, 3-4 
			for(int j=0; j<arr.length-1-i; j++) {
				//j와 j+1을 비교하기때문에 배열.length까지를 범위로 잡으면 배열을 넘어가므로 error
				//거기에 한번돌아가면 마지막부터 배열값이 이미 정렬이되므로 -i를 해주어 불필요한 반복제거 
				//-i를 빼더라도 결과는 맞게 나오지만, 불필요한 반복이 동작하므로 i를 빼주는 것.
				if(arr[j] > arr[j+1]) { //j인덱스가 j+1인덱스보다 값이 클때 구동
					int tmp = arr[j];//j에 j+1값을 넣어줄거기때문에(덮어쓰기) 기존j는 변수를 많들어서 대입해놓음
					arr[j] = arr[j+1];//j+1의 값을 j에 대입
					arr[j+1] = tmp;	//tmp에 저장되어있던 j인덱스의 값을 j+1인덱스에 대입(결과 : 위치가 서로 반대가됨) 
				}
			}
		}
	/*	if(arr[0] > arr[1]) {
			//자리바꿈로직
			int tmp = arr[0];//배열 첫번째값을 임시로 넣어둘 임시공간
			arr[0] = arr[1];
			arr[1] = tmp;
		}
		if(arr[1] > arr[2]) {
			int tmp = arr[1];
			arr[1] = arr[2];
			arr[2] = tmp;
		}
		if(arr[2] > arr[3]) {
			int tmp = arr[2];
			arr[2] = arr[3];
			arr[3] = tmp;
		}
		if(arr[3] > arr[4]) {
			int tmp = arr[3];
			arr[3] = arr[4];
			arr[4] = tmp;
		}================================= 첫번째 정렬
		if(arr[0] > arr[1]) {
			int tmp = arr[0];
			arr[0] = arr[1];
			arr[1] = tmp;
		}
		*/
		for(int i=0; i<arr.length; i++) {//출력 for문
			
			System.out.print(arr[i]+" ");
		}
	}

[ 2. 중복값 검사  ] ==================================================================

:정수를 입력받아 기존에 입력하여 배열에 들어간 값이면 중복입니다 출력 + 재입력

	public void exam5() {
		//1. 배열에 들어가는 숫자는 중복이면 중복입니다 메세지 출력
		//2. 배열에 중복숫자가 들어갈 수 없도록
		//단, 0은 입력하지 않는다고 가정
		//num : 사용자가 입력한 숫자가 들어있음
		//배열 : 최종적으로 저장할 숫자
		Scanner sc = new Scanner(System.in);
		int[] arr = new int[5];
		for(int i=0; i<arr.length; i++) {
			System.out.print((i+1)+"번째 숫자 입력 : ");
			int num = sc.nextInt();
			boolean bool = true;
			for(int j=0; j<arr.length; j++) {
				if(num == arr[j]) {
					i--;//중복시 다시 해당회차를 입력받기 위해서
					bool = false;//중복이 하나라도 있으면 아래의 값대입코드실행X
					System.out.println("중복");
					break; //하나라도 중복되면 로직종료(중복체크를 멈추는 break;)
				} //else{ arr[i] = num; } => [X]
				  //이 경우 첫번째 배열이랑만 체크하고 다음인덱스랑 비교하지않고 값을 넣어버림 
			}
			//중복이 하나라도 있으면 배열에 값을 넣지 않음
			if(bool) {
				arr[i] = num;
			}		
		}
		for(int i=0; i<arr.length; i++) {
			System.out.print(arr[i]+"\t");
		}
	}
	
	public void exam55() {
		Scanner sc = new Scanner(System.in);//사용자가 입력받기위해 스캐너사용
		int[] arr = new int[5];//5칸짜리 배열생성
		
		for(int i=0; i<arr.length; i++) {
			System.out.print((i+1)+"번째 숫자를 입력하세요 : ");//1~5번 입력을 받기위해(배열인덱스 0~4)
			int num = sc.nextInt();//입력받은 숫자를 저장할 정수형변수
			boolean bool = true;//중복일경우 입력받은 값을 배열에 넣지않기위한 변수
			for(int j=0; j<arr.length; j++) { //j<arr.length인 이유 i로 하면 0/01/012이렇게검사되므로
				if(arr[j] == num) { //j 0 1 2 ... arr.length
					i--;//위에서 증감을하는데 재입력을 받기위해 i값을 줄여준다. 
					bool = false;//중복값이 나오면 아래에서 값대입을 하지않기위한변수
					System.out.println("중복입니다.");
					break; //j 0~arr.length까지 돌리는동안 중복이 하나라도 있으면 코드실행x
					//i=0 - j~arr.length : 0번인덱스입력할때 배열인덱스중복검사(0~arr.length)
					//i=1 - j~arr.length : 1번인덱스입력할때 배열인덱스중복검사(0~arr.length)
					//배열인덱스 중복검사 시 만갸 arr[1]의 인덱스와 num이 중복되면 어차피 넣어주지 않을거기때문에
					//break;를 통해 for문을 나가주고 다음 for문(i)을 실행하기위해
				} //j-for문에 else{ arr[i]=num }을 해주면 안되는 이유
				  //여기에 else를 넣어버리면 0번인덱스만 검사를하고 이후인덱스는 중복여부검사를 하지않고
				  //(if문은 if가아니면 바로 else로 가버리니까)바로 값을 넣어버리므로 이후에는 중복값이 들어갈수잇다.
			}
			if(bool) {//내부for문(j)에서 arr[j]==num이 충족되면 bool = false가 되어 아래코드 실행x
				arr[i] = num;
			}
		}
	}

 

[ 3. 로또 프로그램 ] =================================================================

: 범위1~45 / 중복값X / 버블정렬 /

사용자에게 값을 6개 입력받아 중복값검사와 버블정렬 후 출력.

컴퓨터는 랜덤값 6개를 받아 중복값검사와 버블정렬 후 출력.

사용자가 입력한값과 컴퓨터의 랜덤값의 일치불일치를 확인하여 일치가 6이상일시 1등! 

	public void lotto() {
		//범위조절(1~45), 유저컴퓨터 중복X
		//사용자번호 컴퓨터번호 정렬되어 출력
		//맞은갯수 출력(6개:1등 5개:2등 - 꽝)
		Scanner sc = new Scanner(System.in);
		Random r = new Random();
		System.out.println("=========== 로또 프로그램 ===========");
		int[] uLotto = new int[6];//입력한번호가 들어갈 배열(중복x, 버블정렬)
		int[] cLotto = new int[6];//컴퓨터 랜덤번호가 들어갈배열(중복x, 버블정렬)
		
		for(int i=0; i<uLotto.length; i++) {//사용자입력for문
			boolean bool = true;//사용자중복값 외부for문안에있어야 구동할때마다 true가 되므로 꼭!!!!
			System.out.print((i+1)+"번째 번호 입력(1~45) : ");
			int uNum = sc.nextInt();//사용자가 입력한 로또번호
			if(uNum <= 0 || uNum > 46) {
				System.out.println("1~45중 한개를 입력해주세요.");
				i--;
			}else {//1 <= uNum && num <= 45
				for(int j=0; j<uLotto.length; j++) {//사용자입력중복체크
					if(uNum == uLotto[j]) {
						bool = false;
						i--;
						System.out.println("이미 중복된 번호입니다. 다시 입력해주세요.");
						break;
					}
				}
				if(bool) {
					uLotto[i] = uNum;
				}

			}//범위else문종료
		}
		//사용자값 출력 for문(작은순서대로 버블정렬)
		for(int i=0; i<uLotto.length-1; i++) {
			for(int j=0; j<uLotto.length-1-i; j++) {
				if(uLotto[j] > uLotto[j+1]) {
					int tmp = uLotto[j];
					uLotto[j] = uLotto[j+1];
					uLotto[j+1] = tmp;
				}
			}
		}//사용자 버블정렬종료
		int count = 0; //회차변수
		while(true) {//54321등이 되어야 종료되는 반복문		
			//컴퓨터 랜덤번호 출력
			int win = 0;//컴퓨터-사용자비교를해서 동일하면 카운트해줄 변수(while내부에 있어야계속 초기화)
			
			for(int i=0; i<cLotto.length; i++) {//컴퓨터
				int cNum = r.nextInt(45)+1;
				boolean bool = true;
				for(int j=0; j<cLotto.length; j++) {//컴퓨터 중복체크
					if(cNum == cLotto[j]) {
						bool = false;
						i--;
						break;
					}
				}
				if(bool) {
					cLotto[i] = cNum;
				}
			}
			//컴퓨터 버블정렬
			for(int i=0; i<cLotto.length-1; i++) {
				for(int j=0; j<cLotto.length-1-i; j++) {
					if(cLotto[j] > cLotto[j+1]) {
						int tmp = cLotto[j];
						cLotto[j] = cLotto[j+1];
						cLotto[j+1] = tmp;
					}
				}		
			}		
			//컴퓨터 - 사용자 등수체크
			for(int i=0; i<uLotto.length;i++) {
				for(int j=0; j<cLotto.length;j++) {
					if(uLotto[i] == cLotto[j]) {
						win++;
						break;//내부for문에서 동일값이 나오면 더이상 검사할필요없으니까(중복값검사를했으므로)
						//반복문을 나가준다.
					}
				}
			}
			System.out.println("============ 결과 ============");
			//사용자 출력
			System.out.println("사용자 번호");
			for(int i=0; i<uLotto.length; i++) {
				System.out.print(uLotto[i]+" ");
			}
			System.out.println();
			//컴퓨터 출력
			System.out.println("컴퓨터 번호");
			for(int i=0; i<cLotto.length; i++) {
				System.out.print(cLotto[i]+" ");
			}
			
			System.out.println();
			count++;
			System.out.println("[회차] : "+count+" / [ 맞은 갯수 ] : "+win);
			if(win == 6) {//switch~case문을 이용할경우 반복 시 while(변수)로 해줘야한다.
				System.out.println("1등!");
				break;
			} else if(win == 5) {
				System.out.println("2등!3등!");
			} else if(win == 4) {
				System.out.println("4등!");
			} else if(win == 3 ) {
				System.out.println("5등!");
			}
			else {
				System.out.println("꽝!");
			}
		}
	}

	public void lotto2() {
	//심심해서 한번더해보기
		Scanner sc = new Scanner(System.in);
		Random r = new Random();
		int[] uLotto = new int[6];
		int[] cLotto = new int[6];
		int win = 0; //맞는갯수확인
		
		System.out.println("======== 로또 프로그램 ========");
		for(int i=0; i<uLotto.length; i++) {
			boolean bool = true;
			System.out.print((i+1)+"번째 번호 입력(1~45) : ");
			int uNum = sc.nextInt();
			if(uNum <= 0 || uNum > 45) {
				System.out.println("잘못 입력하셨습니다. 1~45 중 한개를 입력해주세요.");
				i--;
			}else {
				//중복체크
				for(int j=0; j<uLotto.length; j++) {
					if( uNum == uLotto[j] ) {
						bool = false;
						i--;
						System.out.println("이미 중복된 번호입니다. 다시 입력해주세요.");
						break;
					}
				}
				if(bool) {
					uLotto[i] = uNum;
				} 
			}
		}
		//유저로또번호정렬(버블정렬)
		for(int i=0; i<uLotto.length-1; i++) { //uLotto=5 0~3까지만 돌리면 되므로 -1
			for(int j=0; j<uLotto.length-1-i; j++) {
				//j와 j+1을 비교하기때문에 배열.length까지를 범위로 잡으면 배열을 넘어가므로 error
				//거기에 한번돌아가면 마지막부터 배열값이 이미 정렬이되므로 -i를 해주어 불필요한 반복제거 
				if(uLotto[j] > uLotto[j+1]) {//만약 왼쪽(j)인덱스가 오른쪽(j+1)인덱스보다 크면 자리를 바꿔주는 if문				
					int tmp = uLotto[j]; //j번째 인덱스를 j+1번인덱스로 옮겨주기위해 빈변수에 넣어줌.
					uLotto[j] = uLotto[j+1]; //j+1의 값을 j인덱스에 대입(덮어쓰기)
					uLotto[j+1] = tmp; //tmp에 넣은 j인덱스에 있던 값을 j+1인덱스에 덮어쓰기
					//기존 : j(큰수) j+1(작은수) -> 변경 : j(작은수) j+1(큰수)
				}				
			}
		}
		System.out.println("사용자 번호");
		for(int i=0; i<uLotto.length; i++) {
			System.out.print(uLotto[i]+" ");
		} 
		System.out.println();
		//사용자(입력,정렬,중복) 끝
		//컴퓨터시작
		for(int i=0; i<cLotto.length; i++) { //컴퓨터가 랜덤으로 1~45사이의 값을 출력
			int cNum = r.nextInt(45)+1;
			boolean bool = true;
			for(int j=0; j<cLotto.length; j++) {
				if(cNum == cLotto[j]) {
					bool = false;
					i--;
					break;
				}
			}
			if(bool) {
				cLotto[i] = cNum;
			}
		}
		//컴퓨터가 생성한 랜덤값 버블정렬
		for(int i=0; i<cLotto.length-1; i++) {
			for(int j=0; j<cLotto.length-1-i; j++) {
				if(cLotto[j] > cLotto[j+1]) {
					int tmp = cLotto[j];
					cLotto[j] = cLotto[j+1];
					cLotto[j+1] = tmp;
				}
			}
		}
		System.out.println("컴퓨터 번호");
		for(int i=0; i<cLotto.length; i++) {
			System.out.print(cLotto[i]+" ");
		}
		System.out.println();
		
		//컴퓨터 - 유저 비교코드
		for(int i=0; i<uLotto.length; i++) {
			for(int j=0; j<cLotto.length; j++) {
				if(uLotto[i] == cLotto[j]) {
					win++;
				}
			}
		}
		//갯수출력
		System.out.println("맞는 갯수 : "+win);
		if(win==6) {
			System.out.println("1등!!");
		} else if(win==5) {
			System.out.println("2등!");
		} else {
			System.out.println("꽝!");
		}		
	}

 

[ 4. 배열 복사 - 얕은 복사 / 깊은 복사 ] ===================================================

--- 추가, 알아두면 좋은 사항 ---------------------------------------------------------------------------------------------------------------------------

  String str1 = "hi";
  String str2 = sc.next();
  if(str1 == str2){} -> false 
  참조형변수는 그 값이 있는 주소값을 가지고 있기때문에 str1의 값(주소값1)과 str2의 값(주소값1)을 비교하면
  서로 같을 수 없음.(문자열 비교시 . equals를 사용한걸 참고)

---------------------------------------------------------------------------------------------------------------------------------------------------------------

   1) 얕은 복사 : 객체의 주소값만 가져와 참조형변수에 저장하고 하나의 객체를 두 변수가 참조하고 있는것 -서로영향o
   (스택메모리에있는 두 변수가 힙메모리에있는 하나의 객체를 참조)


  2) 깊은 복사 : 다른 객체를 생성하여 새로운 객체에 값만 복사(똑같은형태로 만들어서) - 서로영향x

      2-1) 깊은 복사를 하는 3가지방법 - fo문을 통한 1:1대입 / arraycopy / 배열별명.clone()

/*
  배열복사 
   1.얕은 복사 : 객체의 주소값만 가져와 참조형변수에 저장하고 하나의 객체를 두 변수가 참조하고 있는것 -서로영향o
   (스택메모리에있는 두 변수가 힙메모리에있는 하나의 객체를 참조)
 	String str1 = "hi";
 	String str2 = sc.next();
 	if(str1 == str2){} -> false 
 	참조형변수는 그 값이 있는 주소값을 가지고 있기때문에 str1의 값(주소값1)과 str2의 값(주소값1)을 비교하면
 	서로 같을 수 없음.
 	2.깊은 복사 : 다른 객체를 생성하여 새로운 객체에 값만 복사(똑같은형태로 만들어서) - 서로영향x
 */
	public void arrayCopy() {
		
		int num1 = 10;
		int num2 = num1;
		System.out.println("num1 : "+num1); //10
		System.out.println("num2 : "+num2); //10
		num2 = 1000;
		System.out.println("num1 : "+num1); //10
		System.out.println("num2 : "+num2); //1000
		
		//얕은복사
		System.out.println("=== 얕은 복사 ===");
		int[] arr1 = {1, 2, 3, 4};
		int[] arr2 = arr1;
		for(int i=0; i<arr1.length; i++) {
			System.out.print(arr1[i]+" "); //1 2 3 4
		}
		System.out.println();
		for(int i=0; i<arr2.length; i++) {
			System.out.print(arr2[i]+" "); //1 2 3 4
		}
		System.out.println();
		arr1[2] = 100;
		arr2[3] = 1000;
		
		for(int i=0; i<arr1.length; i++) {
			System.out.print(arr1[i]+" "); //1 2 100 1000
		}
		System.out.println();
		for(int i=0; i<arr2.length; i++) {
			System.out.print(arr2[i]+" "); //1 2 100 1000
		}
		System.out.println();
		//일반형변수와는 달리 참조형변수는 그 객체의 주소값을 가지고 있음
		//arr2에 arr1을 넣으면 주소값이 들어간다. 결과적으로 같은객체를 가리키고있음(실제배열은 한개인것)
		//그러므로 arr1[2]=100 arr2[3]=1000;을 출력했을때 배열1 배열2 둘다 값이 바뀐것
	
		//깊은복사
		System.out.println("=== 깊은 복사 ===");
		int[] arr3 = {5, 6, 7, 8};
		int[] arr4 = new int[arr3.length];//동일한 길이의 신규배열생성
		//깊은복사 1.for문을 통한 1:1값대입
		for(int i=0; i<arr3.length; i++) {//arr4에 arr3값을 복사하는 for문
			arr4[i] = arr3[i]; 
		}
		for(int i=0; i<arr3.length; i++) {
			System.out.print(arr3[i]+" ");
		}
		System.out.println();
		for(int i=0; i<arr4.length; i++) {
			System.out.print(arr4[i]+" ");
		}
		System.out.println();

		arr3[1] = 1000;
		arr4[0] = 0;
		
		for(int i=0; i<arr3.length; i++) {
			System.out.print(arr3[i]+" "); // 5 1000 7 8
		}
		System.out.println();
		for(int i=0; i<arr4.length; i++) {
			System.out.print(arr4[i]+" "); // 0 6 7 8
		}
		//중간에 값을 바꿔줘도 서로 영향을 주지않음 : 깊은복사
		//서로영향을 주는게 얕은복사(원본데이터도함께변경시) / 영향이 가지않는게 깊은복사(원본데이터유지시)
		System.out.println();
	}
	//깊은복사의 3가지방법
	public void arrayCopy2() {
		//1.for문을 통한 1:1값대입(위에서함)
		//2.arraycopy
		int[] arr1 = {1, 2, 3, 4, 5};//원본
		int[] arr2 = new int[10];
		//1 원본데이터가 저장되어있는 배열 
		//2 원본배열 중 복사시작 인덱스번호 
		//3 새 배열(복사값이 들어갈 배열)
		//4 새 배열 중 복사된 데이터가 들어갈 시작 인덱스번호
		//5 복사할 데이터 길이
		System.arraycopy(arr1, 2, arr2, 5, 3);//특정데이터만 복사시 사용
		//arr1의 2번인덱스부터 복사해서 arr2번의 5번인덱스부터 넣겠다. 3개를
		//0000034500
		for(int i=0; i<arr2.length; i++) { 
			System.out.print(arr2[i]+" ");
		}
		System.out.println();
		int[] arr3 = arr1.clone();//전체데이터 복사시 사용
		for(int i=0; i<arr3.length; i++) {
			System.out.print(arr3[i]+" ");
		}
	}

[ 5. 2차원배열 ] ====================================================================

	//2차원배열
	//1차원 배열안에 다른 배열을 넣은것 / 배열은 저장된 값마다 인덱스 번호 두개로 설정 [행][열]
	//3차원은 객체를 이용하고 배열은 2차원까지
	public void test5() {
		//2차원배열은 [][]를 사용
		int[][] arr = new int[2][3]; //2행x3열의 배열
		//실제로는 길이가 3인 배열을 2개 저장하는 배열 
		int k = 1;
		for(int i=0; i<arr.length; i++) {//행은 그냥 length
			for(int j=0; j<arr[i].length; j++) {//열은 따라갔을 때 그 배열의 length
				arr[i][j] = k;
				k++;
			}
		}
		for(int i=0; i<arr.length; i++) {
			for(int j=0; j<arr[i].length; j++) {
				System.out.print(arr[i][j]+" ");
			}
			System.out.println();
		}
	}

[ 후기 ] -------------------------------------------------------------------------------------------------------------------------------------------------------

 

오늘 제일 오래 연습해본 실습문제는 로또프로그램이었다.

처음에 버블정렬을 이해를 다했다고 생각했는데 사실 덜했던건지 조건식을 계속 잘못넣었는데 주석달면서 여러번 코딩해보니 완벽하게 이해할 수 있었다. 슬슬 8일차가 되니 연습문제도 복잡해지고 길어지기 시작했다. 실습문제가 복잡해 질수록 처음보면 이걸 어떻게해야하나...싶어지는데 막상 차근차근 짜다보면 완성되는게 너무신기하고 재미있다.

 

오늘 실수한 부분

1. 중복값검사에서 처음 코드짤 때 for문 로직 실수

2. 버블정렬 조건식에 -1되는이유

3. 로또프로그램 win(컴퓨터랑 맞은갯수)변수 위치를 잘못잡음(반복문 밖에 작성해서 계속 카운트됨)

   변수위치 잘못잡는 실수를 자주한다. 신경써야겠다.

 

 

'국비수업 > JAVA' 카테고리의 다른 글

10일차 : 객체지향프로그래밍  (0) 2022.12.12
9일차 : 메소드(Method)  (0) 2022.12.08
7일차 : Random, 배열  (0) 2022.12.07
6일차 : Break, Continue, Random  (0) 2022.12.06
5일차 : 제어문  (0) 2022.12.06
Comments