오늘의 목표

더보기

✔️ 개인과제 제출

✔️ 알고리즘 


⏱️ 오늘의 일정

9:00 ~ 11:00 - 알고리즘 세션 강의
10:00 ~ 11:00 - 프로그래머스 코테 문제 풀기

11:00 ~ 14:00 - 알고리즘 유튜브 강의 듣기
15:00 ~ 19
:00 - 알고리즘 유튜브 문제 풀기 ( 백준 )

19:00 ~ 21:00 - 캠프 알고리즘 문제 풀기


📜 알고리즘 세션 강의

9:00 ~ 11:00 - 알고리즘 세션 강의

 

알고리즘 세션 강의가 있었다.

오늘 내용은 배열과 리스트에 관한 내용이였다.

 

📜 알고리즘 세션 강의

10:00 ~ 11:00 - 프로그래머스 코테 문제 풀기

 

카드 뭉치

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/159994.%E2%80%85%EC%B9%B4%EB%93%9C%E2%80%85%EB%AD%89%EC%B9%98

 

AlgorithmCodingTest/프로그래머스/1/159994. 카드 뭉치 at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 알고리즘 유튜브 강의 듣기

11:00 ~ 14:00 - 알고리즘 유튜브 강의 듣기

 

https://www.youtube.com/@BaaaaaaaaaaaaaaaaaaaaarkingDog

 

BaaarkingDog

 

www.youtube.com

 

미뤄두었던 알고리즘 강의를 들었다. 2강 까지 들었고 이제 매일, 적어도 1강 씩은 꾸준히 들을 계획!

 

📜 알고리즘 유튜브 문제 풀기 ( 백준 )

15:00 ~ 19:00 - 알고리즘 유튜브 문제 풀기 ( 백준 )

 

위 강의에서 2강까지 수강하고 나서 연습문제가 백준 사이트를 통해 제공되어서 풀었다.

 

📜 캠프 알고리즘 문제 풀기

19:00 ~ 21:00 - 캠프 알고리즘 문제 풀기

 

저번처럼 이번에도 세션을 듣고나서 문제가 제공되었다.

 

문제 1

**오늘, 두산 베어스와 기아 타이거스가 야구 경기를 하고 있습니다. 이제, 두산 베어스의 공격 차례입니다. 현재 주자는 아무도 없지만, 두산 베어스는 계속해서 1루타(안타)를 치기 시작합니다. 안타를 칠 때마다 주자들은 1루씩 진루합니다. 두산 베어스가 기아 타이거스보다 더 높은 점수를 얻으려면 최소 몇 개의 안타를 쳐야 할까요?

참고로, 두산 베어스와 기아 타이거스의 점수는 프로그램 실행 시 임의적으로 사용자가 줄 수 있으며 두산 베어스에게 1루타의 신이 강림이 되어 타석을 설 때마다 무조건 1루타를 치는 것이 확정이라고 가정해주세요.**

야구의 득점 조건:

  • 타자는 홈에서 타석을 시작합니다.
  • 타자는 홈 → 1루 → 2루 → 3루 → 홈으로 들어오는 순간 1점을 획득합니다.

 

 

function solutionOne(doosanScore, kiaScore) {
    let answer = 0;

    if (doosanScore > kiaScore) {
        return answer;
    }
    else {
        let sub = kiaScore - doosanScore;

        answer = 4 + sub;
    }

    return answer;
}

 

문제 2

이진 배열 nums와 정수 k가 주어졌을 때, 최대 k개의 0을 1로 뒤집을 수 있다면 배열에서 연속된 1의 최대 개수를 반환하세요.

 

예시)

[입력]
const nums = [1,1,1,0,0,0,1,1,1,1,0]
const k = 2

[출력]
6

 

예시)

[입력]
const nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1]
const k = 3

[출력]
10

 

좀 억지로 푼거 같긴 하지만.. 

 

function solutionTwo(nums, k) {
    let indexes = [];

    let originalNums = [...nums];
    let originalK = k;

    let i = 0;
    let sums = [];
    let startIndex = 0;

    for (let i = 0; i < nums.length; i++) {
        if (nums[i] == 0) {
            indexes.push(i);

            nums[i] = 1;
            startIndex = i;

            k--;
        }

        if (k == 0) {
            let sum = 0;
            for (let j = 0; j < nums.length; j++) {
                if (nums[j] == 1) {
                    sum += nums[j];
                }
                else {
                    if (sum == 0) {
                        continue;
                    }

                    sums.push(sum);
                    sum = 0;
                }
            }

            if (sum > 0) {
                sums.push(sum);
            }

            nums = [...originalNums];
            k = originalK;
            i = indexes[1] - 1;
            indexes = [];
        }
    }

    return Math.max(...sums);
}

 

🌙 하루를 마치며

주말동안 개인과제를 점검해서 오늘 제출했다. 텍스트 게임을 간만에 만들었는데, 정말 재밌는 시간이였다.

https://github.com/YamSaeng/RoguelikeJavascript

 

GitHub - YamSaeng/RoguelikeJavascript

Contribute to YamSaeng/RoguelikeJavascript development by creating an account on GitHub.

github.com

 

 

 

 

 

 

웹서버

http 또는 https를 통해 웹 브라우저에서 요청하는 html 문서나 오브젝트( 이미지, 파일 등 ) 을 

전송해주는 서비스 프로그램을 말한다.

 

웹서버

 

웹 서버의 주된 기능은 웹 페이지를 클라이언트로 전달하는 것이다.

주로 그림, CSS, 자바스크립트를 포함한 HTML 문서가 클라이언트로 전달된다.

 

웹서버에서 보내준 데이터 즉, 그림이나 텍스트 같은 것을 보기만 하면 되기 때문에

연결을 계속 유지하고 있을 필요가 없다. 

따라서 요청한 데이터를 보내주고 나면 연결을 끊는다. 

 

연결을 유지 할 필요가 없다는 것은 해당 유저를 웹 서버 메모리에 올려두지 않는다는 말과 같다.

