spring_2기[본캠프]/과제

[달리기반 과제] 3회차 과제

minwoo95 2025. 12. 16. 16:05

https://github.com/MinWoo1995/RunningTeam-TASK3

[필수 미션] - 랜덤 1:1 전투 시뮬레이션

이제 서로의 팀에서 랜덤한 챔피언 하나씩 꺼내 싸우게 해보자.

 

[선택 미션]

1. 제네릭 와일드카드(? extends Champion) 적용해보기

미션 내용

  • 아래 메서드를 설계하세요.
public static void printTeamMembers(List<? extends Champion> team)
  • List<Garen> , List<Champion> 모두 받을 수 있어야 합니다.

2. 잘못된 제네릭 설계 사례 만들고 고쳐보기

미션 내용

  • 아래와 같은 잘못된 설계를 먼저 작성합니다.
public class Team<T> {
    private List<T> members;
}
  • 왜 이 설계가 위험한지 설명한 뒤
  • T extends Champion 으로 수정하세요.

 

Main

package Task_LOLChampion;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public class main {
    public static void main(String[] args) {
        Garen garen1 = new Garen("Garen1");
        Garen garen2 = new Garen("Garen2");
        Ash ash1 = new Ash("Ash1");
        Ash ash2 = new Ash("Ash2");

        //가렌1과 에쉬1이 서로 공격을 주고받음
        garen1.attackTo(ash1);
        ash1.attackTo(garen1);

        //Q/W/E/R 스킬을 모두 추상 메서드로 확장해보기
        ash2.useQ(garen2,garen2);
        ash2.useW(garen2);
        ash2.useE(garen2);
        ash2.useR(garen2);

        //Lux, Teemo 등 챔피언 2명 더 만들기
        Lux lux1 = new Lux("Lux1");
        Teemo teemo1 = new Teemo("Teemo1");

        //가렌에게 “레벨업(levelUp)” 메서드를 만들어 체력·공격력 증가하게 해보기
        garen1.levelUp(200);
        garen1.useR(ash1);

        //takeDamage 후 체력이 0 이하가 되면 “가렌 사망!” 메시지 출력
        ash1.useW(garen1);

        //attackDamage 값을 난수(랜덤)로 만들어 “치명타 개념” 추가해보기
        garen2.useE(ash2);

        //인터페이스를 2개 이상 조합한 챔피언 만들기(예: 근거리 + 탱커)
        garen2.defenseDamageUp();
        garen2.dash();

        //“치명타 확률” 같은 고유 패시브를 메서드로 추가해보기
        garen1.useE(ash1);

        //기본 체력, 기본 공격력, 기본 방어력 값 GameConstants의 static final 상수 사용
        Ash ash3 = new Ash("Ash3");

        //모든 챔피언의 전투 횟수(static) 카운팅 기능 추가
        System.out.println("모든 챔피언의 총 전투 횟수 : "+GameConstants.battleCount);

        //고정된 부활(resurrect) 규칙을 final 메서드로 만들기
        Ash ash4 = new Ash("Ash4");
        ash4.setattackDamage(1000);//어택데미지 변수가 상수로 초기 셋팅 되어 기존 어택데미지를 높게 재설정
        ash4.useQ(garen1,garen1);

        //인터페이스 otherResurrect을 만들어 추상메서드를 선언하여 서로 다른 챔피언의 부활 조건을 결정
        //가렌은 최대 2번만 부활이 가능하다.
        //에쉬는 최대 3번만 부활이 가능하다.
        ash4.useQ(garen1,garen1);
        ash4.useQ(garen1,garen1);
        garen1.useQ(ash4,ash4);
        garen1.useQ(ash4,ash4);
        garen1.useQ(ash4,ash4);
        garen1.useQ(ash4,ash4);

        //전투 로그 기록 출력
        GameConstants.LogPrint();

        //static 변수 두 개가 서로 참조할 때 초기화 순서 문제를 경험해보기
        /*int a = 5;
        int c = a + b;//일반 변수의경우 선언되지 않고 먼저 사용하면 오류가 발생
        int b = 5;

        System.out.println(c);*/

        /*
        GameConstants클래스
        public static int a = b+10;
        public static int b = 20;

        public static void test(){
            System.out.println("a :" + a);<-10출력
            System.out.println("b :" + b);<-20출력
        }

        GameConstants.test();
        //확인해보니, 논리적으로 실행이 되어야하는데, 자바 버전에 따라 실행이 불가능함
        */

        //전투 횟수(battleCount)를 인스턴스 필드로 바꾸면 어떤 문제가 생기는지 실험
        //GameConstants.battleCount을 인스턴스로 변경시 모든 챔피언의 전투횟수를 수집할수 없다.
        //챔피언별 battleCount를 가지게 되고 자기의 카운트만 저장하게 됩니다.
        //챔피언별 저장한 카운트를 게터로 받아와서 한대모아 더해서 출력하는 방법이 가능하다.


        //상수 그룹을 Enum으로 표현해보기 [속성(체력/공격/방어)를 상수화 시켜 챔피언 생성시 상수조합으로 챔피언 생성하기]
        //실행 결과 확인하기 GameConstants.championsValue에서 이넘을 정의하고 챔피언 클래스의 생성자에 마력을 설정하게 로직을 구현

        //부활(resurrect) 메서드를 템플릿 메서드 패턴으로 확장해보기

        //3차 과제 시작
        //서로의 팀에서 랜덤한 챔피언 하나씩 꺼내 싸우게 해보자.
        //레드팀 블루팀을 만들고 거기서 랜덤하게 챔피언을 꺼내어 전투하게 하기

        List<Champion> redTeam = new ArrayList<Champion>();
        List<Champion> blueTeam = new ArrayList<Champion>();
        List<Champion> allChampions = new ArrayList<Champion>();

        allChampions.add(new Garen("가렌1"));
        allChampions.add(new Ash("에쉬1"));
        allChampions.add(new Ash("에쉬2"));
        allChampions.add(new Garen("가렌2"));
        allChampions.add(new Ash("에쉬3"));
        allChampions.add(new Ash("에쉬4"));

        //레드팀 블루팀 분류
        for (int i = 0 ; i < allChampions.size(); i++) {
            Champion a = allChampions.get(i);
            if(a.getTeamcolor()==0){
                redTeam.add(a);
            }else{
                blueTeam.add(a);
            }
        }

        //랜덤 전투하기
        RandomBattle randomBattle = new RandomBattle(redTeam, blueTeam);//배틀 객채 생성

        while(true) {
            //체력을 어떻게 설정할지 입력받기
            System.out.print("몇 라운드로 진행 하시겠습니까?(정수로 입력하세요) : ");
            Scanner scan = new Scanner(System.in);
            String scan1 = scan.nextLine();//입력받기
            int scanInt = Integer.parseInt(scan1);//int로 변환
            if (0<scanInt) {
                for (int i = 0; i <= scanInt; i++) {
                    randomBattle.randomBattleManager(redTeam,blueTeam);
                }
                break;
            } else {
                System.out.println("입력을 잘못하셨습니다. 음수,소수점 제외 양의 정수만 입력하세요");
            }
        }

        //클래스 Team 에서 설계된 내용중에 어떻게 문제가 발생하는지 작성해둠

        //제네릭 와일드 카드 적용해보기->RandomBattle클래스에 매개변수를 와일드 카드로 수정

        //printTeamMembers클래스를 만들어 가렌끼리 에쉬끼리 팀을 구성해보기
        List<Garen> garenList = new ArrayList<>();
        List<Ash> ashList = new ArrayList<>();
        garenList.add(garen1);
        garenList.add(garen2);

        ashList.add(ash1);
        ashList.add(ash2);
        ashList.add(ash3);
        ashList.add(ash4);

        System.out.println("----------가렌 챔피언 목록입니다.----------");
        printTeamMembers.printTeamMembers(garenList);
        System.out.println("----------에쉬 챔피언 목록입니다.----------");
        printTeamMembers.printTeamMembers(ashList);
        //[문제]allChampion.getMembers() 메서드 호출시 Task_LOLChampion.Garen@728938a9 해쉬값이 나오게 됨
        //[해결]Champion 클래스에 toString()을 오버라이드 하여 List 컬렉션을 출력할때 JVM이 오버라이드로 정의된 toString()을 호출하여 문자열을 받아간다.
        
    }
}

 

 

