라라리라

2023.08.25 / Step 10 [클래스] - 코딩 37 일차 본문

코딩/2023 JavaScript Console

2023.08.25 / Step 10 [클래스] - 코딩 37 일차

헤실 2023. 8. 25. 23:59

클래스3_개념01_상속.html

 

<script>

    /*
        [상속]
            [1] 개념
                서로 다른 클래스 두개는 상속이라는 키워드를 통해
                부모 자식 관계를 형성할 수 있다.
                이는 게임으로 설명하면 이해하기 쉽다.

                플레이어 라는 클래스가 있고,
                몬스터 늑대, 박쥐, 호랑이가 있다고 했을 때

                플레이어와 몬스터 늑대 박쥐 호랑이는 각각 특성이 다르지만,
                체력, 공격력, 방어력, 레벨, 등등의 공통 데이터가 존재한다.
                또한 게임이기 때문에 공격하기, 공격 당하기, 사망 등의 기능도
                공통이다.
               
                각 클래스마다 중복되는 데이터와 기능은  
                상속으로 처리하면 코드가 간결해진다.
               
            [2] 상속하는방법
                자식 클래스 extends 부모클래스명 {}
                [예시]
                    class Player extends Unit{}    
    */

    class unit {
        name = "";
        level = 0;
        health = 0;
        power = 0;
        status = "play";

        setdata (a, b, c, d){
            this.name = a;
            this.level = b;
            this.health = c;
            this.power = d;
        }
        constructor (a, b, c, d){
            this.name = a;
            this.level = b;
            this.health = c;
            this.power = d;
        }
        printdata(){
            document.write(`이름 = ${this.name}<br>
            레벨 = ${this.level}<br>
            체력 = ${this.health}<br>
            공격력 = ${this.power}<br>`);
        }
    }
    class player extends unit{}
    class wolfs extends unit{}
    class bats extends unit{}
    class dragon extends unit{}

    let Player = new player("용사", 50, 100, 10);
    let Dragon = new dragon("드래곤", 100, 1000, 99);
   

    Player.printdata();
    document.write("<br>");
    Dragon.printdata();

</script>

 

 


클래스3_개념02_상속응용.html

 

<script>

    class Unit {
        name = "";
        level = 0;
        health = 0;
        power = 0;
        status = "play";

        constructor (name, level, health, power){
            this.name = name;
            this.level = level;
            this.health = health;
            this.power = power;
        }
        printdata(){
            document.write(`이름 : ${this.name} 레벨 : ${this.level} 체력 : ${this.health} 파워 : ${this.power}<br>`);
        }
        attack(enemy){
            enemy.health -= this.power;
            document.write(this.name + "이(가) " + enemy.name + "에게 " + this.power + " 만큼의 피해를 줍니다.<br>");
        }
        checkDead(){
            let check = false;
            if(this.health <= 0){
                this.health = 0;
                check = true;
                this.status = "dead"
            }
            return check;
        }
    }
    class Player extends Unit {
        skill1(){
            this.health += 10;
            if(this.health >= 50){
                this.health = 50;
            }
            document.write(`회복마법 = 10의 체력을 회복합니다<br>`)
        }
        skill2(monsterList){
            document.write("필살기 = 전체를 공격합니다!!<br>")
            for(let i = 0; i < monsterList.length; i++){
                this.attack(monsterList[i]);
            }
        }
    }
    class Wolfs extends Unit {};
    class Bats extends Unit {};
    class Tigers extends Unit {};

    class RpgGame {
        player = new Player("용사", 4, 50, 10);
        enemyList = [];

        Gamesetting(){
            for(let i = 0; i < 3; i++){
                let r = Math.floor(Math.random() * 3);
                if(r == 0){
                    let wolf = new Wolfs("늑대", 1, 15, 2);
                    this.enemyList.push(wolf);
                }
                else if(r == 1){
                    let bat = new Bats("박쥐", 2, 20, 3);
                    this.enemyList.push(bat);
                }
                else if(r == 2){
                    let tiger = new Tigers("호랑이", 4, 30, 4);
                    this.enemyList.push(tiger);
                }
            }
            this.gameinfo();
        }
       

        gameinfo(){
            document.write(`======== [유닛 정보 시작] ========<br>`);
            this.player.printdata();
            for(let i = 0; i < this.enemyList.length; i++){
                this.enemyList[i].printdata();
            }
            document.write(`======== [유닛 정보 종료] ========<br>`);
            document.write("<br>");
        }
        checkenemyDead(){
            for(let i = 0; i < this.enemyList.length; i++){
                if(this.enemyList[i].checkDead()){
                    document.write(`${this.enemyList[i].name}이(가) 사망하였습니다.<br>`);
                    this.enemyList.splice(i, 1);
                    i--;
                }
            }
        }
        playerturn(){
            let index = Math.floor(Math.random() * this.enemyList.length);
            let enemy = this.enemyList[index];
            let r = Math.floor(Math.random() * 3);
            if(r == 0){
                this.player.attack(enemy);
            } else if(r == 1){
                this.player.skill1();
            } else if(r == 2){
                this.player.skill2(this.enemyList);
            }
            this.checkenemyDead();
            if(this.enemyList.length == 0){
                return true;
            } else return false;
           
        }
        enemyturn(){
            for(let i = 0; i < this.enemyList.length; i++){
                this.enemyList[i].attack(this.player);
            }
            if(this.player.checkDead()){
                return true;
            } else return false;
           
        }
        Gameplay(){
            let count = 1;
            while(true){
                document.write(`=========[ ${count}턴 시작 ]=========<br>`);
                if(count % 2 == 1){
                    if(this.playerturn()){
                        document.write("게임 승리 !! <br>");
                        break;
                    }
                } else {
                    if(this.enemyturn()){
                    document.write("game over<br>");
                    break;
                }
                }
                document.write(`=========[ ${count}턴 종료 ]=========<br>`);
                document.write("<br>");
                this.gameinfo();
                count++;
            }
        }
    }

    //--------------------------------------------------------------
    let c = new RpgGame();
    c.Gamesetting();
    c.Gameplay();
   
