Java 응용 | 턴제게임 만들기(2)

Dalyume·2026년 8월 6일

Java 응용

목록 보기
13/15
post-thumbnail

저번 회차에서는 Character 부모클래스제작과, 그 안에 플레이어 캐릭터와 몬스터 캐릭터를 각각 상속받아서 간단히 턴 주고받고 데미지를 주고받게 하였다.

이번에는 뭘 할 것이냐.. 바로 인벤토리를 추가 할 것이다.

바로 가봅시다잉.


우선 인벤토리를 채우려면 아이템 이 필요하니까 그 아이템의 정보를 저장할 클래스를 만들어주자.

Item 클래스

package com.practice;

public class Item {
    private String name;
    private int count;

    public Item(String name, int count) {
        this.name = name;
        this.count = count;
    }

    public String getName() {
        return name;
    }

    public int getCount() {
        return count;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setCount(int count) {
        this.count = count;
    }
}

이정도면 될 것 같다. 참고로 인벤토리에서 아이템을 Map으로 저장할 예정이다.

key = item.getName(), value = item.getCount() 가 되겠지.

이렇게 짜는 이유는

인벤토리는 “중복아이템이 없을 시” 10칸까지 보관이 가능하게 할 것이다.

중복되면 아이템 개수, item.setCount 를 통해 올리겠지.

그리고 중요한 사항. 바로 10칸 이상이 되었을 시 아이템을 먹을 수 없게 해야하니까, 전에 배운 Exception을 터트릴거다.

InventoryFullException (커스텀 예외처리)

package com.practice;

public class InventoryFullException extends RuntimeException {
    public InventoryFullException(String message) {
        super(message);
    }
}

물론 커스텀으로 exception해야 작업이 편할태니 만들어줬다.

Inventory 클래스

package com.practice;

import java.util.HashMap;
import java.util.Map;

public class Inventory {
    private Map<String, Integer> items = new HashMap<>();
    int inventorySize = 10;

    void addItem(Item item) {
        //    새 아이템인데, size가 10이 넘는다? -> exception
        if (items.size() >= 10 && !items.containsKey(item.getName())) {
            throw new InventoryFullException("아이템이 가득차서 더 이상 들고갈 수 없다!");
        }

        if (items.containsKey(item.getName())) { //    items에 있는 아이템인가? -> value 증가
            items.put(item.getName(), items.get(item.getName()) + item.getCount());
        } else { //    items에 없는 아이템인가? -> 새로 추가
            items.put(item.getName(), item.getCount());
        }
    }

    void showInfo() {
        System.out.println("==========인벤토리==========");
        int count = 1;
        for (Map.Entry<String, Integer> entry : items.entrySet()) {
            System.out.printf("%d. %s / %d개\n", count, entry.getKey(), entry.getValue());
            count++;
        }
        System.out.println("==========================");
    }

}

자 인벤토리 구현까지는 끝났다. 그러면 이제 아이템 수급처가 필요하겠지.

몬스터한태 아이템 드랍을 시킬거다….만!

지금 클래스 상속 상태가 어떻게 되어있지??

그렇다..Character 클래스에 플레이어 캐릭터, 몬스터 캐릭터 둘 다 상속되어있다.

무지성으로 Character 클래스에 DropItem 이런거 넣으면 플레이어가 죽어도 템드랍을 하는 이상현상이 생길 것이기에…

여기서 구조를 조금 바꿔주자.

Warrior
Character 클래스 |Ghoul

기존이 이런 형식이였으니,

PlayerCharacter - Warrior
Character 클래스 |Monster - Ghoul

이렇게 바꿔주면 상속이 더 편해지겠지.

Character 클래스

package com.practice;

public class Character {
    protected String name;
    protected int hp;
    protected int fullHp;
    protected int atk;
    protected int def;
    protected Weapon weapon;

    void attack(Character character) {
        if (weapon == null){
            System.out.println(name + "의 맨손공격!");
            System.out.println("enemy 에게 " + atk + "만큼의 데미지를 주었다.");

        }else {
            System.out.println(name + "의 공격!");
            character.damaged(weapon.additionalDamage(atk));
        }
    }