Campion

package Task_LOLChampion;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;

public abstract class Champion implements otherResurrect {
    private String name;
    private int levle;
    private int attackDamage;
    private int defenseDamage;
    private int HP;
    private int MP;
    private int ex;
    private int maxEx;
    Random rand = new Random();
    private int mindamage=100;
    private int maxmindamage=300;
    private int randomDamage;
    private int range = maxmindamage - mindamage+1;
    private int resurrectCount = 0;
    private int resurrectCount2 = 0;
    private int maxresurrectCount = 0;
    private int maxresurrectCount2 = 0;
    private int teamcolor = 0;

    final double CRITICAL_CHANCE = 0.5;//50% 확률
    Random random = new Random();



    public Champion(String name,int level,int attackDamage,int defenseDamage,int maxEx) {
        this.name = name;
        this.levle = level;
        this.attackDamage=GameConstants.getAttackDamage();//private static final 상수이기 때문에 게터 메서드로 참조
        this.defenseDamage = GameConstants.getDefenseDamage();//private static final 상수이기 때문에 게터 메서드로 참조
        this.HP = GameConstants.HP;//static final으로 상수를 가져와서 초기화 진행
        this.MP = MP;
        this.maxEx =  maxEx;
        GameConstants.setchampionnum(1);

        while(true) {
            //체력을 어떻게 설정할지 입력받기
            System.out.print(this.getName() + "의 L1=300,L2=400,L3=500,L4=1200 원하는 마력값을 입력해주세요 ex)L1 : ");
            Scanner scan = new Scanner(System.in);
            String scan1 = scan.nextLine();
            if (scan1.equals("L1") || scan1.equals("L2") || scan1.equals("L3") || scan1.equals("L4")) {
                //[문제] GameConstants.championsValue(scan); 이넘클래스는 이렇게 호출불가능
                //[해결] 리턴값을 저장할 공간 = 클래스명.메서드명.해당메서드의 세터로 셋팅후.게터로 리턴해달라
                this.MP = GameConstants.championsValue.valueOf(scan1).getValue();
                break;
            } else {
                System.out.println("입력을 잘못하셨습니다. L1,L2,L3,L4 중에서 대소문자를 구분하여 입력해주세요 : ");
            }
        }
        while(true) {
            //체력을 어떻게 설정할지 입력받기
            System.out.print(this.getName() + "의 RED BLUE 팀을 입력해주세요: ");
            Scanner scan = new Scanner(System.in);
            String scan1 = scan.nextLine();
            if (scan1.equals("RED") || scan1.equals("BLUE")) {
                //[문제] GameConstants.championsValue(scan); 이넘클래스는 이렇게 호출불가능
                //[해결] 리턴값을 저장할 공간 = 클래스명.메서드명.해당메서드의 세터로 셋팅후.게터로 리턴해달라
                this.teamcolor = GameConstants.TeamColor.valueOf(scan1).getValue();
                break;
            } else {
                System.out.println("입력을 잘못하셨습니다. RED,BLUE 중에서 대소문자를 구분하여 입력해주세요 : ");
            }
        }
    }
    public int getTeamcolor() {
        return teamcolor;
    }
    public void setTeamcolor(int teamcolor) {}
    public int criticalDamage(){
        double probabilityCheck = random.nextDouble();
        if (probabilityCheck < CRITICAL_CHANCE) {
            randomDamage = rand.nextInt(range)+mindamage;
        }
        return this.randomDamage;
    }