</script>

 

 


클래스3_개념03_생성자.html

 

<script>

    /*
        보통 클래스는 setData 메서드와 같은
        초기값을 설정해주는 기능이 필요하다.

        초기값 설정을 위해 한번에 처리할 수 있도록
        생성자 함수를 기본으로 제공하고 있다.
    */

    class Unit {
        health = 0;
        power = 0;
        level = 0;
        name = "";

        /*
        setData(health, power, level, name) {
            this.health = health;
            this.power = power;
            this.level = level;
            this.name = name;
        }
        */

        // 생성자 함수(=메서드)
        constructor(health, power, level, name) {
            this.health = health;
            this.power = power;
            this.level = level;
            this.name = name;
        }
    }

    // new와 동시에 호출할 수 있다.
    let player = new Unit(50, 10, 1, "용사");      

</script>

 

 


클래스3_개념04_static변수_개념.html

 

<script>

    /*
        클래스 내부의 변수 종류

        1. static 변수
            (1) new 없이 바로 사용 가능하다.
            (2) 클래스명.변수명

        2. non-static 변수
            (1) 반드시 new를 통해 객체생성 후 사용 가능하다.
            (2) 객체명.변수명
    */


    class Hello {

        static x = 10;
        y = 20;

    }

    document.write("전역 변수 = " + Hello.x + "<br>");
   
    let h = new Hello();
    document.write("인스턴스 변수 = " + h.y);


</script>

 

 


클래스3_개념05_static변수_예시.html

 

<script>

    /*
        아래 예시와 같이 static변수는 값이 공유되기 때문에
        객체의 개수를 관리하는 count변수에 사용이 가능하다.
    */

    class Monster {
        static count = 0;

        init() {
            Monster.count += 1;
            document.write("몬스터가 생성되었습니다.<br>");
        }

        die() {
            Monster.count -= 1;

            if(Monster.count > 0) {
                document.write("현재 생존자 수는 " + Monster.count + "명 입니다.<br>");
            } else {
                document.write("몬스터가 전멸했습니다.<br>");
            }
        }
    }
   
    let m1 = new Monster();
    let m2 = new Monster();
    let m3 = new Monster();

    m1.init();
    m2.init();
    m3.init();

    m3.die();

    document.write(Monster.count);


</script>

 

 


클래스3_개념06_싱글톤패턴_예시1.html

 