그렇기 때문에 사용자의 상태값이 존재하지 않는다. ( = 스테이리스 서버 )

 

그렇다면 유저가 웹에 다시 요청할때 웹서버는 요청한 유저가 그 유저인지 어떻게 판단할까?

이때 등장하는 개념이 쿠키다. 

 

쿠키 : 웹에 접속할 때마다 클라이언트 브라우저에 텍스로 정보를 남겨두는 파일

 

클라이언트가 웹에 요청할때마다 따로 붙이지 않아도 http 헤더 아래에 쿠키가 붙어서 웹 서버로 같이 들어간다.

쿠키에 요청한 유저를 확인할 수 있는 정보를 담아 웹서버로 전달하고,

웹서버에서 해당 내용을 해석해 유저를 확인한다.

 


 

게임서버

인터넷 상에서 여러 플레이어가 같이 게임을 할 수 있게 하기 위한 프로그램을 말한다.

보통 TCP/IP 프로토콜을 이용해 서버를 구축한다.

 

웹서버와는 다르게 유저가 접속을 끊지 않는 이상 연결을 계속 유지해야한다.

연결을 계속 유지해야하는 것은 해당 유저를 게임 서버 메모리에 올려둔다는 말과 같다.

그렇기 때문에 사용자의 상태값이 존재한다. ( = 스테이풀 서버 )

 

연결을 유지하기 때문에 다른 유저들의 행동, 변화를 바로바로 동기화가 가능하다.

또한 빠른 처리 속도로 실시간 온라인 게임이 가능하며,

모든 게임의 로직을 서버가 전담 하므로 핵이 불가능하다.

'CS' 카테고리의 다른 글

[CS] 디스패처( Dispatcher )  (0) 2025.02.11
[CS] 디자인 패턴  (0) 2024.11.11
[CS] IP 주소의 체계, 사설망, 공인망  (0) 2024.10.07
[CS] 랜카드, MAC 주소  (0) 2024.10.02
[CS] 문자 집합과 인코딩  (0) 2024.08.19

개방형 시스템 상호 연결( OSI ) 모델은 표준 프로토콜을 사용해 다양한 통신 시스템이 통신할 수 있도록 국제표준화기구에서 만든 개념 모델이다. 쉽게 말하면 OSI는 상이한 컴퓨터 시스템이 서로 통신할 수 있는 표준을 제공한다.

 

OSI 모델은 컴퓨터 네트워킹의 범용 언어로 볼 수 있다.

이 모델은 통신 시스템을 7개의 추상적 계층으로 나누고, 각 계층은 다음 계층 위에 스택된다.

OSI 7계층

 

OS 모델의 각 계층은 특정 작업을 처리하고 그 위와 아래의 계층과 통신한다.

 

7. 응용 프로그램 계층 ( 애플리케이션 계층 )

응용 프로그램 계층 ( 애플리케이션 계층 )

 

이 계층은 사용자의 데이터와 직접 상호 작용하는 유일한 계층이다.

웹 브라우저 및 이메일 클라와 같은 소프트웨어 앱은 통신을 개시하기 위해 애플리케이션 계층에 의지한다.

다만, 앞서 언급한 앱들은 애플리케이션 계층의 일부가 아니라는 점을 알아야한다.

애플리케이션 계층은 소프트웨어가 사용자에게 의미 있는 데이터를 제공하기 위해 프로토콜과

데이터를 조작하는 역할을 한다는 점을 알고 있어야한다.

 

애플리케이션 계층에는 HTTP, FTP, SMTP, Telnet 등과 같은 프로토콜이 포함된다.


6. 프레젠테이션 계층 ( 표현 계층 )

프레젠테이션 계층 ( 표현 계층 )

 

이 계층은 주로 데이터를 준비하는 역할을 하고, 애플리케이션 계층이 이를 사용할 수 있게 한다.

다시말해, 계층 6은 애플리케이션이 소비할 수 있도록 데이터를 프레젠테이션한다.

프레젠테이션 계층을 데이터의 변환, 암호화, 압축을 담당한다.

 

서로 통신하는 두 개의 통신 장치는 서로 다른 인코딩 방법을 사용할 수 있어서, 계층 6은 수신 장치의 애플리케이션 계층이 이해할 수 잇는 구문으로 수신 데이터를 변환하는 일을 담당한다. 예를 들면, EBCDIC로 인코딩된 문서 파일을 ASCII로 인코딩 된 파일로 바꿔주는 작업 등을 말한다.

 

장치가 암호화된 연결을 통해 통신하는 경우, 계층 6은 최종 송신자에게 암호화를 추가할 뿐만 아니라 최종 수신자에게 암호화를 디코딩하여 암호화되지 않은 읽기 쉬운 데이터로 애플리케이션 계층을 제시할 수 있도록 하는 역할을 한다.

 

마지막으로, 프레젠테이션 계층은 애플리케이션 계층에서 수신한 데이터를 계층 5로 전송하기 전에 압축하는 일도 담당합니다. 전송할 데이터의 양을 최소화함으로써 통신의 속도와 효율을 높이는 데 도움이 된다.


5. 세션 계층 

세션 계층

 

두 기기 사이의 통신을 시작하고 종료하는 일을 담당하는 계층이다. 통신이 시작될 때부터 종료될 때까지의 시간을 세션이라 한다. 세션 계층은 교환되고 있는 모든 데이터를 전송할 수 있도록 충분히 오랫동안 세션을 개방한 다음 리소스를 낭비하지 않기 위해 세션을 즉시 닫을 수 있도록 보장한다.

 

또한 세션 계층은 데이터 전송을 체크포인트와 동기화한다. 예를 들어, 100MB의 파일이 전송되는 경우 세션 계층이 5MB마다 체크포인트를 설정할 수 있다. 52MB가 전송 된 후 연결이 끊어 지거나 충돌이 발생하면 마지막 체크 포인트에서 세션을 재개하는 것이 가능하다. 즉, 50MB의 데이터만 더 전송하면 된다. 체크 포인트가 없으면 전체 전송을 처음부터 다시 시작해야 한다.


