package test;
import java.util.Random;
import java.util.Scanner;
abstract class Animal { //만든 클래스 중 제일 상위 추상 클래스
private String name; //멤버변수 private 선언
private String type;
private String habitat;
private String food;
private int hp;
private int cnt;
static Random rand=new Random(); //모두 가져다 쓸 수 있도록 Random, Scanner 계속 사용할거라 객체와 무관한 static으로 멤버변수화
static Scanner sc=new Scanner(System.in);
Animal(String name, String type, String habitat, String food) { //객체 초기화 위해 생성자
this.name = name; //체력 빼고 입력 받을 것
this.type = type;
this.habitat = habitat;
this.food = food;
this.hp = 10; //체력만 10으로 고정
}
abstract void eat(); //추상 메서드 구현X
@Override
public String toString() {
if(this.hp<=0) { //만약 체력이 0이하이면 [기절] 출력
return "[기절] "+this.name;
}
return "Animal [name=" + name + ", type=" + type + ", habitat=" + habitat + ", food=" + food + ", hp=" + hp
+ "]"; //체력이 1이상일경우 전체 출력
}
public String getName() { //getter/setter
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getHabitat() {
return habitat;
}
public void setHabitat(String habitat) {
this.habitat = habitat;
}
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}
public int getCnt() {
return cnt;
}
public void setCnt(int cnt) {
this.cnt = cnt;
}
}
abstract class Fish extends Animal{ //Animal 상속 받는 추상 클래스
private int finCnt; // 멤버변수 private로 선언
private int depth;
Fish(String name, String food, int depth){ //생성자
super(name,"어류","물",food);
this.finCnt=6; // 기본 지느러미 개수 6개로 초기화
this.depth=depth;
}
Fish(String name,String food,int finCnt, int depth){ //생성자
super(name,"어류","물",food);
this.finCnt=finCnt;
this.depth=depth;
}
abstract void swim();//추상 메서드 구현X
abstract void eat();//추상 메서드 구현X
public int getFinCnt() {
return finCnt;
}
public void setFinCnt(int finCnt) {
this.finCnt = finCnt;
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
}
abstract class Bird extends Animal{//Animal 상속 받는 추상 클래스
private boolean fly; // 멤버변수 private로 선언하여 외부에서 값을 맘대로 바꿀 수 없도록 함.
// 날 수 있는지 양자택일 여부를 boolean으로 선언
private int flyDistance;
Bird(String name,String food,boolean fly){ //생성자
super(name,"조류","하늘",food);
this.fly=fly;
this.flyDistance=0; // 입력 없을 시 기본 비행거리 0으로 초기화
}
Bird(String name,String food,boolean fly,int flyDistance){//생성자
super(name,"조류","하늘",food);
this.fly=fly;
this.flyDistance=flyDistance;
}
abstract void fly(); // 추상 메서드. 구현 x
abstract void eat(); // 추상 메서드. 구현 x
public boolean isFly() {
return fly;
}
public void setFly(boolean fly) {
this.fly = fly;
}
public int getFlyDistance() {
return flyDistance;
}
public void setFlyDistance(int flyDistance) {
this.flyDistance = flyDistance;
}
}
class Shark extends Fish implements CreatureAct{ //Fish 상속 받고 CreatureAct 인터페이스 가져옴
Shark(){
super("상어","물고기",1000);
}
void bite() {
char ans;
while(true) {
System.out.println("공격하시겠습니까?>>Y/N"); //유효성 검사
System.out.print("대답 입력>> ");
ans=sc.next().charAt(0); // 사용자에게 입력받은 문자열 첫 글자가 Y라면
ans = Character.toUpperCase(ans); // 소문자일 경우(y) 대문자로 변환하여 y, Y 둘 다 가능하게
if(ans!='Y'&& ans!='N') { // Y나 N이 아니라면
System.out.println("정확히 입력해주세요!"); // 다시 입력하도록
continue; //유효성 검사
}
else {
break;
}
}
if(ans=='Y') {
if(rand.nextInt()<7) { // 70% 확률
setHp(getHp()+5); //private으로 선언한 변수를 getter로 가져오고 setter로 값 재설정
System.out.println("사냥을 성공했어요! 밥을 먹을 수 있습니다");
}
else {
setHp(getHp()-3); // getter로 값을 가져온 후 3 빼고 setter로 재설정
System.out.println("먹이가 도망갔습니다.오늘은 굶어야해요..");
}
}
System.out.println("사냥 종료! 현재 "+getName()+" 체력: " + getHp()); //getter로 멤버변수 가져옴
}
@Override // 가독성 위해 추가
void swim() { // 오버라이딩
System.out.println("상어가 빠른 속도로 헤엄칩니다!");
}
@Override // 가독성 위해 추가
void eat() { // 오버라이딩
setHp(getHp()+5); // getter/setter로 재설정
System.out.println(getName()+"이(가) "+getFood()+"을(를) 먹습니다!"); // 이름과 먹이를 getter로 불러와서 출력
System.out.println("현재 체력: "+getHp()); // getter 사용
}
public void makeEgg(){ // CreatureAct 인터페이스 구현
System.out.println(getName()+"이(가) 알을 낳습니다"); // getter
}
}
class Salmon extends Fish implements CreatureAct{//Fish 상속 받고 CreatureAct 인터페이스 가져옴
Salmon(){
super("연어","곤충",20);
}
int goToRiver(Animal[] datas,int cnt) {
char input;
while(true) {
System.out.print("강으로 올라가시겠습니까? Y/N >>");//유효성 검사
input=sc.next().charAt(0); // 사용자에게 입력받은 문자열의 첫 글자를 판단
input = Character.toUpperCase(input); // 만약 소문자일 경우 대문자로 변환
if(input=='Y' || input=='N') { // Y나 N이면 반복문 탈출
break;
}
System.out.println("Y/N 을 입력해주세요");
}
if(input=='Y') {
if(rand.nextInt(10)<4) { // 40% 확률
setHp(0); // 곰을 만나면 체력을 0으로 설정
System.out.println("곰을 만나서 체력이 0이 되었습니다..휴식이 필요해요...");
}
else {
boolean flag=false;
setHp(getHp()+3); // 체력 받아와서 +3하고 setter로 재설정
System.out.println("여행 완료! 현재 연어 체력: " + getHp());
for(int i=0;i<datas.length;i++) { //유효성 검사
if(datas[i]==null) { // 배열의 요소가 null일 때 (nullpointerexception 에러 방지)
datas[i]=new Salmon(); // 새로운 연어를 도감에 추가
System.out.println("친구를 만났습니다. 새로운 연어가 등록되었습니다!");
cnt++; // 배열 요소 개수 증가
flag=true;
break;
}
}
if(!flag) { // 도감이 가득 찬 경우(배열에 빈 공간 x)
System.out.println("도감이 꽉 차서 친구를 추가할 수 없어요ㅠ");
}
}
}
return cnt; // cnt를 main에서 생성해서 요소로 받아왔기 때문에 반환하지 않으면 main의 값이 바뀌지 않기 때문에 반환함
}
@Override
void swim() {
System.out.println("연어가 여유롭게 헤엄칩니다!");
}
@Override
void eat() {
setHp(getHp()+5); // getter,setter
System.out.println(getName()+"이(가) "+getFood()+"을(를) 먹습니다!");
System.out.println("현재 체력: "+getHp());
}
@Override
public void makeEgg() { //CreatureAct 인터페이스 구현
System.out.println(getName()+"이(가) 알을 낳습니다");
}
}
class Goofy extends Fish{//Fish 상속 받고 CreatureAct 인터페이스 가져오지 않음
// 알을 낳지 않는다고 동물이 아니지 않기 때문에
Goofy(){
super("구피","플랑크톤",1);
}
void makeFriend() {
char ans;
while(true) {
System.out.println("친구를 사귀시겠습니까?>>Y/N");
System.out.print("대답 입력>> ");
ans=sc.next().charAt(0); // 문자열 첫번째 확인
ans = Character.toUpperCase(ans); // 소문자 대문자로
if(ans!='Y'&& ans!='N') { //유효성 검사
System.out.println("정확히 입력해주세요!");
continue;
}
else {
break;
}
}
if(ans=='Y') {
if(rand.nextInt()<7) { // 70% 확률
setHp(getHp()+5); // getter,setter
System.out.println("친구를 사겼습니다!");
}
else {
setHp(getHp()-3);// getter,setter
System.out.println("친구 만들기 실패..");
}
}
System.out.println(getName()+" 체력: " + getHp());
}
@Override
void swim() { // 오버라이딩
System.out.println("구피가 무리지어 헤엄칩니다!");
}
@Override
void eat() { // 오버라이딩
setHp(getHp()+5);// getter,setter
System.out.println(getName()+"이(가) "+getFood()+"을(를) 먹습니다!");
System.out.println("현재 체력: "+getHp());
}
}
class Penguin extends Bird implements CreatureAct{//Bird 상속 받고 CreatureAct 인터페이스 가져옴
Penguin(){
super("펭귄","작은 물고기",false,0);
}
void gatheringPenguin() {
int rand=new Random().nextInt(100)+1; // 100마리
System.out.println("과연 펭귄은 몇마리가 모였을까요0^0?");
System.out.println(rand+"마리가 모였네요!");
if(rand>=10) { // 10마리 이상 모이면
setHp(getHp()+5); // 체력 5 추가
System.out.println("결과: 따뜻하네요..ㅎ");
}
else {
setHp(getHp()-3); // 체력 3 감소
System.out.println("결과: 혹한을 견디지 못했습니다." );
}
System.out.println("체력: "+getHp());
}
@Override
void fly() { // 오버라이딩
System.out.println(getName()+": 푸드덕.....");
}
@Override
void eat() { // 오버라이딩
setHp(getHp()+5);
System.out.println(getName()+"이(가) "+getFood()+"을(를) 먹습니다!");
System.out.println("현재 체력: "+getHp());
}
@Override
public void makeEgg() { //CreatureAct 인터페이스 구현
System.out.println(getName()+"이(가) 알을 낳습니다");
}
}
class Parrot extends Bird implements CreatureAct{//Bird 상속 받고 CreatureAct 인터페이스 가져옴
Parrot(){
super("앵무새","씨앗",true,50);
}
void micmick() {
getHp();
System.out.print("훈련시킬 단어를 입력하세요! >> ");
String word = sc.next(); // 사용자에게 문자열 입력 받음
System.out.println("훈련 중...");
System.out.println("훈련 시작! 현재 앵무새 체력: " + getHp() );
for (int i = 0; i < 3; i++) {
int SuccessRate;
// 각 시도에 따른 성공 확률 설정
if (i == 0) SuccessRate = 50; // 첫 번째 시도: 50%
else if (i == 1) SuccessRate = 70; // 두 번째 시도: 70%
else SuccessRate = 100; // 세 번째 시도: 100%
// if문으로 for문 돌 때 확률 미리 설정
System.out.println((i + 1) + "번째 시도 중... (성공 확률: " + SuccessRate + "%)");
// 랜덤 확률로 훈련 반복
// 위에서 설정한 확률에 맞춰 반복문 실행
if (rand.nextInt(100) < SuccessRate) {
System.out.println("훈련 성공!");
System.out.println("앵무새 : " + word);
setHp(getHp() + 5);
break; // 성공 시 반복 종료
} else {
setHp(getHp() - 3);
System.out.println("훈련 실패... 다시 시도합니다.");
System.out.println("훈련 실패 후 현재 앵무새 체력: " +getHp());
}
}
System.out.println("훈련 종료! 현재 앵무새 체력: " + getHp());
}
@Override
void fly() {
System.out.println("앵무새가 하늘을 훨훨 날았습니다!");
}
@Override
void eat() {
setHp(getHp()+5);
System.out.println(getName()+"이(가) "+getFood()+"을(를) 먹습니다!");
System.out.println("현재 체력: "+getHp());
}
@Override
public void makeEgg() { //Creature 인터페이스 구현
System.out.println(getName()+"이(가) 알을 낳습니다");
}
}
public class AnimalProject02 {
public static void main(String[] args) {
Animal[] datas=new Animal[6]; //main 클래스에서 배열 생성
datas[0]=new Shark();
datas[1]=new Salmon();
datas[2]=new Goofy();
datas[3]=new Penguin();
datas[4]=new Parrot();
int cnt=5; //배열에 저장된 개수
while(true) { //메뉴 선택
System.out.println("0. 종료");
System.out.println("1. 동물 전체 출력");
System.out.println("2. 종류에 따른 행동하기");
System.out.println("3. 개별 행동하기");
System.out.println("4. 밥주기");
System.out.print("메뉴를 입력하세요>>");
Scanner sc=new Scanner(System.in);
int menu=sc.nextInt();
if(menu==0) {
break;
}
else if(menu==1) { //전체 출력
for(int i=0;i<datas.length;i++) {
if(datas[i]==null) { // 배열에 요소가 없으면
System.out.println("비어있음"); // 비어있음 출력
}
else {
System.out.println(datas[i]+" "); //toString 메서드 사용
}
}
}
else if(menu==2) { //종류를 선택해서
int input; //종류만이 할 수 있는 메서드 호출
while(true) {
System.out.println("동물 종류를 선택하세요>>");
System.out.print("1.어류 2.조류 >> " );
input = sc.nextInt();
if(input == 1 || input == 2) {
break;
}
System.out.println("올바른 번호를 입력해주세요");
}
if(input == 1) { //어류 메서드 수행
for(int i = 0; i < datas.length; i++) {
if(datas[i] != null && datas[i].getType().equals("어류")) { // getType으로 받아온 종류가 어류라면 swim 메서드 호출
Fish fish=(Fish)datas[i]; //Animal타입의 배열을
//Fish 타입으로 다운캐스팅
fish.swim(); //다운캐스팅 해서 메서드 호출
}
}
}
else {
for(int i = 0; i < datas.length; i++) { // getType으로 받아온 종류가 조류라면 조류가 가진 fly 메서드 호출
if(datas[i] != null && datas[i].getType().equals("조류")) {
Bird Bird=(Bird)datas[i]; //다운캐스팅
Bird.fly();
}
}
}
}
else if(menu==3) { //동물 선택해서 각각 가지고 있는 메서드 호출
while(true) {
System.out.println("개별 행동하기! 동물을 선택하세요");
System.out.println("1. 상어 2.연어 3.구피 4.펭귄 5.앵무새"); //행동할 동물 선택
int input;
input=sc.nextInt();
if(input<1 || 5<input) { //UI/UX
System.out.println("올바르게 입력하세요");
continue;
}
if(datas[input-1].getHp()==0) { //유효성 검사
System.out.println("체력이 0이에요ㅠ");
break;
}
else if(input==1) { //배열의 요소들 다운캐스팅해서
Shark shark=(Shark)datas[0]; //메서드 호출
shark.bite();
break;
}
else if(input==2) {
Salmon salmon=(Salmon)datas[1];
cnt=salmon.goToRiver(datas,cnt);
break;
}
else if(input==3) {
Goofy goofy=(Goofy)datas[2];
goofy.makeFriend();
break;
}
else if(input==4) {
Penguin penguin=(Penguin)datas[3];
penguin.gatheringPenguin();
break;
}
else if(input==5) {
Parrot parrot=(Parrot)datas[4];
parrot.micmick();
break;
}
else {
System.out.println("올바른 숫자를 입력해주세요");
}
}
}
else if(menu==4) { //동물을 선택해서 먹기 메서드 호출
while(true) {
System.out.println("누구에게 밥을 줄까요?");
System.out.print("1. 상어 2.연어 3.구피 4.펭귄 5.앵무새>>");
int input=sc.nextInt();
if(input==1) {
Shark shark=(Shark)datas[input-1];
shark.eat();
break;
}
else if(input==2) {
for(int i=0;i<cnt;i++) {
if(datas[i].getName().equals("연어")) { // 문자열 비교. getName으로 받아온 문자열이 연어와 같으면
System.out.println(i+1+"번"+datas[i].getName()); // 몇번연어인지 출력
}
}
int num;
while(true) {
System.out.print("몇 번에게 줄까요?>>"); //유효성 검사
num=sc.nextInt();
if(0<num && num<=datas.length) {
break;
}
System.out.println("올바른 번호를 입력해주세요");
}
datas[num-1].eat();
break;
}
else if(input==3) {
Goofy goofy=(Goofy)datas[input-1];
goofy.eat();
break;
}
else if(input==4) {
Penguin penguin=(Penguin)datas[input-1];
penguin.eat();
break;
}
else if(input==5) {
Parrot parrot=(Parrot)datas[input-1];
parrot.eat();
break;
}
else {
System.out.println("올바른 번호를 입력해주세요");
}
}
}
}
}
}