    void damaged(int damage) {
        int totalDamage = damage - def;

        if(hp <= totalDamage){
            died();
            return;
        }

        if (totalDamage <= 0) {
            System.out.println(name + "은 공격을 받았으나, 데미지를 입지 않았다!");
        } else {
            hp -= damage - def;
            System.out.println(name + "은(는) " + (damage-def) + "만큼의 데미지를 입었다!");
            System.out.println("남은 채력 : " + hp + "/" + fullHp);
        }
    }

    void died(){
        System.out.println(name + "은(는) 쓰러졌다!");
    }

}

died 메서드를 추가해, 체력이 0이 됐을 때 이벤트를 분리했다.

플레이어 캐릭터 클래스

package com.practice;

public class PlayerCharacter extends Character {

    private Inventory inventory;

    public PlayerCharacter() {
        inventory = new Inventory();
    }

    void equipWeapon(Weapon weapon) {
        this.weapon = weapon;
        System.out.println(name + "은 " + weapon.getWeapon() + "을 장착했습니다.");
    }

    void pickUpItem(Item item) {
        System.out.println("전사는 " + item.getName() + " " + item.getCount() + "개를 인벤토리에 넣었다.");
        inventory.addItem(item);
        inventory.showInfo();
    }
}
public class Warrior extends PlayerCharacter

워리어 클래스는 상속을 바꿔주었다.

몬스터 클래스

package com.practice;

import java.util.Random;

public class Monster extends Character{

    private Random random = new Random();
    private Item droppedItem;

    public Item getDroppedItem() {
        return droppedItem;
    }

    public Item dropItem(){
        return new Item("회복 포션", 2);
    }

    @Override
    void died() {
        super.died();
        int randomDrop = random.nextInt(10) + 1;

        if(randomDrop > 3){
            System.out.println(name + "은(는) 아이템을 떨궜다.");
            droppedItem = dropItem();
        }
    }
}
public class Ghoul extends Monster

구울도 마찬가지.

드롭률은 랜덤으로 간단하게 정했는데, 다이스 처럼 주사위 1~10중 3 초과로 뜨면 드롭된다. (약 70%)

package com.practice;

public class MainGameTest {
    public static void main(String[] args) {
        Warrior warrior = new Warrior("전사");
        Ghoul ghoul = new Ghoul();
        Weapon weapon = new Weapon("검", 5);

        warrior.equipWeapon(weapon);
        warrior.attack(ghoul);
        warrior.attack(ghoul);
        warrior.attack(ghoul);
        warrior.attack(ghoul);

        Item item = ghoul.getDroppedItem();

        if(item != null){
            warrior.pickUpItem(item);
        }
    }
}

이제 테스트를 해보자.

전사은 검을 장착했습니다.
전사의 공격!
구울은() 13만큼의 데미지를 입었다!
남은 채력 : 37/50
전사의 공격!
구울은() 13만큼의 데미지를 입었다!
남은 채력 : 24/50
전사의 공격!
구울은() 13만큼의 데미지를 입었다!
남은 채력 : 11/50
전사의 공격!
구울은() 쓰러졌다!
구울은() 아이템을 떨궜다.
전사는 회복 포션 2개를 인벤토리에 넣었다.
==========인벤토리==========
1. 회복 포션 / 2==========================

잘 작동 되는 듯.

예외 테스트도 해봐야겠다.

inventory의 기본 사이즈를 0으로 바꾸고 실행했다.

전사는 회복 포션 2개를 인벤토리에 넣었다.
Exception in thread "main" com.practice.InventoryFullException: 아이템이 가득차서 더 이상 들고갈 수 없다!
	at com.practice.Inventory.addItem(Inventory.java:13)
	at com.practice.PlayerCharacter.pickUpItem(PlayerCharacter.java:18)
	at com.practice.MainGameTest.main(MainGameTest.java:18)

만족스럽다.

profile
신생아 개발자

0개의 댓글