4. 전송 계층

전송 계층

 

계층 4는 두 기기 간의 종단 간 통신을 담당한다. 여기에는 세션 계층에서 데이터를 가져와서 계층 3으로 보내기 전에 세그먼트라고하는 조각으로 분할하는 일이 포함된다. 수신 기기의 전송 계층은 세그먼트를 세션 계층이 이용할 수 있는 데이터로 재조립해야 한다.

전송 계층은 또한 흐름 제어 및 오류 제어 기능의 역할을 한다. 흐름 제어는 연결 속도가 빠른 송신자가 연결 속도가 느린 수신자를 압도하지 않도록 최적의 전송 속도를 결정한다. 전송 계층은 수신된 데이터가 완료되었는지 확인하고 수신되지 않은 경우 재전송을 요청하여 최종 수신자에 대해 오류 제어를 수행한다.

 

전송 계층 프로토콜에는 TCP 및 UDP 가 있다.


3. 네트워크 계층

네트워크 계층

 

네트워크 계층은  서로 다른 두 네트워크 간 데이터 전송을 용이하게 하는 역할을 한다. 서로 통신하는 두 장치가 동일한 네트워크에 있는 경우에는 네트워크 계층이 필요하지 않다. 네트워크 계층은 전송 계층의 세그먼트를 송신자의 장치에 패킷이라고 불리는 더 작은 단위로 세분화하여 수신 장치에서 이러한 패킷을 다시 조립한다. 또한, 네트워크 계층은 데이터가 표적에 도달하기 위한 최상의 물리적 경로를 찾는데 이를 라우팅이라 한다.

 

네트워크 계층 프로토콜에는 IP, ICMP 등이 있다.


2. 데이터 연결 계층

데이터 연결 계층

 

데이터 연결 계층은 네트워크 계층과 매우 비슷하지만, 데이터 연결 계층은 동일한 네트워크에 있는 두 개의 장치 간 데이터 전송을 용이하게 한다. 데이터 연결 계층은 네트워크 계층에서 패킷을 가져와서 프레임이라고 불리는 더 작은 조각으로 세분화한다. 네트워크 계층과 마찬가지로 데이터 연결 계층도 인트라 네트워크 통신에서 흐름 제어 및 오류 제어를 담당한다.(전송 계층은 네트워크 간 통신에 대해서만 흐름 제어 및 오류 제어만을 담당함).

 

대표적인 장비로 스위치가 있다.


1. 물리 계층

물리 계층

 

이 계층에는 케이블, 스위치 등 데이터 전송과 관련된 물리적 장비가 포함된다.

주로 전기적, 기계적, 기능적인 특성을 이용해 통신 케이블로 데이터를 전송하게 된다.

이 계층에서는 단지 데이터를 전달만 할뿐 전송하려거나 받으려는 데이터가 무엇인지, 어떤 에러가 있는지

등에는 전혀 신경쓰지 않는다.

이 계층은 또한 1과 0의 문자열인 비트 스트림으로 변환되는 계층이다.

뿐만 아니라 두 장치의 물리적 계층은 신호 규칙에 동의해서 두 장치의 1이 0과 구별될 수 있어야 한다.

 

대표적인 장비로는 통신 케이블, 리피, 허브 등이 있다.

 

참고 : https://www.cloudflare.com/ko-kr/learning/ddos/glossary/open-systems-interconnection-model-osi/

 

 

 

자바스크립트에서 값은 항상 문자열이나 숫자형 같은 특정한 자료형에 속한다.

자바스크립트에는 8가지 기본 자료형이 있다.

 

숫자형

let n = 123;
n = 12.345;

 

숫자형은 정수 및 부동소수점 숫자를 나타낸다.

숫자형과 관련된 연산은 다양한데, 곱셉, 나눗셈, 덧셈, 뺄셈 등이 대표적이다.

숫자형엔 일반적인 숫자 외에 Infinity, -Infinity, NaN 같은 특수 숫자 값이 포함된다.

 

Infinity는 무한대를 나타낸다.

일반적으로 0으로 나누면 무한대를 얻을 수 있다.

console.log( 1 / 0 );
console.log( Infinity );

 

NaN은 계산 중 에러가 발생했다는 것을 나타내주는 값이다.

부정확하거나 정의되지 않은 수학 연산을 사용하면 계산 중 에러가 발생하는데, 이때 NaN이 반환된다.

console.log( "글자" / 2 ); // NaN

 

 

NaN은 웬만해선 바뀌지 않는다. NaN에 어떤 추가 연산을 해도 결국 NaN이 반환된다.


BigInt

자바스크립트에선 내부 표현 방식 때문에 (2^53 - 1)(9007199254740991) 보다 큰 값 또는

-(2^53-1) 보다 작은 정수는 숫자형을 사용해 나타낼 수 없다.

BigInt 형은 길이에 상관없이 정수를 나타낼 수 있다.

BigInt 형 값은 정수 리터럴 끝에 n을 붙이면 만들 수 잇다. 

 

// 끝에 'n'이 붙으면 BigInt형 자료입니다.
let bigInt = 1234567890123456789012345678901234567890n;

문자형

자바스크립트에선 문자열을 따옴표로 묶는다.

let str = "Hello";
let str2 = 'Single quotes are ok too';
let phrase = `can embed another ${str}`;

 

따옴표는 세 종류가 있다.

1. 큰따옴표 : "Hello"

2. 작은따옴표 : 'Hello'

3. 역 따옴표( 백틸, backtick ) : `Hello`

 

큰따옴표와 작은따옴표는 기본적인 값으로, 자바스크립트에서는 이 둘에 차이를 두지 않는다.

역 따옴표로 변수나 표현식을 감싼 후 ${...} 안에 넣어주면, 다음과 같이 원하는 변수나 표현식을 

문자열 중간에 손쉽게 넣을 수 있다.

 

let name = "John";

// 변수를 문자열 중간에 삽입
console.log( `Hello, ${name}!` ); // Hello, John!

// 표현식을 문자열 중간에 삽입
console.log( `the result is ${1 + 2}` ); // the result is 3

