Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[보스 몬스터 잡기] 신우경 미션 제출합니다. #7

Open
wants to merge 7 commits into
base: kung036
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/main/java/bossmonster/Main.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package bossmonster;

import bossmonster.action.Play;

public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
Play play = new Play();
play.start();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MP가 20일 때 마법 공격을 할 수 있네요🤔
image

}
}
81 changes: 81 additions & 0 deletions src/main/java/bossmonster/action/BossMonsterAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package bossmonster.action;

import bossmonster.character.BossMoster;

import java.util.Random;

// 보스 몬스터 행동
public class BossMonsterAction {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 BossMonsterAction은 크게 보면 행동과 출력으로 나뉘는데요. 상태 출력하는 것이 BossMonsterAction가 가져야 할 책임일까요? 우경님의 생각이 궁금합니다. 출력부분이 BossMonsterAction에 있는 것과 없는 것 어떤 차이가 있을까요?

public BossMoster bossMoster;

public BossMoster getBossMoster() {
return bossMoster;
}

public void setBossMoster(BossMoster bossMoster) {
this.bossMoster = bossMoster;
}

// 몬스터 상태 출력
public void printState() {
System.out.println("============================");
System.out.println("BOSS HP [" + bossMoster.getCurrentHP() + "/" + bossMoster.getHP() + "]");
}

// 처음 보스 몬스터 출력
public void printFirstState() {
printState();
System.out.println("____________________________\n" +
" ^-^\n" +
" / 0 0 \\\n" +
"( \" )\n" +
" \\ - /\n" +
" - ^ -\n" +
"____________________________\n");
Comment on lines +28 to +34
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

다른 개발자가 새로운 클래스에서 보스몬스터 이미지가 필요한 상황이라고 가정해볼게요. 29~33라인까지 복붙을 하고, 또 다른 클래스에서 복붙을 하고, 복붙x10...
만약 이런 상황이라면 다른 개발자들이 실수할 여지가 있을것 같아요. 만약 보스의 이미지가 바뀐다면? 복붙한 내용을 다 수정해야겠죠. 이런 부분을 어떻게 해결할 수 있을까요?

}

// 공격당한 보스 몬스터 출력
public void printAttackedState() {
printState();
System.out.println("____________________________\n" +
" ^-^\n" +
" / x x \\\n" +
"( \"\\ )\n" +
" \\ ^ /\n" +
" - ^ -\n" +
"____________________________\n");
}

// 보스가 이겼을 경우 상태 출력
public void printWinState() {
printState();
System.out.println("____________________________\n" +
" ^-^\n" +
" / ^ ^ \\\n" +
"( \" )\n" +
" \\ 3 /\n" +
" - ^ -\n" +
"____________________________\n");
}

// 플레이어 공격(0 ~ 20)
public int attack() {
Random random = new Random();
int damage = random.nextInt(20);
System.out.println("보스가 공격 했습니다. (입힌 데미지 : " + damage + ")");
return damage;
}

// 플레이어에게 공격 당함
public void damage(int damage) {
bossMoster.setCurrentHP(bossMoster.getCurrentHP() - damage);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setter를 사용하지 않고 구현해볼까요? setter를 사용한 경우와 사용하지 않은 경우 어떤 장단점이 있을가요?

if (bossMoster.getCurrentHP() < 0) bossMoster.setCurrentHP(0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구글컨벤션에 따르면 비어있는 if문도 중괄호를 사용합니다!

}

// 보스 몬스터 HP 확인
public boolean checkHP() {
if (bossMoster.getCurrentHP() == 0) return true; // HP가 0이 되었을 때
return false;
}

}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

POSIX 명세라는게 존재해요!

95 changes: 95 additions & 0 deletions src/main/java/bossmonster/action/InitialCharacter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package bossmonster.action;

import bossmonster.character.BossMoster;
import bossmonster.character.Player;
import bossmonster.error.Error;

import java.util.Scanner;

public class InitialCharacter {
private Player player = new Player();
private BossMoster bossMoster = new BossMoster();

final Scanner sc = new Scanner(System.in);

// 보스 몬스터 및 플레이어 초기 설정
public InitialCharacter() {
System.out.print("보스 몬스터의 HP 입력 : ");
checkBossMonsterHP();

System.out.print("플레이어 이름 입력 : ");
checkPlayerName();

System.out.print("플레이어의 HP, MP 입력(스페이스로 구분) : ");
checkPlayerHPMP();

System.out.println("보스 레이드를 시작합니다!\n");
}

// 보스 몬스터의 HP 입력 확인
private void checkBossMonsterHP() {
int HP = sc.nextInt();
while(HP < 100 || 300 < HP) {
try {
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
Error.printError("보스 몬스터 초기 HP는 100 이상 300 이하입니다.");
}
Comment on lines +33 to +37
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try-catch 문이 예외를 핸들링 하는게 아니라 if문 처럼 동작하는 것처럼 느껴져요.
어떻게 하면 사용자 입력이 잘못되었을 때, 예외를 던지면서 옳은 값을 입력받을 때 까지 반복할 수 있을까요?

HP = sc.nextInt();
}

bossMoster.setHP(HP);
bossMoster.setCurrentHP(HP);
}

// 플레이어 이름 길이 확인
private void checkPlayerName() {
String name = sc.next();
while(!(name.length() <= 5)) {
try {
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
Error.printError("플레이어 이름 길이는 5자 이하만 가능합니다.");
}
name = sc.next();
}

player.setName(name);
}

// 플레이어의 HP, MP 입력
private void checkPlayerHPMP() {
int HP = sc.nextInt();
int MP = sc.nextInt();
while(!(HP + MP == 200)) {
try {
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
Error.printError("플레이어의 HP와 MP의 합은 200 입니다.");
}
HP = sc.nextInt();
MP = sc.nextInt();
}

player.setHP(HP);
player.setCurrentHP(HP);
player.setMP(MP);
player.setCurrentMP(MP);
}

public void setPlayer(Player player) {
this.player = player;
}

public Player getPlayer() {
return player;
}

public BossMoster getBossMoster() {
return bossMoster;
}

public void setBossMonster(BossMoster bossMoster) {
this.bossMoster = bossMoster;
}
}
91 changes: 91 additions & 0 deletions src/main/java/bossmonster/action/Play.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package bossmonster.action;

import bossmonster.error.Error;

// 게임
public class Play extends InitialCharacter {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InitialCharacter를 상속한 이유가 무엇인가요?

private final BossMonsterAction bossMonsterAction = new BossMonsterAction();
private final PlayerAction playerAction = new PlayerAction();

private int totalTurn = 0;

public Play() {
super();
bossMonsterAction.setBossMoster(getBossMoster());
playerAction.setPlayer(getPlayer());
}

public void start() {
// 첫 시작

while (!bossMonsterAction.checkHP() && !playerAction.checkHP()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클린코드에서는 부정조건절을 지양해요.

// 상태 출력
if (getBossMoster().getHP() == getBossMoster().getCurrentHP()) bossMonsterAction.printFirstState();
else bossMonsterAction.printAttackedState();
playerAction.printState();

// 플레이어 공격
boolean check = true;
while(check) { // MP 확인
// 플레이어 - 공격 방법 입력받기
int attack = printAttack();

// 플레이어 - 공격
check = playerAttack(attack);
}

// 보스 몬스터 - 공격
playerAction.damage(bossMonsterAction.attack());
totalTurn++;
}

// 종료
if (bossMonsterAction.checkHP()) { // 승리
bossMonsterAction.printAttackedState();
playerAction.printState();
System.out.println(getPlayer().getName() + " 님이 " + totalTurn + "번의 전투 끝에 보스 몬스터를 잡았습니다.");
}
if (playerAction.checkHP()) { // 패배
bossMonsterAction.printWinState();
playerAction.printState();
System.out.println(getPlayer().getName() + "의 HP가 0이 되었습니다.");
System.out.println("보스 레이드에 실패했습니다.");
}
}

// 플레이어 공격
private boolean playerAttack(int attack) {
boolean check = true; // 공격 성공한 경우
if (attack == 1) { // 물리공격
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1번이 물리공격이군요! 물리공격이라는 주석을 지운다면 어떻게 다른 개발자에게 물리공격이라고 알려줄 수 있을까요?

playerAction.physicalAttack();
bossMonsterAction.damage(10);
check = false;
} else if (attack == 2 & !playerAction.magicAttack()) { // 마법공격
bossMonsterAction.damage(20);
check = false;
}

return check;
}

// 공격 멘트 출력
private int printAttack() {
System.out.println("어떤 공격을 하시겠습니까?\n" +
"1. 물리 공격\n" +
"2. 마법 공격");

int attack = sc.nextInt();

while (attack != 1 && attack != 2) {
try {
throw new IllegalArgumentException();
} catch (IllegalArgumentException e) {
Error.printError("공격하셔야 합니다. 1 또는 2를 입력해주세요.");
}

attack = sc.nextInt();
}

return attack;
}
}
63 changes: 63 additions & 0 deletions src/main/java/bossmonster/action/PlayerAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package bossmonster.action;

import bossmonster.character.Player;
import bossmonster.error.Error;

public class PlayerAction {
public Player player;

public Player getPlayer() {
return player;
}

public void setPlayer(Player player) {
this.player = player;
}

// 현재 플레이어 상태 출력
public void printState() {
System.out.println(player.getName() + " HP [" + player.getCurrentHP() + "/" + player.getHP() + "]"
+ " MP [" + player.getCurrentMP() + "/" + player.getMP() + "]");
System.out.println("============================");
}

// 플레이어의 물리 공격
public void physicalAttack() {
System.out.println("물리 공격을 했습니다. (입힌 데미지: 10)");
player.setCurrentMP(player.getCurrentMP() + 10); // MP 회복
if(player.getCurrentMP() > player.getMP()) player.setCurrentMP(player.getMP()); // 최대 회복 MP
}

// 플레이어의 마법 공격
public boolean magicAttack() {
try {
checkMP(20);
} catch (IllegalArgumentException e) {
Error.printError("MP가 부족합니다. 물리 공격을 해주세요");
return true;
}

System.out.println("마법 공격을 했습니다. (입힌 데미지: 20)");
player.setCurrentMP(player.getCurrentMP() - 30); // MP 소모
return false;
}

// 보스 몬스터에 데미지 입음
public void damage(int damage) {
player.setCurrentHP(player.getCurrentHP() - damage);
if(player.getCurrentHP() < 0) player.setCurrentHP(0);
}

// 플레이어 HP 확인
public boolean checkHP() {
if(player.getCurrentHP() == 0) return true; // HP가 0이 되었을 때
return false;
}

// 플레이어 MP 확인
public void checkMP(int MP) {
if(player.getCurrentMP() - MP < 0) { // MP가 0이 되었을 때
throw new IllegalArgumentException();
}
}
}
30 changes: 30 additions & 0 deletions src/main/java/bossmonster/character/BossMoster.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package bossmonster.character;

public class BossMoster {
private int HP; // 100 ~ 300
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구글코드컨벤션에 따르면 자바에서 필드명은 lowerCamelCase로 작성해요😄 다른 부분도 수정하면 좋을것 같아요!
참고


private int currentHP;

public BossMoster(int HP) {
this.HP = HP;
}

public BossMoster() {
}

public int getHP() {
return HP;
}

public void setHP(int HP) {
this.HP = HP;
}

public int getCurrentHP() {
return currentHP;
}

public void setCurrentHP(int currentHP) {
this.currentHP = currentHP;
}
}
Loading