<script>

    class Student {
        constructor(name, kor, eng) {
            /* 변수의 생성과 값 초기화를 동시에 할 수 있다. */
            this.name = name;
            this.kor = kor;
            this.eng = eng;
        }

        printData() {
            document.write("이름:" + this.name + ", 국어:" + this.kor + "점, 영어:" + this.eng + "점<br>");
        }
    }

    class StudentManager {
        constructor() {
            this.stList = [];

            let st1 = new Student("김철수", 100, 20);
            let st2 = new Student("이만수", 20, 40);
            this.stList.push(st1);
            this.stList.push(st2);
        }
    }

    class Board {
        constructor(studentManager) {
            this.studentManager = studentManager;
        }

        printStudentInfo() {
            document.write("전체학생 정보<br>");
            for(let i=0; i<this.studentManager.stList.length; i++) {
                this.studentManager.stList[i].printData();
            }
        }
    }

    class Professor {
        constructor(studentManager) {
            this.studentManager = studentManager;
        }

        searchStudentInfo(index) {
            document.write("학생 검색<br>");
            this.studentManager.stList[index].printData();
        }
    }

    let stManager = new StudentManager();
    let board = new Board(stManager);
    let professor = new Professor(stManager);
    board.printStudentInfo();
    professor.searchStudentInfo(1);

    /*
        위와 같이 게시판(Board)이나 교수(Professor) 클래스에서
        학생 정보를 사용하기 위해서는
        학생매니저(StudentManager) 클래스를 일일이 전부 넣어줘야 한다.

        이를 싱글톤 패턴을 사용하면,
        보다 쉽게 사용가능하다.
    */

</script>

 

 


클래스3_개념06_싱글톤패턴_예시2.html

 

<script>

    /*  
        [개념] 싱글톤 만드는법
                [1-1] 변수앞에 static을 붙이면 전역변수가 된다.  
                [1-2] 리턴함수앞에 static 을 붙여 전역 함수를 만든다.
                [1-3] 전역 변수나 함수는 다른 어떤곳에서든 사용할수있다.
        }
    */

    class Hello {

        // 1단계) 클래스 내부에서 static 변수로 생성한다.
        static instance = new Hello();

        // 2단계) 1단계에서 생성한 instance 변수를 리턴하는 static 함수를 작성한다.
        static getInstance() {
            return Hello.instance;
        }
    }



    let h1 = new Hello();
    let h2 = new Hello();
    document.write(h1 == h2, "<br>");
   
    let h3 = Hello.getInstance();
    let h4 = Hello.getInstance();
    document.write(h3 == h4, "<br>");

</script>

 

 


클래스3_개념06_싱글톤패턴_예시3.html

 

<script>
   

    class Student{
        constructor(name , kor , eng){
            this.name = name;
            this.kor = kor;
            this.eng = eng;
        }
    }

    class StudentManager{
        static stmanage = new StudentManager(); // 내부에서 static 변수로 자신을 생성한다.
        static Instance(){
            return StudentManager.stmanage; // instance 는 그냥 변수명으로 바꿔도 상관없다.
        }

        constructor(){
            this.stList = [];
            let st1 = new Student("김철수" , 100, 20);
            let st2 = new Student("이만수" , 20, 40);
            this.stList.push(st1);
            this.stList.push(st2);
        }
    }

    class Board{
        printStudentInfo(){
            console.log("전체학생")
            let stManager = StudentManager.Instance();
            for(let i = 0; i < stManager.stList.length; i++){
                console.log(stManager.stList[i])
            }
        }
    }

    class Professor{
        searchStudentInfo(index){
            let stManager = StudentManager.Instance();
            console.log("학생검색 : " , stManager.stList[index])
           
        }
    }

    // let stManager = new StudentManager(); 이미 static으로 생성했기 때문에 또 생성하면 안된다.
    let board = new Board();
    let pro = new Professor();
    board.printStudentInfo();
    pro.searchStudentInfo(1);

    /*
        위와 같이 게시판(Board)이나 교수(Professor) 클래스에서
        학생 정보를 사용하기 위해서는
        학생매니저(StudentManager) 클래스를 일일이 전부 넣어줘야 한다.

        이를 싱글톤 패턴을 사용하면,
        보다 쉽게 사용가능하다.
    */
   
</script>