백엔드/JAVA

1주차 수업내용 정리 및 주사위 게임 예제 실습

두개의 문 2023. 4. 28. 21:17
1주차 내용 정리

 

1. 자바는 1995년 썬마이크로시스템즈에서 개발한 (               ) 프로그래밍 언어이다.
2. 자바 언어의 특징은 "한 번 작성하면 어디서든 실행할 수 있다."를 의미하는 WORA("Write Once Run Anywhere)에 있습니다. WORA를 가능하게 하는 자바 실행환경을 무엇이라고 부를까요?
3. 어떤 자바 프로그램을 실행하려고 하면 반드시 (               ) 함수가 존재해야 합니다.
   이 함수의 원형을 작성하세요.
4. 자바 소스 코드는 확장자 (               ) 파일로 저장됩니다. 그리고 실행을 하려면 이 파일을 확장자 (               ) 파일로 변환해야 합니다. 이 과정은 무엇일까요?
5. STS는 (               ) 기반의 스프링 프로젝트 개발팀에서 만든 통합개발환경(IDE)입니다. STS에서 제공하는 기능이 아닌 것은 무엇일까요?
  ① 소스코드 편집
  ② 자바 코드 컴파일
  ③ 소스코드 비교
  ④ 파이썬 코드 실행
6. STS에서는 일반 웹프로그래밍도 가능합니다. 이 기능을 가능하게 하려면 어떻게 해야 할까요? 방법을 이야기 해봅시다. 

 

더보기

1. 객체지향 

2. JRE

3. main / public static void main( String [] args ) { }

4. .java / .class / compile

5. Eclipse / ④ 파이썬 코드 실행  → Eclipse에서 제공하는 기능

6. VSC에 확장 프로그래밍 기능 존재 ( Spring 확장 툴 설치 )

 

▶ JDK ( Java Development Kit ) / JRE ( Java Runtime Environment ) / JVM ( Java Virtual Machine )

일반 애플리케이션과 Java 애플리케이션 비교

- JVM ( 자바 가상 머신 ) : 자바를 실행하기 위한 가상 기계를 의미

  · 일반 애플리케이션 

   ① OS 거쳐서 바로 하드웨어로 전달

   ② OS 종속적 → 다른 OS에서 실행시키기 위해서는 애플리케이션을 그 OS에 맞게 변경해야 함    

  · Java 애플리케이션

   ① JVM을 거친 후, 하드웨어로 전달

      → 즉, JVM이 자바 응용 프로그램으로부터 전달받은 명령을 해당 운영체제가 이해할 수 있도록 변환하여 전달

       ∴ Java 애플리케이션은 OS와 하드웨어에 독립적이므로 다른 OS에서도 실행이 가능 

   ② JVM : OS 종속적 → 해당 OS에서 실행가능한 JVM이 필요

 

  - JDK ( 자바 개발 도구 ) : Java 애플리케이션을 개발하기 위한 키트로, 개발 환경을 지원

    → 다운로드 하면 항상 호환 버전의 JRE가 포함됨,  JRE에는 기본 JVM이 포함됨

 

  - JRE : 자바 실행 환경

    : Java로 만들어진 프로그램을 실행시키는데 필요한 라이브러리들과 각종 API, JVM이 포함됨

    → 개발은 안되고 실행만 됨 

 

 

 


명명 규칙

 

  ▶ package 

   - 서로 관련된 클래스들끼리 그룹 단위로 묶어 놓음

    → 효율적으로 클래스 관리 가능

   - 점(.)으로 패키지와 다른 패키지 포함 가능 

   - 클래스명과 쉽게 구분하기 위해서 보통 소문자 사용

 

  ▶ class

   - 해당 클래스를 파악할 수 있도록 간단하고 명확히 작성

   - 첫 문자를 대문자로 시작, 명사로 작성

   - 단어 2개 이상 포함 시, 파스칼 표기법 이용 : 각 단어의 첫 문자를 대문자로 표현

     ex ) HelloWorld

  

  ▷ 각종 표기법 정리

   ① 카멜 표기법 (camelCase)

   ② 파스칼 표기법 ( PascalCase )  

   ③ 스네이크 표기법 ( snake_case )

 

 

 


