JAVA
를 이용하여 콘솔 슈팅 게임을 제작한다.
구현 요구사항은 총 4가지 이다.
슈팅 콘솔 게임 프로그램의 플로우이다. 총 두 가지로 표현했다.
Class
와 메인 메소드
내에서의 플로우이다.
Class
플로우먼저 클래스간의 플로우는 다음과 같다.
각 클래스의 기능을 간단하게 설명하자면,
Enemy
클래스는 콘솔 게임의 적(보스) 을 담당한다. 역할은 Player
에게 공격받는 역할이다.Player
클래스는 2개 이다. 슈퍼 클래스인 Player 1
과 서브 클래스 Player 2
로 총 두개의 클래스를 갖고 있다.Player
클래스는 콘솔 게임의 플레이어를 담당한다. 역할은 Weapon
을 장착해 Enemy
를 공격한다.Weapon
클래스는 총 4개 이다. 슈퍼 클래스 1개와 서브 클래스 3개로 구성 돼있다.Player
의 공격을 도와주는 역할이다. 각 클래스마다 다른 점은Menu
클래스는 콘솔 게임의 가독성을 높여주는 역할이다. 출력문으로 구성 되어있다.다음은 메인 메소드에서의 프로그램 플로우다.
패키지 이름 : GunGame
클래스 : Enemy
, Game
, Menu
, Player
, Weapon
메소드 개수 : 8개
Menu
package GunGame;
public class Menu {
void MainMenu() {
System.out.println("======== 슈팅 게임 ========");
System.out.println(":: [1] 게임 시작 ");
System.out.println(":: [2] 게임 종료 ");
System.out.println("===========================");
System.out.print(" 숫자[1 - 2] 를 입력 해주세요. >>> ");
}
void BattleMenu() {
System.out.println("========== 전투 메뉴 ===========");
System.out.println(":: [0]Shoot ! ");
System.out.println(":: [1]권총 [2]리볼버 ");
System.out.println(":: [3]자동 소총 [4]핸드 캐넌 ");
System.out.println(":: [5]플레이어 교체 ");
System.out.println("==============================");
System.out.print("숫자[1 - 5] 를 입력 해주세요. >>> ");
}
}
Menu
클래스는 메인 메뉴에서의 전반적인 콘솔 출력문의 담당해주는 클래스이다.
MainMenu()
메소드는 프로그램 최초 컴파일 시 나타나는 메소드이다.BattleMenu()
메소드는 플레이어가 전투 돌입 시 나타나는 메소드이다.Player
package GunGame;
public class Player {
Weapon myGun;
public String pName = "Player 1";
public String ShowUserName() {
return pName;
}
public Player() {
myGun = new Weapon();
}
int Attack() {
return myGun.Shoot();
}
}
class Player2 extends Player {
public Player2() {
super.pName = "Player 2";
}
}
Player
클래스는 이 프로그램에서의 플레이어를 담당하는 클래스이다.
Player
슈퍼 클래스와 Player2
서브 클래스가 있다.Weapon
클래스 객체가 존재한다.ShowUserName()
메소드는 현재 플레이어 이름을 보여주는 메소드이다.Attack()
메소드는 플레이어가 장착한 무기로 적에게 공격을 한다. 여기서 내가 태그(교체)기능을 표현하고자 한 것은 Player2
서브 클래스에서 Player2
를 생성 할 때 플레이어 이름을 부모 클래스로의 인스턴스 변수를 참조super()
하여 Player 2로 변경 했다.public Player2() {
super.pName = "Player 2";
}
Weapon
package GunGame;
public class Weapon {
int ammo = 60;
int damage = 10;
String weaponName = "권총";
public Weapon() {
System.out.println("\"" + weaponName + "\" 을(를) 장착하셨습니다 !");
}
public Weapon(int ammo, int dmg) {
this.ammo = ammo;
this.damage = dmg;
}
public void ChangeName(String mine) {
this.weaponName = mine;
System.out.println("\"" + weaponName + "\" 을(를) 장착하셨습니다 !");
}
protected int Shoot() {
System.out.println("빵 야 - ! !");
System.out.println("현재 무기 : " + weaponName);
ammo -= damage;
if (ammo >= 0) {
System.out.println("적에게 준 데미지 : \"" + damage +"\" Hit !");
System.out.println("현재 남은 탄약은 \"" + ammo + "\" 이에요.");
return damage;
} else {
System.out.println("탄약이 부족해요 ! !");
System.out.println("무기를 바꿔 재장전 해주세요.");
}
return 0;
}
}
class Revolver extends Weapon {
String weaponName = "리볼버";
public Revolver(int ammo, int damage) {
super(ammo, damage);
super.weaponName = weaponName;
ChangeName(weaponName);
}
}
class Rifle extends Weapon {
String weaponName = "자동 소총";
public Rifle(int ammo, int damage) {
super(ammo, damage);
super.weaponName = weaponName;
ChangeName(weaponName);
}
}
class Canon extends Weapon {
String weaponName = "핸드 캐넌";
public Canon(int ammo, int damage) {
super(ammo, damage);
super.weaponName = weaponName;
ChangeName(weaponName);
}
}
Weapon
클래스는 Player
가 적에게 공격을 도와주는 역할을 하는 클래스이다.
클래스 내의 메소드는 총 2개이다.
슈퍼 클래스의 생성자는 기본적으로 2개이다. 2개로 구분 지은 이유는 다음과 같다.
첫번 째 생성자의 존재 이유는 프로그램 내에서 기본 무기(Weapon
) 선택 시에는
int ammo = 60;
int damage = 10;
String weaponName = "권총";
public Weapon() {
System.out.println("\"" + weaponName + "\" 을(를) 장착하셨습니다 !");
}
위의 코드들이 적용되어 총알은 60발, 데미지는 10발로 선택되게 하기 위함이고
// 슈퍼 클래스 내 생성자
public Weapon(int ammo, int dmg) {
this.ammo = ammo;
this.damage = dmg;
}
class Revolver extends Weapon {
String weaponName = "리볼버";
public Revolver(int ammo, int damage) {
super(ammo, damage);
super.weaponName = weaponName;
ChangeName(weaponName);
}
}
두 번째 생성자는 나머지 서브클래스(총 3개)들을 super()
를 이용하여 슈퍼 클래스에 생성자에 접근해 각각 서브 클래스들의 총알과 데미지를 메인 메소드내에서 서브 클래스 호출 시 쉽게 바꾸기 위해서였다.
public void ChangeName(String mine) {
this.weaponName = mine;
System.out.println("\"" + weaponName + "\" 을(를) 장착하셨습니다 !");
}
해당 메소드는 기본 무기 클래스를 제외한 모든 무기 클래스에서 생성 될 때 마다 무기가 바뀌었다는 텍스트를 출력하는 메소드이다.
다음은 Weapon
클래스에서 중요한 적에게 데미지를 주는 Shoot()
메소드 표현방식이다.
protected int Shoot() {
System.out.println("빵 야 - ! !");
System.out.println("현재 무기 : " + weaponName);
ammo -= damage;
if (ammo >= 0) {
System.out.println("적에게 준 데미지 : \"" + damage +"\" Hit !");
System.out.println("현재 남은 탄약은 \"" + ammo + "\" 이에요.");
return damage;
} else {
System.out.println("탄약이 부족해요 ! !");
System.out.println("무기를 바꿔 재장전 해주세요.");
}
return 0;
}
해당 메소드의 로직은 다음과 같다.
Shoot()
메소드가 호출 될 때마다 클래스 내 데미지(damage
) 값 만큼 총알(ammo
)이 깎이도록 했다. damage
값을 리턴하여 적에게 데미지를 줬다. 0
을 리턴하여 데미지를 못 주도록 설정했다.Enemy
package GunGame;
public class Enemy {
int enemyHP;
public Enemy() {
// 적 체력 500-1000 난수 생성
enemyHP = (int)(Math.random()*(1000-500)) + 500;
}
void EnemyStatus() {
System.out.println("보스의 현재 체력은 \"" + enemyHP + "\" 이에요!");
}
void EnemyClearText() {
System.out.println("★★★★★★★★★★★★★★★★★★★★★★★★★★★★");
System.out.println("★★ 보스 퇴치 성공 ! ★★");
System.out.println("☆★★★★★★★★★★★★★★★★★★★★★★★★★★★");
System.out.println("메인 메뉴로 돌아 갑니다..");
}
}
Enemy
클래스는 이 프로그램에서 적(보스)를 담당하는 클래스이다.
Enemy
클래스가 호출 될 때마다 생성자 내부에서 적의 체력을 500-1000 사이로 랜덤하게 나오도록 했다.EnemyStatus()
메소드는 현재 적의 체력상태를 텍스트로 출력해주는 메소드이다.EnemyClearText()
는 적을 정상적으로 처치했을 때 텍스트를 출력해주는 메소드이다. package GunGame;
import java.util.InputMismatchException;
import java.util.Scanner;
public class Game {
// 메인 메소드
public static void main(String args[]) {
Menu menu = new Menu();
Enemy boss = new Enemy();
Scanner sc = new Scanner(System.in);
int inputNum = 0;
try {
while (true) {
menu.MainMenu();
inputNum = sc.nextInt();
sc.nextLine();
if (inputNum == 1) {
System.out.println("* - 게 임 스 타 트 - *");
Player p1 = new Player();
System.out.println("\"" + p1.ShowUserName() + "\" : 연결 완료 !");
boss.EnemyStatus();
while (true) {
if (boss.enemyHP > 0) {
int selNum;
menu.BattleMenu();
selNum = sc.nextInt();
sc.nextLine();
switch (selNum) {
case 0:
boss.enemyHP -= p1.Attack();
boss.EnemyStatus();
break;
case 1: // 기본 무기 장착 및 재장전
p1.myGun = new Weapon();
break;
case 2: // 리볼버 장착 및 재장전(탄약 : 120 , 데미지 30) 총 4 번 슈팅 가능
p1.myGun = new Revolver(120, 30);
break;
case 3: // 라이플 장착 및 재장전(탄약 : 200 , 데미지 50) 총 4 번 슈팅 가능
p1.myGun = new Rifle(200, 50);
break;
case 4: // 핸드캐넌 장착 및 재장전(탄약 : 450 , 데미지 150) 총 3 번 슈팅 가능
p1.myGun = new Canon(450, 150);
break;
case 5:
if (p1 instanceof Player2) {
p1 = new Player();
System.out.println("\"" + p1.ShowUserName() + "\" 로 변경!");
break;
}
if (p1 instanceof Player) {
p1 = new Player2();
System.out.println("\"" + p1.ShowUserName() + "\" 로 변경!");
break;
}
default:
System.out.println("숫자 [1-5] 만 입력해주세요.");
break;
}
}
else if (boss.enemyHP <= 0) { // 보스 처치 시 실행되는 부분.
boss.EnemyClearText();
boss = new Enemy(); // 보스 새로 생성
break; // 메인 메뉴로 복귀
}
}
}
else if (inputNum == 2) {
System.out.println("게임을 종료 합니다.");
break;
}
else
System.out.println("숫자 [1 - 2] 만 입력해주세요.");
}
} catch (InputMismatchException e) {
System.out.println("입력값 오류 ! 숫자만 입력 해주세요.");
System.out.println("프로그램을 종료합니다. .");
}
}
}
Game
클래스는 프로그램의 메인이자 실행을 담당하는 메소드이다.
catch (InputMismatchException e) {
System.out.println("입력값 오류 ! 숫자만 입력 해주세요.");
System.out.println("프로그램을 종료합니다. .");
}
switch
문 내부이다. switch (selNum) {
case 0:
boss.enemyHP -= p1.Attack();
boss.EnemyStatus();
break;
case 1: // 기본 무기 장착 및 재장전
p1.myGun = new Weapon();
break;
case 2: // 리볼버 장착 및 재장전(탄약 : 120 , 데미지 30) 총 4 번 슈팅 가능
p1.myGun = new Revolver(120, 30);
break;
case 3: // 라이플 장착 및 재장전(탄약 : 200 , 데미지 50) 총 4 번 슈팅 가능
p1.myGun = new Rifle(200, 50);
break;
case 4: // 핸드캐넌 장착 및 재장전(탄약 : 450 , 데미지 150) 총 3 번 슈팅 가능
p1.myGun = new Canon(450, 150);
break;
case 5: // 플레이어 변경 기능
if (p1 instanceof Player2) { // Player1가 Player2에 속할 경우 플레이어1 생성
p1 = new Player();
System.out.println("\"" + p1.ShowUserName() + "\" 로 변경!");
break;
}
if (p1 instanceof Player) { // Player1가 그대로 Player에 속할 경우 플레이어2 생성
p1 = new Player2();
System.out.println("\"" + p1.ShowUserName() + "\" 로 변경!");
break;
}
기본 무기 선택 시(1번 입력시)에는 슈퍼 클래스의 생성자가 생성되고, 그 외에 모든 무기는 서브 클래스이기 때문에 상속 받은 슈퍼 클래스를 참조하여 생성자에 접근 한 후 총알과 데미지를 설정 했음을 알 수 있다.
5번 선택시는 instanceof
를 이용하여 클래스를 확인한 후 각각의 플레이어가 특정 클래스에 속한지 체크 후 형변환하여 서로 태그(교체)해서 새로운 플레이어로 만들어줬다.
아래 이미지를 클릭하여 출력 영상(Youtube)을 볼 수 있다.
아래는 실행 결과다.
사용자로부터 1번 입력을 받고 게임 시작과 동시에 Player
와 보스(Enemy)
가 생성된다.
Player
는 기본적으로 Weapon(기본 권총)
을 들고 있다.
보스의 체력은 500-1000
으로 랜덤 생성된다.
입력 시 행동
Player 1
또는 Player 2
로 교체 된다.여기서 총을 선택[1-4 번 입력]
할 때 마다 무기의 탄약이 자동으로 충전된다.
보스 처치 시 시작시 최초 메뉴로 돌아간다.
이번 콘솔 게임을 설계하고 작성하며 객체 지향에 점점 익숙해져 갔다.
슈퍼클래스 및 서브클래스의 상호작용 개념과 super()
의 사용법, 각 클래스의 메소드를 어디서 호출해야 코드를 간결하게 표시할 수 있을지 고민하고 또 고민했다.
메인 메소드를 더욱 간결하게 표현하고 싶었는데, 현재 내 지식으로 최대한 간결하게 짜봤다.
이 코드에서 개선해야할 부분은 상속 할 때 오버라이딩을 활용 못한 점, instanceof
를 적절히 사용했는 지 피드백을 듣고 싶다. 또한 이 코드에서의 문제점이 무엇인지 다른 분들께 피드백을 받고 싶다.
Emily had always been fascinated by games of chance, but she never truly engaged with them until a friend introduced her to a new online https://stellarspinscasino1.com/ blackjack site. With its fresh interface and promises of exciting gameplay, Emily decided to delve in. She was meticulous in her approach, studying the site’s rules and bonuses thoroughly before placing her first bet. Her aim was to balance enjoyment with strategy, a challenge she was eager to embrace.