Boolean 형

boolean형은 ture와 false 두 가지 값밖에 없는 자료형 이다.

boolean형은 긍정이나 부정을 나타내는 값을 저장할 때 사용한다.

let nameFieldChecked = true; 
let ageFieldChecked = false;

null 값

null 값은 지금까지 소개한 자료형 중 어느 자료형에도 속하지 않는 값이다.

null 값은 오로지 null 값만 포함하는 별도의 자료형이다.

let age = null;

 

 

자바스크립트의 null은 다른 언어에서의 null과는 성격이 다르다.

다른 언어에서는 null을 존재하지 않는 객체에 대한 참조널 포인터를 나타낼 때 사용한다.

하지만 자바스크립트에서 null은 존재하지 않는 값, 비어 있는 값, 알 수 없는 값을 나타내는 데 사용한다.

 

위 예시를 들어 설명하자면 let age = null; 은 나이를 알 수 없거나 그 값이 비어있음을 보여준다. ( 해석의 영역 )


undefined 값

undefined 값도 null 값처럼 자신만의 자료형을 형성한다.

undefined는 값이 할당되지 않은 상태를 나타낼 때 사용한다.

변수는 선언했으나, 값을 할당하지 않았다면 해당 변수에 undefined가 자동으로 할당된다.

let age;

console.log(age); // 'undefined'가 출력됩니다.

 

변수에 undefined를 명시적으로 할당하는 것도 가능하다.

let age = 100;

// 값을 undefined로 바꿉니다.
age = undefined;

console.log(age); // "undefined"

 

하지만 이렇게 undefined를 직접 할당하는 것은 권장되지 않는다.

변수가 비어있거나 알 수 없는 상태라는 걸 나타낼 때는 null을 사용하는 것이 좋다.

undefined는 값이 할당되지 않은 변수의 초기값을 위해 예약어로 남겨두는 편이 낫다.


typeof 연산자

typeof 연산자는 인수의 자료형을 반환한다. 자료형에 따라 처리 방식을 다르게 하고 싶을 경우와

변수의 자료형을 빠르게 알아내고자 할 때 유용하다.

 

typeof 연산자는 두 가지 형태의 문법을 지원한다.

1. 연산자 : typeof x

2. 함수 : typeof(x)

 

typeof undefined // "undefined"

typeof 0 // "number"

typeof 10n // "bigint"

typeof true // "boolean"

typeof "foo" // "string"

typeof Symbol("id") // "symbol"

 

참고 : https://ko.javascript.info/types

 

자료형

 

ko.javascript.info

 

'Javascript' 카테고리의 다른 글

[Javascript] Express.js 프레임 워크  (0) 2024.08.28
[Javascript] Node.js  (0) 2024.08.27
[Javascript] 화살표함수  (0) 2024.08.22
[Javascript] 프로토타입 ( Prototype )  (0) 2024.08.22
[Javascript] Random - 난수 생성하기  (0) 2024.08.21

오늘의 목표

더보기

✔️ 개인과제


⏱️ 오늘의 일정

9:00 ~ 21:00 개인과제


📜 개인과제

9:00 ~ 21:00 개인과제

 

11일에 이어서 개인과제를 진행했다.

game.js 에 몰려있던 클래스들을 각각 분리했다.

 

Logs.js  ( 로그 관리 )

let gInstance = null;

export class CLogs {    
    constructor() {
        if (gInstance) {
            return gInstance;
        }

        this._logs = [];
        gInstance = this;        
    }

    get logs() {
        return this._logs;
    }

    set logs(value) {
        this._logs.push(value);
    }

    printLogs() {
        this._logs.forEach((log) => console.log(log));
    }

    static getInstance() {
        return gInstance;
    }
}

 

Logs는 싱글톤 객체로 게임에 사용하는 모든 로그들을 관리한다.

 

 

Creature.cs ( 생명체 ( 플레이어와 몬스터 부모 ) )

class Creature {
    constructor() {
        this.bonusHP = 30;
        this.bonusRecovoryHP = 0.02;

        this.defenceState = DEFENCE_OFF;
        this.defenceRating = 0.4;

        this.attackPoint = 1;
        this.recovoryHP = 0.2;
        this.name = null;
        this.weapon = null;
        this.inventory = [];

        this.statusEffect = new CStatusEffect(this);
    }

    equipWeapon(weaponType) {
        switch (weaponType) {
            case '1':
                this.weapon = new CMaceWeapon(this);
                break;
            case '2':
                this.weapon = new CSwordWeapon(this);
                break;
            case '3':
                this.weapon = new CTwohandSwordWeapon(this);
                break;
        }
    }

    attack(battleTurn, target) {
        if (this.weapon != null) {
            return this.weapon.WeaponAttack(battleTurn, target);
        }
    }

    defence() {
        this.defenceState = DEFENCE_ON;
    }

    OnDamage(damagePoint) {
        if (this.hp - damagePoint < 0) {
            this.hp = 0;

            return true;
        }
        else {
            this.hp -= damagePoint;

            return false;
        }
    }

    StatusUpdate(stage) {
        this.hp += Math.floor(this.hp * this.recovoryHP) + (rand(1, 3) * stage);
        this.attackPoint += (rand(1, 3) * stage);

        this.recovoryHP += this.bonusRecovoryHP;        

        this.statusEffect.StatusInit();
    }

    Update(battleTurn) {
        let Logs = CLogs.getInstance();

        switch (this.statusEffect.Effect) {
            case STATUS_EFFECT_RESERVE_STUN:
            case STATUS_EFFECT_RESERVE_BLEEDING:
                this.statusEffect.Start(battleTurn);
                break;
            case STATUS_EFFECT_STUN:
            case STATUS_EFFECT_BLEEDING:
                this.statusEffect.Update(battleTurn);
                break;
        }
    }
}

 

Creature에는 StatusUpdate()로 Stage에 따라 랜덤하게 각종 능력치가 상승한다.

EquipWeapon()로 장비를 착용한다.

OnDamage()를 통해 데미지 처리를 한다.