    public void setresurrectCount(int resurrectCount){
        this.resurrectCount = resurrectCount;
    }
    public int getresurrectCount(){
        return this.resurrectCount;
    }


    public void setmaxresurrectCount(){
        this.maxresurrectCount = GameConstants.getmaxresurrectCount();
    }
    public int getmaxresurrectCount(){
        return this.maxresurrectCount;
    }

    public void setmaxresurrectCount2(){
        this.maxresurrectCount2 = GameConstants.getmaxresurrectCount2();
    }
    public int getmaxresurrectCount2(){
        return this.maxresurrectCount2;
    }

    public void setresurrectCount2(int resurrectCount){
        this.resurrectCount2 = resurrectCount;
    }
    public int getresurrectCount2(){
        return this.resurrectCount2;
    }


    public int getlevel() {
        return levle;
    }
    public void setlevel(int level) {
        this.levle += level;
    }
    public int getrandomDamage(){
        return randomDamage;
    }
    public void setdefenseDamageUp1(int defenseDamage) {
        this.defenseDamage += defenseDamage;
    }
    public int getdefenseDamageUp1(){
        return defenseDamage;
    }
    public int getmaxEx(){
        return maxEx;
    }
    public void setmaxEx(int maxEx) {
        this.maxEx = maxEx;
    }
    public int getEx(){
        return ex;
    }
    public void setEx(int ex){
        this.ex = ex;
    }
    public String getName() {
        return name;
    }
    public int getLevle() {
        return levle;
    }
    public void setHP(int HP) {
        this.HP = HP;
    }
    public int getHP() {
        return this.HP;
    }
    public int getMP() {
        return this.MP;
    }
    public void setMP(int MP) {
        this.MP = MP;
    }
    public int getattackDamage() {
        return this.attackDamage;
    }
    public void setattackDamage(int attackDamage){
        this.attackDamage += attackDamage;
    }
    public void attackTo(Champion target){
        int a=target.getHP()-this.attackDamage;
        target.setHP(a);
        System.out.println(target.getName()+"가"+this.name+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.HP+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        this.MP-=100;
        System.out.println(this.name+"의 남은 마력 : "+this.MP);
    }
    public abstract void useQ(Champion target,otherResurrect target2);
    public abstract void useW(Champion target);
    public abstract void useE(Champion target);
    public abstract void useR(Champion target);
    public void takeDamage(int damage) {
        System.out.println("------------takeDamage------------");
        int m = this.HP - damage;
        if (m <= 0) {
            System.out.println(this.name + "가 사망 하였습니다.");
            System.out.println("-------------------------------");
            setHP(0);
        } else {
            System.out.println(this.name + "의 남은 체력 :" + this.HP);
            System.out.println("-------------------------------");
            setHP(m);
        }
    }
    //고정된 부활(resurrect) 규칙을 final 메서드로 만들기
    final void resurrect1(){

        if(this.HP<=0){
            this.HP=0;//너무 큰 데미지를 입어 마이너스 체력까지 떨어진 상태일 경우 0으로 체력을 초기화후 20센트 체력을 주입
            this.HP+=(int)(GameConstants.HP * 0.2);//해당 변수들이 int 형이기 때문에 더블형이 불가하여 형변환을 해야한다.
            System.out.println(this.name + "의 체력이 20% 회복되어 부활 되었습니다. 현재 체력 : " + this.HP);
            System.out.println(this.name + "님 어서 우물로 돌아가 체력을 회복하세요~");
        }
        hook();

    }
    final void resurrect(){
        if(this.HP<=0){
            this.HP=0;
        }
    }
    public abstract void checkHP();//공격자가 공격 당한 챔피언의 피를 본인 스스로 확인해보라는 메서드
    public void hook(){}
    public void ohterResurrect(){}

    @Override
    public String toString() {
        return this.name;
    }
}

 

GameConstants

package Task_LOLChampion;

import java.util.ArrayList;
import java.util.List;

public class GameConstants {//여기에는 static 선언 불가.
    //내부에 동일한 이름을 가진 (GameConstants)을 2중 구조로 선언시 내부 클래스에는 static 선언이 가능하다.
    //내부에 2중 클래스를 만들어 static을 부여하는 사용법은 크게 2가지 정도이다.
    //1.대규모 상수 그룹의 논리적 분리 (Namespacing) 2. 독립적인 Helper Class 제공
    //1번 이유
    //챔피언 관련    GameConstants.Champion.HP
    //시스템 설정    GameConstants.System.TIMEOUT
    //UI 색상 GameConstants.UI.COLOR_RED
    //2번 이유
    //바깥 클래스의 객체 없이도 독립적으로 동작해야 하는 유틸리티성 헬퍼 클래스를 만들 때 사용

