💙 들어가며
do while문을 통해 반복, 입력, 검사 등의 흐름을 제어하고,
switch문을 활용해 특정 입력에 대한 결과를 세팅해보자.
✏️ 학습내용 정리
#오목게임 만들기 시작
우리는 이미 while문을 활용하는 방법을 알고 있다.
조건이 참일 경우에 원하는 연산을 반복해서 실행시킬 수 있다.
여기서부터 오목게임을 만들어볼 것이다. (오목게임 대장정의 시작)
반복문을 활용해서 바둑판을 만들고,
x와 y 두 가지의 값을 받아 x나 y가 -1일 때 먼저 break로 나가게 해보자.
🚨조건문을 사용할 때는 먼저 걸러져야 할 경우의 수를 따지자.
while(true){
Scanner scan = new Scanner(System.in);
int ox = -1;
int oy = -1;
//사용자의 이해를 위해 0을 넣어줌
System.out.println("그만두기: -1 0");
System.out.print("(x sp y): ");
ox = scan.nextInt();
if(ox == -1) {
System.out.println("종료");
break;
}★// if ox == -1
oy = scan.nextInt();
// ||을 했을 때는 왜 안되는지 생각해보기
while(!((1<=ox && ox<=10) || (1<=oy && oy<=10))) {
System.out.println("오목 좌표의 범위(-1 or 1~10)를 벗어났습니다.");
//사용자의 이해를 위해 0을 넣어줌
System.out.println("그만두기: -1 0");
System.out.print("(x sp y): ");
ox = scan.nextInt();
oy = scan.nextInt();
//위에서는 -1을 안했기 때문에 여기 안으로 들어왔지만
//여기에서도 -1을 할 수 있다.
//한 번 더 걸러줘야 한다. -1일땐 break!
if(ox == -1) {
System.out.println("종료");
break;
}//★if ox == -1
}//★while 2
//위의 모든 경우가 다 걸러진 뒤에야 바둑판이 실행된다.
for (int i = 0; i < 12; i++) {
for (int j = 0; j < 12; j++)
if (i == 0 && j == 0)
System.out.print("┌");
else if (i == 0 && j == 11)
System.out.print("┐");
else if (i == 11 && j == 0)
System.out.print("└");
else if (i == 11 && j == 11)
System.out.print("┘");
else if(ox==j && oy == i)
System.out.print("○");
else if (j == 0)
System.out.print("├");
else if (j == 11)
System.out.print("┤");
else if (i == 0)
System.out.printf("┬");
else if (i == 11)
System.out.print("┴");
else
System.out.print("┼");
System.out.println();
}//★for i
}//★while 1
⭕ 출력결과:

빈바둑판 하나와 그만 두기 옵션을 다는 데만 해도 굉장히 많은 양의 코드가 나왔다.
그리고 특정 상황일 때 반복되는 연산들이 생겼다.
#do~while
이제 특정 상황에서 반복되는 것들을 do~while을 이용해서 그룹화 하고 검사해보자.
그 전에 이해해야 할 do~while의 중요한 특징이 있다.
do는 해야한다는 뜻이다. 그렇기 때문에,
- do하는 내용이 무조건 while이 2번째, 3번째 돌 때도 똑같이 실행될 때 사용하는 제어문이다.
- 그냥 while과 다르게 do~while은 무조건 do의 내용을 최초 1회 while과 상관없이 실행한다.
- while조건이 참일 경우에 다시 do로 되돌아간다.
- do{실행할 내용} while(실행조건);의 모양을 띈다. while은 끝에 세미콜론(;)으로 끝난다.
그렇다면 위의 코드를 do~while을 사용해서 줄여보자.
⭕ 반복되는 코드를 줄여보자.
System.out.print("(x sp y): ");
ox = scan.nextInt();
while(!((1<=ox && ox<=10) || (1<=oy && oy<=10))) { // ||을 했을 때는 왜 안되는지 생각해보기
System.out.println("오목 좌표의 범위(-1 or 1~10)를 벗어났습니다.");
System.out.println("그만두기: -1");
System.out.print("(x sp y): ");
⭕
문장은 while에서 끝나니까 while에서 ;를 붙인다.
그리고 반드시 do에서 하는 작업들이 2번째 while에도 똑같이 적용될 때 do~while을 쓰는 것
(while이 참일 때 위로 올라가는 것이다.)
그냥 while과 구분해보자.
do{
System.out.print("\t(x sp y > ");
x = scan.nextInt();
if(!(1<x && x>10)
System.out.println("오목 좌표의 범위(-1 or 1~10)를 벗어났습니다.");
} while(!(1<x && x<10));
do~while은 앞으로 같은 조건 하에서 여러 번 내용을 반복시키거나, 값이 맞는지 확인하고 검사시키고 싶을 때 유용하게 사용할 수 있겠다.
#switch
do~while은 반복, 검사였다면 메뉴는 무조건 switch라는 제어구조를 떠올리면 된다.
switch의 최대 특징이자 장점은 if~else if~else처럼 거쳐거쳐 가는 것이 아니라 123 중에 선택한 것으로 바로 가는 것이다. if처럼 조건에 맞는지 하나하나 비교하지 않는다. 입력값을 case별로 나누고 거기서부터 실행한다.
#switch 주의점과 break
그렇기 때문에 switch문에서 입력값 1, 2, 3 중에서 3을 입력하면 (1, 2와 비교되지도 않고) case 3부터 바로 실행된다.
아주 효율적이고 획기적이다.
그런데 3과 달리, 1과 2를 입력할 때는 주의할 점이 있다.
이 또한 흐름이기 때문에 case1 또는 case2만 실행하고 자동으로 끝나는 것이 아니라 1을 입력하면 1부터 1,2,3이 다 실행되고, 2를 입력하면 2,3이 바로 실행된다는 점이다.
때문에 우리는 각 case(블록)마다 실행되고 멈추게 하기 위해 블록 마지막에 break를 써서 나머지 case들이 연달아서 실행되지 않도록 제어할 것이다.
(case에서 break를 사용하면 switch 블럭의 끝으로 이동한다.)
물론, break는 필요에 따라서 사용될수도 안 될수도 있다.
(2, 3번이 같은 내용이라면 굳이 2에 break 안쓰고 3에다 써서 2~3이 이어지도록 할 수 있다.)
#Break Label
break는 반복문 메소드가 여러개 중첩되어 있는 경우에 선언된 곳 1개만 빠져나가는 형식이다.
그런데 케이스별로 종료시키고 싶은 제어문이 다를 수 있겠다.
(만약 여러개의 중첩문 중에 2개를 빠져나가고 싶다거나 하면 어떻게 해야 할까?)
case 1은 switch문만 빠져나오게 하고 싶으나 case 2는 더 상위의 제어문을 빠져나오게 하고 싶을 수 있지 않은가?
이럴 때 우리는 Label을 사용하면 원하는 제어문을 빠져나올 수 있게 break를 제어할 수 있다.
Label을 붙여서 설명해주는 것이다. 이 break는 어디를 빠져나갈 것이라고.
이것은 C언어에서 물려받은 기능인데 그 중에 go to 의 기능을 없애고 (너무 무분별하게 사용되었기 때문에)
label기능 하나만 남겨두었다고 한다.
이렇게 case 5에 Label을 활용하여 break를 사용하면, case 5는 switch문을 건너 뛰어 가장 큰 틀에서 움직이고 있는 while문까지 한 번에 break시킬 수 있게 된다.
🚨 Break Label: OVER의 기능
OVER: while (true) {
do {
System.out.println("┌───────────┐");
System.out.println(" Omok Game ");
System.out.println(" by hjh ");
System.out.println("└───────────┘");
System.out.println("1. 게임시작");
System.out.println("2. 도움말");
System.out.println("3. 저장하기");
System.out.println("4. 불러오기");
System.out.println("5. 종료");
System.out.print(">");
menu = scan.nextInt();
} while (!(0 < menu && menu < 6));
MAIN: switch (menu) {
......
case 5: {
System.out.println("게임을 종료합니다.");
break OVER;
} // case 5
제어문을 제대로 사용할 수 있게 된 기분이다.
#return
여담으로 가급적 사용을 지양하는 return에 대해서도 간단하게 다루겠다.
return은 break와 다르게 메인 함수를 벗어나는 메소드이다. (메인 함수 자체를 벗어나고 강제 종료함)
때문에 break와는 다르게 신중하게 사용할 필요가 있겠다.
💙 마치며
1.
제어문의 핵심은 흐름이다.
내가 짠 코드가 어떤 흐름을 가지고 있는 지를 읽는 안목을 기르자.
switch문을 사용할 때 case마다 break를 쓰면 어디로 빠져나가는 지를 꼭 파악하자.
2.
그리고 오늘 선생님의 말씀:
"종료합니다."라고 출력하는 값이 있을 때에는
"종료했습니다."라는 말을 break로 빠져나온 뒤에 출력될 수 있게 해야한다.
종료한다고 해놓고 중간에 어떤 다른 코드들이 난입될지 모르기 때문에 확실하게 빠져나온 뒤에 출력될 수 있도록 순서를 잘 기억하자.
'JAVA' 카테고리의 다른 글
[뉴렉처 6기] JAVA│버블 정렬과 선택 정렬(230623) (1) | 2023.07.01 |
---|---|
[뉴렉처 6기] JAVA│배열(Array)를 활용한 데이터 편집│최소값, 최대값, 자리바꾸기(230622) (1) | 2023.06.29 |
[뉴렉처 6기] JAVA│메모리(stack, heap)│Garbage Collector│오류와 디버깅(230626) (0) | 2023.06.27 |
[뉴렉처 6기] JAVA│바둑판 찍기 코드 2가지 리뷰 및 바둑돌 놓기(230619) (1) | 2023.06.26 |
[뉴렉처 6기] JAVA│배열(Array)의 뜻과 사용 방법(230621) (1) | 2023.06.22 |