Update()에서는 Creature에 출혈 및 기절 상태이상이 적용된다.

 

Player.cs ( 플레이어 )

export class Player extends Creature {
    constructor() {
        super();

        this.name = "플레이어";
        this.hp = 250;
        this.defensePoint = 0.5;
    }
}

 

플레이어는 선택한 무기로 바로 공격하기 때문에 부모의 attack()을 사용해 상대방을 공격한다.

 

Monster.cs ( 몬스터 )

export class Monster extends Creature {
    constructor() {
        super();

        this.name = "자바스크립트";
        this.hp = 100;
        this.defensePoint = 0.1;
        this.inventory.push(new CMaceWeapon(this));
        this.inventory.push(new CSwordWeapon(this));
        this.inventory.push(new CTwohandSwordWeapon(this));
    }

    attack(battleTurn, target) {
        let Logs = CLogs.getInstance();     

        let weaponChoiceNum = rand(0, 2);

        if (this.inventory.length > 0) {
            if (this.inventory[weaponChoiceNum] != null) {
                this.weapon = this.inventory[weaponChoiceNum];

                Logs.logs = chalk.yellow(`[${battleTurn}] ${this.name}가 ${this.weapon.name}을 장착했습니다.`);

                return this.weapon.WeaponAttack(battleTurn, target);
            }
        }
    }
}

 

몬스터는 attack()을 오버라이딩해서 자신이 소유하고 있는 무기 중 랜덤하게 골라 장착하고 상대방을 공격한다.

 

StausEffect.cs ( 상태이상 )