    static final int HP=100;//final 키워드 사용과 동시에 변수 값을 초기화하기 않으면 오류가 발생
    private static final int attackDamage=100;
    private static final int defenseDamage=50;//static이 붙게 되면 class 레벨의 변수가 된다!! 객체 생성없이 바로 사용가능하니까
    //static final은 외부 클래스에서 접근은 가능 하나 수정이 불가하고 참조만 가능하다.
    //static final private은 외부클래스에서 접근이 불가하고 내부 메서드나 생성자를 통해 접근이 가능하다.

    static int battleCount = 0;//모든 챔피언의 전투 횟수 카운트하기 위한 독립 변수
    private static final int resurrectCount = 0;
    private static final int maxresurrectCount = 2;
    private static final int maxresurrectCount2 = 3;
    private static int championnum = 0;//챔피언 생성 수

    private GameConstants(){
        throw new AssertionError("이 클래스는 상수만 취급하는 클래스입니다. [클래스명.상수명]으로 호출하세요");
        //객체를 생성할려고 한다면, 오류문을 출력하여 올바르게 사용할수 있도록 안내하자!
    }
    public static int getchampionnum() {
        return championnum;
    }
    public static void setchampionnum(int championnum) {
        GameConstants.championnum += championnum;//챔피언 생성시 1씩 증가
    }
    //스태틱으로 선언된 상수들만 취급함으로, 생성자를 퍼블릭으로 사용하게 되면,
    //다른 개발자가 불필요하게 객체를 생성하는 일을 방지하여 자원을 효율적으로 사용할수있다.
    //왜냐하면 스태틱 변수들은 객체 생성 없이 바로 클래스명.상수명으로 바로 호출하여 사용하기 때문이다.
    public static int getAttackDamage(){
        return GameConstants.attackDamage;//static 키워드 때문에 this.변수명이 아닌 [클래스명.상수명]으로 리턴을 하면된다.
    }
    public static int getDefenseDamage(){
        return GameConstants.defenseDamage;
    }
    public static int getresurrectCount(){
        return GameConstants.resurrectCount;
    }
    public static int getmaxresurrectCount(){
        return GameConstants.maxresurrectCount;
    }
    public static int getmaxresurrectCount2(){
        return GameConstants.maxresurrectCount2;
    }
    public static List<String> log = new ArrayList<>();//전투로그 저장하는 동적배열
    public static void Log(String logMassage){
        log.add(logMassage);
        System.out.println("전투로그가 기록되었습니다.");
    }
    public static void LogPrint(){
        for(int i=0;i<log.size();i++){
            System.out.println((i+1)+"번 "+log.get(i));
        }
    }