주사위 게임 만들기

 

※ 코딩 전, 글로 최대한 자세히 구현하는 습관 들이자

  → 앞으로 MVC 패턴으로 구분해서 문장으로 자세히 구현하는 습관을 들여야 할 거 같다.

강사님
 1. 필요한 배우 : 컴퓨터, 나
 2. 컴퓨터가 생각한 수 | 내가 생각한 수 비교해서
    가장 큰 수를 생각한 사람이 이긴다.
 3. 임의의 수 : 난수 (간단한 Math 클래스 난수를 이용)
 4. 주사위를 던지는 루틴 - 모델
    두 주사위를 비교해서 큰 값을 판정하는 판정 루틴 - 컨트롤러

    승자를 출력하는 출력 루틴 -


1. 컴퓨터와 사용자가 각각 주사위를 던진다.
    컴퓨터가 던진 주사위 수 : comNumber
    사용자가 던진 주사위 수 : userNumber
2. 주사위 수 : 난수로 설정 - Random 클래스 이용
    seed 값 : 1 ~ 6 범위 설정
3. 주사위 수를 서로 비교
* 조건문 이용 
컴퓨터 > 사용자 : 컴퓨터 승
컴퓨터 < 사용자 : 사용자 승
컴퓨터 = 사용자 : 동점


package web.back;

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

public class DiceGame {
	public static void main(String[] args) {
	
		// 경기할 배우들 등장 ( -> 변수 선언 )
		int com; 
		int na;
		
		// 다시 게임을 반복하는 것이지, 게임하는 플레이어(com, na)들이
		// 바뀐 것이 아니므로 변수선언 이후부터 루프를 쓰는 것이 좋다.
		// 난수 발생모듈도 처음 한번만 초기화 하면 계속 쓸 수 있으므로
		// 난수발생모듈 이후부터 반복하면 됨
		
		// Model = 데이터
		// 경기 시작 : 난수 발생
		// 1. Random() 메소드를 이용한 방법
		Random ran = new Random(); 	// 난수 발생 모듈 사용
		// 2. Math.random() 메소드를 이용한 방법 -> 아래 필기 내용 참고
			
		// int endCount = 3; 
		String gamePlay; 	// 계속 게임을 할 것인가 결정하는 변수
		/////////////////while 시작///////////////////
		while( true ) {
		
			// 주사위의 점수를 얻어온다.
		    com = ran.nextInt(6) + 1;	// 1 ~ 6 까지 seed값 설정
			na  = ran.nextInt(6) + 1;
			
			String gameMsg = "";
			// Controller = 경기 판정
			if ( com == na ) {          // 동점일 경우
				gameMsg = 
						"컴퓨터 점수 : " + com + "\n" +
					    "나 점수 : " + na + "\n" +
					    "동점입니다.";
			} else if ( com > na ) {	// 컴퓨터가 이긴 경우
				gameMsg = 
						"컴퓨터 점수 : " + com + "\n" +
					    "나 점수 : " + na + "\n" +
					    "컴퓨터가 이겼습니다.";						
			} else if ( com < na) {		// 컴퓨터가 진 경우(의미파악을 위해 적자)
				gameMsg = 
						"컴퓨터 점수 : " + com + "\n" +
					    "나 점수 : " + na + "\n" +
					    "나님이 이겼습니다.";						
		    }
			
			// 결과 판정 출력
			System.out.println(gameMsg);
			
			// 프로그램을 계속 진행할 것인가 선택
			// 스캐너의 위치는 여기가 좋다.
			Scanner sc = new Scanner(System.in);
			System.out.println("게임을 계속 할까요?( Y / N )");
			gamePlay = sc.nextLine();
		
			// 게임을 끝내기 위한 endCount 1 감소
			// endCount = endCount - 1;
			
			// endCount == 0 이면 주사위 게임 종료
			//if ( endCount == 0 ) {
			//	break;	// 현재 무한루프를 끝내라.
			//}
			
			// gamePlay의 값이 "Y" 또는 "y"이면 계속 게임 실행
			// gamePlay의 값이 "N" 또는 "n"이면 게임 종료
			if ( gamePlay.equals("Y") ||
			     gamePlay.equals("y")) {
				// 게임을 처음부터 계속 하는 경우
				continue;	// 루프의 처음부터 다시 시작
			} else if ( gamePlay.equals("N") ||
			     gamePlay.equals("n")) {
				// 게임을 그만 끝마칠 경우
				break;		// 현재 루프를 끝낸다.
			}
		}	
		/////////////////while 끝///////////////////
		
		System.out.println("### 프로그램 종료 ###");
	}	
}

 