Update(battleTurn) {
        let Logs = CLogs.getInstance();

        this.EffectCount--;       

        switch (this.Effect) {
            case STATUS_EFFECT_STUN:
                Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 기절!! [${this.EffectCount}] 턴 남음`);                
                break;
            case STATUS_EFFECT_BLEEDING:
                Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 출혈!! 1턴당 [${this.damage}]씩 체력이 감소합니다. [${this.EffectCount}] 턴 남음`);
                this.owner.OnDamage(this.damage);                
                break;
        }              

        if (this.EffectCount == 0) {

            switch (this.Effect) {
                case STATUS_EFFECT_STUN:
                    Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 기절 해제!`);
                    break;
                case STATUS_EFFECT_BLEEDING:
                    Logs.logs = chalk.cyanBright(`[${battleTurn}] [${this.owner.name}] 출혈 해제!`);
                    break;
            }

            this.StatusInit();
        }
    }

 

StatusEffect는 내부적으로 저장하고 있는 Effect의 값에 따라 상태이상을 owner에게 적용한다.

Start()로 상태이상을 적용하고, Update()를 통해 상태이상을 지속시킨다.

 

Weapon.js ( 무기 )

 WeaponAttack(battleTurn, target) {
     let Logs = CLogs.getInstance();

     if (this.owner.statusEffect.Effect == STATUS_EFFECT_STUN) {
         Logs.logs = chalk.cyanBright(`${this.owner.name}가 기절 상태이상에 걸려 공격할 수 없습니다.`);
         return false;
     }

     if (RatingSuccess(this.attackRating)) {
         if (target.defenceState == DEFENCE_ON) {
             target.defenceState = DEFENCE_OFF;

             if (RatingSuccess(target.defenceRating)) { // 상대방의 방어 확률에 따라 방어                                        
                 Logs.logs = chalk.yellow(`[${battleTurn}] ${target.name}가 ${this.owner.name}의 공격을 방어했습니다.`);

                 return false;
             }
             else {
                 Logs.logs = chalk.yellow(`[${battleTurn}] ${target.name}가 ${this.owner.name}의 공격을 방어하지 못했습니다.`);
             }
         }

         let damagePoint = rand(this.minAttackPoint + this.owner.attackPoint, this.maxAttackPoint + this.owner.attackPoint);
         let finalDamagePoint = Math.floor(damagePoint - damagePoint * target.defensePoint);

         if (target.statusEffect.Effect == STATUS_EFFECT_NONE) {
             if (RatingSuccess(this.statusEffectRating)) {
                 if (target.statusEffect != null) {
                     // 상태이상 적용
                     switch (this.weaponType) {
                         case WEAPON_MACE:
                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 기절 상태이상 적용.`);

                             target.statusEffect.Effect = STATUS_EFFECT_RESERVE_STUN;
                             break;
                         case WEAPON_SWORD:
                             target.OnDamage(finalDamagePoint)

                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 연속 공격!!`);
                             Logs.logs = chalk.green(`[${battleTurn}] ${this.owner.name} 공격 성공! ${this.owner.name}가 ${target.name}에게 ${finalDamagePoint} 의 피해를 입혔습니다.`);                                
                             break;
                         case WEAPON_TWO_HAND_SWORD:
                             Logs.logs = chalk.magenta(`[${battleTurn}] ${target.name}에게 출혈 상태이상 적용.`);

                             target.statusEffect.Effect = STATUS_EFFECT_RESERVE_BLEEDING;
                             target.statusEffect.damage = this.owner.attackPoint;
                             break;
                     }
                 }
             }
         }

         Logs.logs = chalk.green(`[${battleTurn}] ${this.owner.name} 공격 성공! ${this.owner.name}가 ${target.name}에게 ${finalDamagePoint} 의 피해를 입혔습니다.`);

         return target.OnDamage(finalDamagePoint);
     }
     else {
         Logs.logs = chalk.red(`[${battleTurn}] ${this.owner.name}의 공격이 빗나갔습니다.`);

         return false;
     }
 }

 

Weapon 클래스에서는 WeaponAttack() 메서드를 이용해 상대방을 공격하고,

무기 종류에 따라 상대방에게 상태이상을 적용한다.

 

🌙 하루를 마치며

캠프에서 제시한 기본과 도전은 모두 구현을 완료했다.

내일 한번 더 테스트 해서 버그가 없는지 확인하고, 제출한 뒤 캠프에서 제공한 Node.js 강의 수업을 들어야겠다.

오늘의 목표

더보기

✔️ 스탠다드 반 강의 OT

✔️ 프로그래머스 알고리즘 문제 풀이

✔️ 자바스크립트 강의 정리

❌ 개인 과제 진행


⏱️ 오늘의 일정

9:00 ~ 10:00 - 프로그래머스 알고리즘 문제 풀이
10:00 ~ 11:00 - 스탠다드 반 강의 OT

13:00 ~ 20:00 - 자바스크립트 강의 정리


📜 프로그래머스 알고리즘 문제 풀이

9:00 ~ 10:00 - 프로그래머스 알고리즘 문제 풀이

 

명예의 전당

https://github.com/YamSaeng/AlgorithmCodingTest/tree/main/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4/1/138477.%E2%80%85%EB%AA%85%EC%98%88%EC%9D%98%E2%80%85%EC%A0%84%EB%8B%B9%E2%80%85%EF%BC%881%EF%BC%89

 

AlgorithmCodingTest/프로그래머스/1/138477. 명예의 전당 (1) at main · YamSaeng/AlgorithmCodingTest

This is an auto push repository for Baekjoon Online Judge created with [BaekjoonHub](https://github.com/BaekjoonHub/BaekjoonHub). - YamSaeng/AlgorithmCodingTest

github.com

 

📜 스탠다드 반 강의 OT

10:00 ~ 11:00 - 스탠다드 반 강의 OT

 

스탠다드 반 강의 OT 세션에 참여했다.

스탠다드 반은 CS 지식과 네트워크 지식을 강의하는 수업으로 매주 화, 목 10시에 시작한다고 공지를 받았다.

발제자 3명이 해당 주차의 주제를 각각 조사해오고 직접 발표를 한 뒤, 튜터님의 강의가 이어지는 방식으로 진행된다.

발제자 3명은 랜덤하게 돌려서 뽑는 방식이라고 하고, 발제자가 아니더라도 다른 사람들도 내용을 조사해 블로그에 게시한 후 링크를 전달해야 한다고 설명받았다.

 

📜 자바스크립트 강의 정리

13:00 ~ 20:00 - 자바스크립트 강의 정리

 

강의 시간에 배웠던 자바스크립트 강의와 수업 내용은 아니지만 필요한 내용도 함께 정리했다.

 

2024.08.22 - [Javascript/배열 ( Array )] - [Javascript] Array - 최대값, 최소값

 

[Javascript] Array - 최대값, 최소값

Array ( 배열 ) 에서 최대값과 최소값을 구하는 방법을 알아보자. Math.max(), Math.min() let maxValue = Math.max(1, 2, 3, 4, 5);let minValue = Math.min(1, 2, 3, 4, 5);console.log(maxValue); // 5console.log(minValue); // 1 Math.max()

program-yam.tistory.com

 

2024.08.22 - [Javascript/클래스( class )] - [Javascript] class

 

[Javascript] class

클래스는 객체를 생성하기 위한 템플릿으로 생각하면 된다.클래스를 생성하기 위해서는 class 키워드를 사용한다.기본 문법class MyClass { // 여러 메서드를 정의할 수 있음 constructor() { ... } method1() {

program-yam.tistory.com

 

2024.08.22 - [Javascript] - [Javascript] 프로토타입 ( Prototype )

 

[Javascript] 프로토타입 ( Prototype )

prototype 프로퍼티는 자바스크립트 내부에서 광범위하게 사용된다.모든 내장 생성자 함수에서 prototype 프로퍼티를 사용한다.Object.prototype빈 객체를 생성해보자.let obj = {};alert( obj ); // "[object Object]"

program-yam.tistory.com

 

2024.08.22 - [Javascript] - [Javascript] 화살표함수

 

[Javascript] 화살표함수

함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법이 있다. 바로 화살표 함수를 말하는데, 화살표 함수라는 이름은 문법의 생김새를 차용해 지어졌다.let func = (arg1, arg2, ...arg

program-yam.tistory.com

 

🌙 하루를 마치며

개인 과제도 진행을 해야하는데, 두통이 너무 심해 중간중간 약을 먹고 누워 있어서 진행을 하지 못했다.

한 2일간 계속 두통이 이어지는데 이유를 모르겠다..

 

앞서 언급했던 Node.js 강의 입문과 숙련이 모든 수강생한테 지급되었다. 

애초에 목표했던 대로 이번주 안에 과제를 제출하고 주말에 Node.js 강의를 수강하도록 해야겠다.

함수 표현식보다 단순하고 간결한 문법으로 함수를 만들 수 있는 방법이 있다.

 

바로 화살표 함수를 말하는데, 화살표 함수라는 이름은 문법의 생김새를 차용해 지어졌다.

let func = (arg1, arg2, ...argN) => expression

 

위처럼 코드를 작성하면 인자 arg1..argN을 받는 함수 func가 만들어지고,

함수 func는 화살표 우측의 표현식을 평가하고, 평가 결과를 반환한다.

 

let sum = (a, b) => a + b;

/* 
위 화살표 함수는 아래 함수의 축약 버전이다.
let sum = function(a, b) {
  return a + b;
};
*/

console.log( sum(1, 2) ); // 3

 

위처럼 ( a, b ) => a + b는 인수 a와 b를 받는 함수다.

( a, b ) => a + b 는 실행되는 순간 표현식 a + b를 평가하고 그 결과를 반환한다.

 

※ 인수가 하나밖에 없으면 인수를 감싸는 괄호를 생략할 수 있다

let double = n => n * 2;
// let double = function(n) { return n * 2 }과 동일하다.

console.log( double(3) ); // 6

 

 

※ 인수가 하나도 없을 경우 괄호를 비워놓으면 된다. 다만, 이 때 괄호는 생략할 수 없다.

let sayHi = () => console.log("안녕하세요!");

sayHi();

 

 

화살표 함수는 함수 표현식과 같은 방법으로 사용할 수 있다.

let age = prompt("나이를 알려주세요.", 18);

let welcome = (age < 18) ?
  () => console.log('안녕') :
  () => console.log("안녕하세요!");

welcome();

 

위처럼 함수를 동적으로 만들 수도 있다.

'Javascript' 카테고리의 다른 글

[Javascript] Node.js  (0) 2024.08.27
[Javascript] 자료형  (0) 2024.08.24
[Javascript] 프로토타입 ( Prototype )  (0) 2024.08.22
[Javascript] Random - 난수 생성하기  (0) 2024.08.21
[Javascript] Map  (0) 2024.08.19

prototype 프로퍼티는 자바스크립트 내부에서 광범위하게 사용된다.

모든 내장 생성자 함수에서 prototype 프로퍼티를 사용한다.


Object.prototype

빈 객체를 생성해보자.

let obj = {};
alert( obj ); // "[object Object]" ?

 

"[Object Object]" 문자열을 생성하는 코드는 어디에 있는걸까?

obj는 비어 있는데 말이다.

obj = new Object()를 줄이면 obj = {} 가 된다.

여기서 Object는 내장 객체 생성자 함수인데, 이 생성자 함수의 prototype은 toString을 비롯한 다양한 메서드가 구현되어 있는 거대한 객체를 참조한다.

Object의 prototype이 Object.prototype을 참조하는 그림

 

 

new Object()를 호출하면 새롭게 생성된 객체의 Prototype 은 Object.prototype을 참조한다.

new Object()를 사용해 생성된 객체의 Prototype이 Object.prototype을 참조하는 그림

 

 

따라서 obj.toString()을 호출하면 Object.prototype에서 해당 메서드를 가져오게 된다.

예시를 통해 확인해 보자.

let obj = {};

console.log(obj.__proto__ === Object.prototype); // true

console.log(obj.toString === obj.__proto__.toString); //true
console.log(obj.toString === Object.prototype.toString); //true

 

다양한 내장 객체의 프로토타입

Array, Date, Function을 비롯한 내장 객체들 역시 프로토타입에 메서드를 저장해 놓는다.

배열 [1, 2, 3]을 만들면 new Array() 의 디폴트 생성자가 내부에서 동작하여 Array.prototype이 배열 [1, 2, 3]의 프로토타입이 되고 개발자는 Array.prototype을 통해 배열 메서드를 사용할 수 있다.

 

명세서에선 모든 내장 프로토타입의 상속 트리 꼭대기엔 Object.prototype이 있어야 한다고 규정한다.

세 내장 객체를 이용해 지금까지 설명한 내용을 그려보면 다음과 같다.

 

 

이번엔 코드로 각 내장 객체의 프로토타입을 직접 확인해 보자.

let arr = [1, 2, 3];

// arr은 Array.prototype을 상속받았나요?
console.log( arr.__proto__ === Array.prototype ); // true

// arr은 Object.prototype을 상속받았나요?
console.log( arr.__proto__.__proto__ === Object.prototype ); // true

// 체인 맨 위엔 null이 있습니다.
console.log( arr.__proto__.__proto__.__proto__ ); // null

 

 

체인 상의 프로토타입엔 중복 메서드가 있을 수 있다.

Array.prototype엔 요소 사이에 쉼표를 넣어 요소 전체를 합친 문자열을 반환하는 자체 메서드 toString이 있다.

let arr = [1, 2, 3]
console.log(arr); // 1,2,3 <-- Array.prototype.toString의 결과

 

 

그런데 Object.prototype에도 메서드 toString이 있다. 이렇게 중복 메서드가 있을 때는 체인 상에서 가까운 곳에 있는 메서드가 사용된다. Array.prototype 이 체인 상에서 더 가깝기 때문에 예시에서는 Array.prototype의 toString이 사용된다.

 

 

Chrome 개발자 콘솔과 같은 도구를 사용해 console.dir를 사용하면 내장 객체의 상속 관계를 확인할 수 있다.

 

 

배열이 아닌 다른 내장 객체들 또한 같은 방법으로 동작한다. 

함수도 마찬가지며 call, apply를 비롯한 함수에서 사용할 수 있는 메서드는 Function.prototype에서 받아온다.

function f() {}

console.log(f.__proto__ == Function.prototype); // true
console.log(f.__proto__.__proto__ == Object.prototype); // true, 객체에서 상속받음

 

'Javascript' 카테고리의 다른 글

[Javascript] 자료형  (0) 2024.08.24
[Javascript] 화살표함수  (0) 2024.08.22
[Javascript] Random - 난수 생성하기  (0) 2024.08.21
[Javascript] Map  (0) 2024.08.19
[Javascript] 소수 올림, 내림, 반올림  (0) 2024.08.19

클래스는 객체를 생성하기 위한 템플릿으로 생각하면 된다.

클래스를 생성하기 위해서는 class 키워드를 사용한다.


기본 문법

class MyClass {
  // 여러 메서드를 정의할 수 있음
  constructor() { ... }
  method1() { ... }
  method2() { ... }
  method3() { ... }
  ...
}

 

위처럼 클래스를 만들고 new Myclass()를 호출하면 객체가 생성된다.

 

constructor()는 생성자로 new에 의해 자동으로 호출되고, 객체의 기본 상태를 설정해준다.

 

class User {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    console.log("안녕하세요");
  }
}

// 사용법:
let user = new User("Yam");
user.sayHi();

 

위처럼 new User("Yam")를 호출하면, 새로운 객체가 생성되고,

넘겨받은 매개변수와 함께 constructor가 자동으로 실행된다.

 

자바스크립트에서 클래스는 함수의 한 종류로 취급한다.

class User {
  constructor(name) { this.name = name; }
  sayHi() { console.log(this.name); }
}

// User가 함수라는 증거
console.log(typeof User); // function

 

class User 문법 구조가 하는일은 다음과 같다.

1. User라는 이름을 가진 함수를 만들고, 함수 본문은 constructor에서 가져온다.

    constructor가 없으면 본문이 비워진 채로 함수가 만들어진다.

2. sayHi와 같은 메서드를 User.prototype에 저장한다.

 

new User를 호출해 객체를 만들고, 객체의 메서드를 호출하면 메서드를 prototype 프로퍼티를 통해 가져온다.

이 과정이 있어서 객체에서 메서드에 접근할 수 있다.

 

class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

// 클래스는 함수다.
console.log(typeof User); // function

// 정확히는 생성자 메서드와 동일하다.
console.log(User === User.prototype.constructor); // true

// 클래스 내부에서 정의한 메서드는 User.prototype에 저장된다.
console.log(User.prototype.sayHi); // console.log(this.name);

// 현재 프로토타입에는 메서드가 두 개다.
console.log(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

 

 

class라는 키워드 없이도 클래스 역할을 하는 함수를 선언할 수 있다.

 

// class User와 동일한 기능을 하는 순수 함수를 만들어보자.

// 1. 생성자 함수를 만든다.
function User(name) {
  this.name = name;
}

// 모든 함수의 프로토타입은 'constructor' 프로퍼티를 기본으로 갖고 있기 때문에
// constructor 프로퍼티를 명시적으로 만들 필요가 없다.

// 2. prototype에 메서드를 추가한다.
User.prototype.sayHi = function() {
  console.log(this.name);
};

// 사용법:
let user = new User("John");
user.sayHi();

 

위 처럼 순수 함수로 클래스 역할을 하는 함수를 선언하는 방법과 class 키워드를 사용하는 방법의 결과는 거의 같다.

 

이 두 방법에는 중요한 차이가 몇가지 있다.

1. class로 만든 함수엔 특수 내부 프로퍼티인 IsClassConstructor : true 가 이름표처럼 붙는다.

    이것만으로도 두 방법엔 분명한 차이가 있음을 알 수 있다.

 

class User {
  constructor() {}
}

console.log(typeof User); // User의 타입은 함수이긴 하지만 그냥 호출할 수 없다
User(); // TypeError: Class constructor User cannot be invoked without 'new'

 

자바스크립트는 다양한 경우 IsClassConstructor : true를 활용한다.

클래스 생성자를 new와 함께 호출하지 않으면 에러가 발생하는데 이 때 IsClassConstructor : true 가 사용된다.

 

또 다른 차이점으로는

2. 클래스에 정의된 메서드는 열거할 수 없다.

    클래스의 prototype 프로퍼티에 추가된 메서드의 enumerable 플래그는 false 이기 때문.

    for in 으로 객체를 순회할 때, 메서드는 순회 대상에서 제외하고자 하는 경우가 많아 이 특징은 꽤 유용하다.

 

3. 클래스는 항상 엄격 모드로 실행된다. 클래스 생성자 안 코드 전체에 자동으로 엄격 모드가 적용된다.


클래스 표현식

함수처럼 클래스도 다른 표현식 내부에서 정의, 전달, 반환, 할당할 수 있다.

 

클래스 표현식을 만들어보자.

let User = class {
  sayHi() {
    console.log("안녕하세요.");
  }
};

 

 

기명 함수 표현식과 유사하게 클래스 표현식에도 이름을 붙일 수 있다.

클래스 표현식에 이름을 붙이면, 이 이름은 오직 클래스 내부에서만 사용할 수 있다.

// 기명 클래스 표현식(Named Class Expression)
// (명세서엔 없는 용어이지만, 기명 함수 표현식과 유사하게 동작한다.)
let User = class MyClass {
  sayHi() {
    console.log(MyClass); // MyClass라는 이름은 오직 클래스 안에서만 사용할 수 있다.
  }
};

new User().sayHi(); // 원하는대로 MyClass의 정의를 보여준다.

console.log(MyClass); // ReferenceError: MyClass is not defined, MyClass는 클래스 밖에서 사용할 수 없다.

getter와 setter

클래스는 getter와 setter를 지원한다.

get과 set을 이용해 user.name을 조작해보자!

class User {

  constructor(name) {
    // setter를 활성화합니다.
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      console.log("이름이 너무 짧습니다.");
      return;
    }
    this._name = value;
  }

}

let user = new User("성원");
console.log(user.name); // 성원

user = new User(""); // 이름이 너무 짧습니다.

 

참고로 getter와 setter는 User.prototype에 정의된다.


클래스 필드

클래스 필드라는 문법을 사용하면 어떤 종류의 프로퍼티도 클래스에 추가할 수 있다.

클래스 User에 name 프로퍼티를 추가해보자.

class User {
  name = "성원";

  sayHi() {
    console.log(`${this.name}님 안녕하세요!`);
  }
}

new User().sayHi(); // 성원님 안녕하세요!

 

 

클래스를 정의할 때 <프로퍼티 이름> = <값> 을 써주면 간단히 클래스 필드를 만들 수 있다.

클래스 필드의 중요한 특징 중 하나는 User.prototype이 아닌 개별 객체에만 클래스 필드가 설정된다는 점이다.

class User {
  name = "성원";
}

let user = new User();
console.log(user.name); // 성원
console.log(User.prototype.name); // undefined

 

 

 

 

참고 : https://ko.javascript.info/class

 

클래스와 기본 문법

 

ko.javascript.info

 

Array ( 배열 ) 에서 최대값과 최소값을 구하는 방법을 알아보자.

 

Math.max(), Math.min() 

let maxValue = Math.max(1, 2, 3, 4, 5);
let minValue = Math.min(1, 2, 3, 4, 5);

console.log(maxValue); // 5
console.log(minValue); // 1

 

Math.max() 함수는 입력받은 수 중 최대값을 구해서 반환해주는 함수다.

Math.min() 함수는 입력받은 수 중 최소값을 구해서 반환해주는 함수다.

 

위 함수들을 사용해 배열의 최대값과 최소값을 구하기 위해서는 

배열의 내용들을 꺼내 함수로 전달해주는 작업이 필요하다.

 

Spread Operator( 전개 연산자 )를 이용하면 배열의 내용들을 꺼내 함수로 전달할 수 있다.

let arr = [1, 2, 3, 4, 5];
let maxValue = Math.max(...arr);
let minValue = Math.min(...arr);

console.log(maxValue); // 5
console.log(minValue); // 1

 

 

 

+ Recent posts