    public enum championsValue{
        //정의
        L1(300),
        L2(400),
        L3(500),
        L4(1200);
        //속성
        private final int value;
        //생성자
        championsValue(int value){
            this.value = value;
        }
        //게터
        public int getValue(){
            return value;
        }
    }
    public enum TeamColor{
        //정의
        RED(0),
        BLUE(1);
        //속성
        private final int color;
        //생성자
        TeamColor(int color){
            this.color = color;
        }
        //게터
        public int getValue(){
            return color;
        }
    }
}

 

ohterResurrect

package Task_LOLChampion;

public interface otherResurrect {
    //인터페이스는 메서드 선언만 해두고, 정의는 각자 클래스에서 알아서 맞춰서 하기
    //자바 7버전은 무조건 메서드를 추상메서드로 선언해야함
    public abstract void ohterResurrect();
}

 

ShortDistance

package Task_LOLChampion;

public interface ShortDistance {
    public void dash();
}

 

Tanker

package Task_LOLChampion;

public interface Tanker {
    public void defenseDamageUp();
}

 

Garen

package Task_LOLChampion;

public class Garen extends Champion implements Tanker,ShortDistance,otherResurrect {
    public Garen(String name){
        super(name,1,1000,50,500);
    }
    @Override
    public void defenseDamageUp() {
        System.out.println("------------근거리 패시브------------");
        System.out.println("방어력이 100 증가합니다.");
        setdefenseDamageUp1(100);
        System.out.println(getName()+"의 패시브 반영 방어력 : "+getdefenseDamageUp1());
        System.out.println("----------------------------");
    }
    @Override
    public void dash(){
        System.out.println("------------탱커 패시브------------");
        System.out.println("앞으로 순간이동을 실시합니다!!");
        System.out.println("----------------------------");
    }
    @Override
    public void useQ(Champion target, otherResurrect target2) {
        System.out.println("------------useQ------------");
        System.out.println(getName() + "이(가) 'Q' 스킬을 사용합니다.");
        attackTo(target);
        System.out.println("----------------------------");
        GameConstants.battleCount++;
        target2.ohterResurrect();
        String logMemo = this.getName()+"의 "+"Q 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useR(Champion target) {
        System.out.println("------------useR------------");
        System.out.println(getName() + "이(가) 'R' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 100;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        System.out.println("----------------------------");
        GameConstants.battleCount++;
        String logMemo = this.getName()+"의 "+"R 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useE(Champion target) {
        System.out.println("------------useE------------");
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        System.out.println(getName() + "의 'E' 스킬은 랜덤한 확률로 치명타 데미지가 발생합니다.");
        int probability = criticalDamage();
        if (probability >= 100) {
            int hp = target.getHP()-getrandomDamage();
            target.setHP(hp);
            GameConstants.battleCount++;
            System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        }else{
            System.out.println(getName() + "의 치명타가 발생하지 않았습니다.");
        }
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 50;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        System.out.println("---------------------------");
        String logMemo = this.getName()+"의 "+"E 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useW(Champion target) {
        System.out.println("------------useW------------");
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = getattackDamage();
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        target.takeDamage(hp);
        int mp = getMP();
        mp -= 20;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());

        System.out.println("----------------------------");
        GameConstants.battleCount++;
        String logMemo = this.getName()+"의 "+"W 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    public void levelUp(int ex) {
        System.out.println("------------levelUp-------------");
        System.out.println(getName()+"이 획득한 경험치 : "+ex);
        int getex = getEx();
        int ex1 = getex+ex;
        setEx(ex1);
        System.out.println(getName()+"의 현재 총 경험치 : "+getEx());
        int getex1 = getEx();
        int maxex = getmaxEx();
        int ex2 = maxex-getex1;
        System.out.println(getName()+"의 레벨업까지 필요한 경험치 : "+ex2);
        if(getex1>=maxex){
            setlevel(1);
            System.out.println(getName()+"레벨업 하였습니다. : 현재레벨 "+getlevel());
            setattackDamage(50);
            setHP(150);
            System.out.println(getName()+"의 총 체력 : "+getHP()+" 총 공경력 :"+getattackDamage());
        }
        System.out.println("-------------------------------");
    }
    @Override
    public void checkHP(){
         if(getHP()<=0){
             System.out.println(getName()+"의 체력이 "+getHP()+" 사망하였습니다.");
             resurrect1();
         }
    }
    @Override
    public void ohterResurrect(){
        this.setmaxresurrectCount();
        int b = this.getresurrectCount();
        int c = this.getmaxresurrectCount();
        if(b<c){
            if(this.getHP()<=0){
                System.out.println(this.getName()+"의 체력이 "+this.getHP()+" 사망하였습니다.");
                resurrect1();
                b++;
                this.setresurrectCount(b);
            }
        }else{
            System.out.println(this.getName()+"은 부활"+this.getmaxresurrectCount()+"회를 사용 하셨음으로 부활이 불가합니다.");
        }
    }
    public void hook(){
        System.out.println(this.getName()+"은 부활하면서 체력 증강 +100 버프를 추가 적용받았습니다.");
        int buf = this.getHP()+100;
        this.setHP(buf);
    }

}

 

Ash

package Task_LOLChampion;

public class Ash extends Champion implements otherResurrect {
    public Ash(String name){
        super(name,1,600,50,500);
    }
    @Override
    public void useQ(Champion target, otherResurrect target2) {
        System.out.println("------------useQ------------");
        System.out.println(getName() + "이(가) 'Q' 스킬을 사용합니다.");
        attackTo(target);
        System.out.println("----------------------------");
        GameConstants.battleCount++;
        target2.ohterResurrect();
        String logMemo = this.getName()+"의 "+"Q 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useR(Champion target) {
        System.out.println(getName() + "이(가) 'R' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 100;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
        String logMemo = this.getName()+"의 "+"R 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useE(Champion target) {
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 50;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
        String logMemo = this.getName()+"의 "+"E 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void useW(Champion target) {
        System.out.println("------------useW------------");
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = getattackDamage();
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        target.takeDamage(hp);
        int mp = getMP();
        mp -= 20;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        System.out.println("----------------------------");
        GameConstants.battleCount++;
        String logMemo = this.getName()+"의 "+"W 스킬 전투로그 기록 타겟 : "+ target.getName();
        GameConstants.Log(logMemo);
    }
    @Override
    public void checkHP(){
        if(getHP()<=0){
            resurrect();
        }
    }
    @Override
    public void ohterResurrect(){
        this.setmaxresurrectCount2();
        int b = this.getresurrectCount2();
        int c = this.getmaxresurrectCount2();
        if(b<c){
            if(this.getHP()<=0){
                System.out.println(this.getName()+"의 체력이 "+this.getHP()+" 사망하였습니다.");
                resurrect1();
                b++;
                this.setresurrectCount2(b);
            }
        }else{
            System.out.println(this.getName()+"은 부활"+this.getmaxresurrectCount2()+"회를 사용 하셨음으로 부활이 불가합니다.");
        }
    }
    public void hook(){
        System.out.println(this.getName()+"은 부활하면서 체력 증강 +200 버프를 추가 적용받았습니다.");
        int buf = this.getHP()+100;
        this.setHP(buf);
    }

}

 

Lux

package Task_LOLChampion;

public class Lux extends Champion {
    public Lux(String name) {
        super(name,5,50,10,600);
    }
    @Override
    public void useQ(Champion target, otherResurrect target2) {
        System.out.println(getName() + "이(가) 'Q' 스킬을 사용합니다.");
        attackTo(target);
        GameConstants.battleCount++;
    }
    @Override
    public void useR(Champion target) {
        System.out.println(getName() + "이(가) 'R' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 100;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void useE(Champion target) {
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 10;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void useW(Champion target) {
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 40;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void checkHP(){
        if(getHP()<=0){
            resurrect();
        }
    }
    public void hook(){
        System.out.println(this.getName()+"은 부활하면서 체력 증강 +300 버프를 추가 적용받았습니다.");
        int buf = this.getHP()+100;
        this.setHP(buf);
    }

}

 

Teemo

package Task_LOLChampion;

public class Teemo extends Champion{
    public Teemo(String name) {
        super(name,2,30,10,400);
    }
    @Override
    public void useQ(Champion target, otherResurrect target2) {
        System.out.println(getName() + "이(가) 'Q' 스킬을 사용합니다.");
        attackTo(target);
        GameConstants.battleCount++;
    }
    @Override
    public void useR(Champion target) {
        System.out.println(getName() + "이(가) 'R' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 100;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void useE(Champion target) {
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 60;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void useW(Champion target) {
        System.out.println(getName() + "이(가) 'E' 스킬을 사용합니다.");
        int hp = target.getHP()-getattackDamage();
        target.setHP(hp);
        System.out.println(target.getName()+"가"+getName()+"에게 공격 당하였습니다. 현재"+target.getName()+"의 체력은"+target.getHP()+"입니다.");
        //출력문을 데미지 계산 위에 위치시켜서 감소된 HP 확인이 안되었다.[문제]
        int mp = getMP();
        mp -= 80;
        setMP(mp);
        System.out.println(getName()+"의 남은 마력 : "+getMP());
        GameConstants.battleCount++;
    }
    @Override
    public void checkHP(){
        if(getHP()<=0){
            resurrect();
        }
    }
    public void hook(){
        System.out.println(this.getName()+"은 부활하면서 체력 증강 +400 버프를 추가 적용받았습니다.");
        int buf = this.getHP()+100;
        this.setHP(buf);
    }
}

 

 

Team

package Task_LOLChampion;

import java.util.List;

public class Team<T> {//클래스명 옆에 <T>을 작성하여 제네릭 클래스임을 명시해야함
    private List<T> members;
}
//이렇게 제네릭을 설계하게 된다면 발생하는 문제점
//타입의 안정성이 보장되지 못한다.
//아무런 타입을 다루게 되며, 반데로 저장된 데이터를 활용할때 오류가 발생할수있다.
//그렇기 때문에, 제네릭의 타입을 지정하여 사용하여야 하며,
//아무런 타입의 데이터가 들어가있다면 로직을 구현하는데도 문제가 발생한다.
//그래서 반드시 클래스명 옆에 제네릭의 상한선은 정하는게 맞다!

 

printTeamMembers

package Task_LOLChampion;

import java.util.ArrayList;
import java.util.List;

public class printTeamMembers{
    public static void printTeamMembers(List<? extends Champion> team){
        System.out.println("---------- 팀 멤버 목록 ----------");
        if (team.isEmpty()) {
            System.out.println("팀에 멤버가 없습니다.");
            return;
        }

        for (Champion member : team) {
            System.out.println(member.getName());
        }
        System.out.println("---------------------------------");
    }
}