▷ library / package / import문

· library ( 라이브러리 )

  ① 다른 곳에서 만들어 놓은 기능을 의미 → 관련있는 기능끼리 모아 놓은 것 = package

  ② 라이브러리의 종류

     - 표준 라이브러리 : JDK ( 자바 개발 키트 )에서 제공

     - 사용자 정의 라이브러리 : 사용자인 내가 만든 라이브러리

     - 써드파티 ( third-party ) 라이브러리 : 다른 사용자나 회사에서 만든 라이브러리

 

· package : 남이 만들어놓은 모듈을 의미

  ① package 선언 :  package 패키지명 ;

  ② 위치 : 반드시 소스파일에서 주석과 공백을 제외한 첫 번째 문장이어야 함

  ③ 하나의 소스파일에 단 한 번만 선언될 수 있음

      단, 자바에서는 기본적으로 '이름없는 패키지'를 제공 -> 소스파일 작성 시, 패키지 선언하지 않아도 문제 없음

      ※ 앞으로 프로젝트 작성 시, 미리 패키지를 구성하여 클래스들을 효율적으로 관리해야 함.

 

· import문 : 컴파일러에게 소스파일에 사용된 클래스의 패키지에 대한 정보 제공

  - 모든 소스파일에서의 import문의 위치 : package문 다음, class 선언 이전

 

 

▷ 난수 발생시키는 방법

 1. Random() 메소드를 이용한 방법

  ① import문 첫 줄에 표기
     - 직접 입력 : import java.util.Random;  
     - 자동 기능 추가 : 윈도우) ctrl + shift + O 
  ② Random 객체 생성
     Random ran = new Random();
  ③ seed 값 설정 ( seed : 난수를 발생시킬 범위 )
      1 ~ 6 까지 무작위로 int값 반환하려면, ran.nextInt(6) +1 ;

 

 2. Math.random() 메소드를 이용한 방법

  · Math 클래스 : 기본적인 수학계산에 유용한 메서드로 구성

  → Math.random() : 0.0 ~ 1.0 범위 내에서 실수형 값을 반환

  · 1 ~ 6 까지의 난수 발생시키는 과정

  ① 0.0 <=  Math.random()  < 1.0

  ② 형변환 : 실수형 → 정수형

      0 <=  (int) ( Math.random() )  < 1

  ③ 구하고자 하는 개별값의 갯수인 6을 곱하기

      0 <=  (int) ( Math.random() ) * 6  < 6

  ④ 각 변에 1을 더해주기

      0 + 1 <=  (int) ( Math.random() ) * 6 + 1  < 6 + 1

  ⑤  1 <=  (int) ( Math.random() ) * 6 + 1  < 7

 

 

▷ Scanner 클래스

< 어제 배운 내용들 >

Scanner  클래스 : 키보드로부터 데이터를 입력받아 반환
 cf ) Java에서 모든 데이터형을 문자열로 반환되므로
      문자열이 아닌 다른 데이터형으로 값을 반환하고 싶을 때 Scanner 클래스 이용
  - 사용방법
  ① import java.util.Scanner - import문을 첫 줄에 명시
    : Scanner가 java.util 패키지에 있음을 compiler에게 알려주는 역할
      첫 줄에 입력하지 않을 경우, Compile Error ( Scanner cannot be resolved to a type ) 뜸
  ② Scanner sc = new Scanner ();
    : 새로운  Scanner를 생성새 변수 sc를 사용하겠다는 의미
  ③ Scanner sc = new Scanner ( System.in );
    : 컴퓨터의 입력장치( = 표준입력 )으로부터 입력을 받는 기능을 생성시키라는 의미
 
 - sc.next( );
  : 문자열을 입력할 때 처음으로 나오는 화이트스페이스 ( 공백, 탭, 다음줄 ) 이전 문자열까지만 입력받음

  ex ) "안녕하세요 반갑습니다" → "안녕하세요"만 반환
 - sc.nextInt( ); 
   : 입력받은 값을 정수형으로 반환 

 - sc.nextLine() : 문자열을 입력할 때 "\n" 또는 "\r"로 끝나는 문자열까지 반환

  ex ) "안녕하세요 반갑습니다 [엔터]" → "안녕하세요 반갑습니다"

 

 

▷ 이스케이프 시퀀스  \
 : 문자열 안에 숨겨진 기능

\n   커서를 다음 줄 처음으로 ( n : new line ) → System.out.println(); 과 동일한 기능
\r   커서를 현재 줄 처음으로
\t   현재 위치에서 공백문자 4자 또는 8자 추가
\v   커서를 현재 위치에서 수직으로 다음 줄로
\'   현재 문자열 안에서 ' 작은 따옴표 출력
\"   현재 문자열 안에서 " 큰 따옴표 출력
\\   현재 문자열 안에서 \ 역슬래쉬 출력

 

▷ 문자열 비교 equals()

 : 두 문자열을 비교할 때는 비교 연산자 ( == ) 대신 equals() 메소드 사용
  → 비교하는 두 문자열이 같으면 true, 다르면 false 반환

 · Java는 대소문자 구별

   → 대소문자를 구별하지 않고 비교하고 싶을 때는 equalsIgnoreCase() 메소드 사용

 

 

 


반복문

· 반복 횟수를 알고 있을 때 → for문

· 반복 횟수를 알고 있지 않을 때 → while문

 

▶ for문

for ( 초기화 ; 조건식 ; 증감식 ) {
	조건식이 참인 동안 반복될 구문
}

- 순서

  ① 초기화 수행 →  조건식이 참인 동안 ( ② 조건식 → ③ 실행 구문 → ④ 증감식 ) 반복

                            조건식이 거짓일 경우, for문 전체를 빠져나감

- 필요하지 않으면 생략 가능

   for (  ;  ;  ) {          } : 초기화, 조건식, 증감식 모두 생략 

   조건식이 생략된 경우, 참으로 간주 → 무한 반복문

- 증감식 : 반복문을 제어하는 변수의 값을 증가 또는 감소시키는 식 → 다양한 연산자들로 작성 가능

   그 중 전위형과 후위형에 대해 알아두자  

타입 설명 예시
전위형     값이 참조되기 전에 연산 먼저     x = ++i;     i = i + 1 ;
    x = i;
후위형     값이 참조된 후에 연산      x = i++;     x = i;
    i = i + 1 ;  

※ 증감연산자가 수식에 포함되어 있지 않은 경우, 전위형과 후위형 차이 없음

 

▶ while문

while ( 조건식 ) {
	조건식이 참인 동안, 반복될 구문
}

- 순서

 ① 조건식이 참이면 { } 안의 구문 수행 → 다시 조건식으로 

 ② 조건식이 거짓이면 while문 빠져나감

 

▶ for문과 while문 비교

for ( int i = 1 ; i <= 10 ; i++ ){
	System.out.println(i) ;
}
int i=1;
while ( i <= 10) {
	System.out.println(i);
    i++;
}

항상 서로 변환 가능

→ while문보다는 for문이 좀 더 간결함 다만, 초기화나 증감식이 필요 없는 경우에는 while문이 더 적합

 

▶ 반복문 제어 - break / continue

 ① break문

  - 자신이 포함된 가장 가까운 반복문에서 벗어남

 ② continue문

  - 반복문 내에서만 사용 가능 / 반복문 전체를 벗어나지 않고 다음 반복을 계속 수행함

  - for문 : 증감식으로 이동

    while문, do-while문 : 조건식으로 이동

 

 

 


논리연산자 / 논리 부정 연산자

 

▶ 논리연산자

 - 피연산자로 boolean형 값을 결과로 하는 조건식만을 허용

 ① || ( OR ) : 피연산자 중 어느 한 쪽이 true일 때 결과가 true

 ② && ( AND ) : 피연산자 양쪽 모두 true일 때 결과가 true

 

▶ 논리 부정 연산자 !

 - 주로 반복문과 조건문에서 사용

 - true와 false를 반대로 바꿈

    ex ) ! true → false

 

 

형 변환

 

- 형 변환 : 변수 또는 상수의 타입을 다른 타입으로 변환하는 것

 

▶ 자동 형변환 ( 암시적 형변환 )

 -  서로 다른 타입 간의 대입이나 연산 시, 먼저 형변환으로 타입을 일치시켜야 함

 - 값 손실이 없다는 가정 하에 컴파일러가 형변환을 자동으로 해줌 

→ 기존의 값을 최대한 보존할 수 있는 타입으로 자동 형변환됨

byte b = 1000 ;
// byte 타입의 범위 ( -128 ~ 127 )를 벗어난 값의 대입

→ Error ) 'incompatible types : possible lossy conversion from int to byte'

    : 큰 타입에서 작은 타입으로의 형변환은 값 손실이 발생할 수 있다는 의미

 

▶ 수동 형변환 ( 명시적 형변환 )

- 형변환하고자 하는 변수 앞에 변환하고자 하는 타입을 괄호와 함께 입력

   ex ) double d = 85.3 ; 

          int score = ( int ) d;    → int score = 85 ;

          ※ 변수 d의 값은 형변환 후에도 변화 없음

 

∴  형 변환 : 범위가 좁은 타입 → 넓은 타입으로

   byte → short → int → long → float → double

                           

                  char

    화살표 방향으로의 변환 = 자동 형변환

       반대 방향으로의 변환 = 수동 형변환

 

▷ 기본적으로 컴파일러는 정수 리터럴을 int 타입으로 간주

   만약 int형 타입의 허용범위를 초과할 경우, long 타입임을 컴파일러에게 알려야 에러 발생 안함

  → 정수 리터럴 뒤에 소문자 l 또는 대문자 L을 붙임 ( 소문자 l은 숫자 1과 혼동할 수 있으니 대문자로 표기하자 )

  ※ long 타입 변수에 정수 리터럴을 저장할 때, int 타입의 허용범위 이내일 경우 L 생략 가능

 

▷ 기본적으로 컴파일러는 실수 리터럴을 double 타입으로 간주

   실수 리터럴을 float 타입 변수에 저장하면 컴파일 에러 발생

   → 실수 리터럴을 float 타입으로 저장하고 싶다면 리터럴 뒤에 소문자 f나 대문자 F 붙임

  - 정밀도

float 타입 : 소수점 아래 7자리

double 타입 : 소수점 아래 15자리 

→ double 타입의 정밀도가 더 높으므로 더 정확한 데이터의 저장 가능

 

※ 알파벳 소문자 e 또는 대문자 E가 포함되어 있는 숫자 리터럴 : 소수점이 있는 10진수 실수로 인식

5e2 → 5.0 × 10² = 500.0
0.12E-2 → 0.12 × 10¯² = 0.0012

int var = 1e2;        // 컴파일 에러 ) 100.0 실수형

 

 


Q1. 1 ~ 100 까지의 합 구하기

 

package web.back;
public class sumCalc {
	public static void main(String[] args) {
	
		int sum = 0;	
		int i = 1 ;		// 현재 루프를 가르키는 인덱스 변수
		for ( i = 1 ; i <= 100 ; i++ ) {
			sum = sum + i ;
		}
		System.out.println("1+ ... + 100 = " + sum);
	}	
}
1 + ... + 100 = 5050

 

 


Q2. 1 ~ 100 중 홀수의 합 구하기

 

package web.back;
public class OddCalc {
	public static void main(String[] args) {
	
		int sum = 0;
		int i = 1 ; 
		for ( i = 1 ; i <= 100 ; i = i+1 ) {
			// 홀수일 때만 덧셈 할 수 있음
			// 짝수라면 통과 ( continue )
			if ( i % 2 == 0 ) {
				continue;
			} 
			sum = sum + i ;
		}
		System.out.println("1 + 3 + ... 97 + 99 = " + sum);
	}
}
1 + 3 + ... + 97 + 99 = 2500

 - 10 % 3 = 1 : 10을 3으로 나눴을 때의 나머지 값

 

 

 


Q3. printf()를 이용한 출력

 

 - 같은 값이라도 다른 형식으로 출력하고 싶을 때, 지시자 ( specifier )를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력

 - 지시자 : 값을 어떻게 출력할 것인지를 지시해주는 역할

  → % + conversion : %는 형식문자열의 시작을 의미 / conversion은 값의 타입에 따라 d(정수), f(실수), s(문자열)를 입력

 - 형식 : System.out.printf( "출력할 포맷" , 인수, 인수, 인수, ... ) ;

 - println()과 달리 printf()는 출력 후 줄바꿈 하지 않음 → 지시자 '%n ' 이용

변환 설명 변환 설명
%d   정수 10진법 %tY   년 (4자리)
%o   정수 8진법 %ty   년 (2자리)
%x   정수 16진법 %tm   월 
%f   실수형 %td   일
%s, %S   문자열 %tH, %tM, %tS   시, 분, 초

 

ackage web.back;

import java.util.Date;
public class PrintfEx {
	public static void main(String[] args) {
		int i = 100 ;
		System.out.printf("변수 i = %d", i);
		System.out.printf("\n%d * %d = " + (i * i), i, i);
		System.out.println();	// 빈 줄 
		
		String str1 = "가나다";
		String str2 = "abc";
		
		System.out.printf("문자열 : %s", str1);
		System.out.printf("\n두번째 문자열은 %S", str2);	// 대문자로 출력
		System.out.printf("\n세번째 문자열은 %s", str2);	// 소문자로 출력
		System.out.println();
		
		double d = 123.456789;
		double d1 = 1.23;
		double d2 = 33.123;
		double d3 = 3.5;
		double d4 = 123;
		
		System.out.printf("Double = %.3f", d);	
		// 전체 자리수 지정 안 했으므로 앞에 숫자는 다 출력됨 
		// 소수점 이하 4번째 자리에서 반올림
		// System.out.printf("Double = %6.2f", d);	
		
		
		System.out.printf("\n%10.3f\n", d1);	
		System.out.printf("%10.3f\n", d2);	
		System.out.printf("%10.3f\n", d3);	
		System.out.printf("%10.3f\n", d4);	
		// 소수점 앞의 빈자리 : 공백 / 소수점 뒤의 빈자리 : 0으로 채워

		System.out.printf("%010.3f\n", d1);	
		// 전체 자리수 = 10자리 & 빈 자리수는 0으로 채워라
		System.out.printf("%-10.3f\n", d2);		
		// 왼쪽 정렬해라
변수 i = 100
100 * 100 = 10000
문자열 : 가나다
두번째 문자열은 ABC
세번째 문자열은 abc
Double = 123.457
      1.230
   33.123
     3.500
 123.000
000001.230
33.123