코딩항해기
[Team] Pokemon 게임 만들기 본문
Pokemon 게임 만들기
java / Eclipse
4인참여 (팀장직 수행)
240705 ~ 240711
java 상속, 오버라이딩 연습을 위한 팀 프로젝트를 진행하였다.
[요구사항]
[포켓몬스터 게임 프로그램을 작성해주세요]
class 포켓몬 String 타입 // 모든 포켓몬은 타입이 반드시 존재한다. ex) 전기, 물, ...
String 이름 // 모든 포켓몬은 이름이 반드시 존재한다. ex) 피카츄, 꼬부기, ...
int 레벨 // 새로 잡은 포켓몬의 레벨은 1~5 랜덤한 값을 가진다.
int 경험치 // 새로 잡은 포켓몬의 경험치는 0이다.
void attack() // 50%의 확률로 성공 -> 성공시 50~500 사이의 경험치 획득
void hello() // 피카츄는 삐까삐까, 꼬부기는 꼬북꼬북 등의 울음소리를 출력한다.
void levelUp() // 경험치가 100을 채울때마다 레벨은 +1
class 피카츄
attack() // 전기타입 -> 전기충격
hello() // 삐까삐까
class 꼬부기
attack() // 물타입 -> 물대포
hello() // 꼬북꼬북
syso(포켓몬객체); 수행시 [피카츄 전기타입 Lv5 exp10]으로 출력
- 게임하기 2. 전체상태출력 3. 울음소리듣기 4. 포켓몬잡기 0. 게임종료
# 피카츄,꼬부기 대신 다른 포켓몬들로 구현할 것!
# 요구사항을 벗어나지않는 조건에서 기능 및 설정 추가 가능!
- 게임하기를 누르면
- 포켓몬 중 하나를 고름
- 공격
- 성공을 하면 레벨업
- 포켓몬 잡기는 create
[패키지, 클래스명 설정]
타입 | 공격 | 울음소리 | ||
패키지명 | teamproject | |||
메인클래스명 | PokemonGame | |||
포켓몬 | Pokemon | |||
뮤 | Myu | 에스퍼 | 염동력 | 뮤 |
쥬쥬 | Jyujyu | 물 | 아쿠아링 | 쥬쥬 |
두두 | Dudu | 노멀 | 박치기 | 두두 |
[로직구성]
- 프로그램 종료 전까지 반복함
- 메뉴출력
- 입력값 받기
- 입력값 검증
- 게임종료라면 프로그램 종료, 반복 종료
- 게임하기라면
- 포켓몬을 소유하고 있는지 확인
- 소유하고있다면,
- 포켓몬 중 하나를 고름 (=전체출력메소드)
- 올바른 값을 입력받을 때까지 반복함
- 공격 진행 할지 확인하기
- 공격 진행
- 성공이라면 경험치 (50~500) 랜덤 부여
- 레벨업
- 성공실패 여부와 경험치, 레벨 내용 출력
- 소유하고 있는 포켓몬이 없다면
- 없다고 안내 + 포켓몬 잡으라고 안내
- 소유하고있다면,
- 포켓몬을 소유하고 있는지 확인
- 전체 상태 출력이라면,
- 소유하고 있는 포켓몬이 있는지 확인
- 있다면
- 소유하고 있는 포켓몬의 상태 전체 출력 (toString)
- 없다면 없다고 안내
- 있다면
- 소유하고 있는 포켓몬이 있는지 확인
- 울음소리 듣기라면
- 포켓몬을 소유하고 있는지 확인
- 소유하고 있다면,
- 포켓몬 중 하나를 고름 (=전체출력)
- 옳은 값을 입력할 때까지 반복
- 울음소리 출력
- 소유하고 있는 포켓몬이 없다면
- 없다고 안내
- 소유하고 있다면,
- 포켓몬을 소유하고 있는지 확인
- 포켓몬 잡기 라면
- 저장할 공간이 있는지 확인
- 있다면,
- 포켓몬 객체 랜덤 저장
- 저장한 객체 안내
- 없다면,
- 더 이상 잡을 수 없다고 안내
- 선택지에 없는 값이라면
- 올바른 입력값에 대해 안내
- 선택지의 내용을 실행했다면 다시 메뉴출력부터 반복
[파트분배]
전체메뉴 구성 + 소유여부(메소드) + 1차 취합 | aaa |
전투하기 (=게임하기) | bbb |
포켓몬잡기 (포켓몬객체저장) | miniBcake (팀장) |
포켓몬정보, 울음소리 출력+클래스(메소드부분) | ccc |
[코드흐름도-상세]
파트 담당자들이 각자 파트 작성
[main 한글코딩]
스캐너 선언
- 프로그램 종료 전까지 반복함(무한 반복)
- while(무한 반복)
- 메뉴출력★☆★포켓몬 게임★☆★ϞϞ(๑◕ܫ◕๑) ( U U) U U
- 게임종료
- 게임시작
- 전체 상태 출력
- 울음소리 듣기
- 포켓몬 잡기
- ===================
- (),,,()
- ===================
- 입력값 선언
- 메뉴값 초기화
- 입력값 받기 및 검증(유효성 검사)메뉴값 입력받기
- while 똑바로 입력할때까지 입력하기(무한 반복)
- 게임종료라면 프로그램 종료, (반복 종료)종료
- if(만약에 menu가 0이라면)
- 게임하기라면
- 포켓몬을 소유하고 있는지 확인
- 소유하고있다면,
- 소유중인 포켓몬 배열 생성; 최대 6마리
- 초기 배열 ‘0’;
- 메뉴 4번
- if문 사용(단발성 공격일땐)
- 포켓몬 없이는 공격이 안되므로 없는 플레이어는 잡고 오도록 유도
- 보유중인 포켓몬 데이터 전부 제시하고(선택할 수 있도록)
- “입력하십시요”
- for 반복문으로 (선택한 번호 와 맞는 ’포켓몬’ )
- 리스트 println(); 배열 리스트 변수 활용해서 출력문 작성
- 올바른 값을 입력받을 때까지 반복함if (int ≤0 && int>myPokeList.length){ 총 6마리 보유가능)
- 공격, 2. 포켓몬 재선택, 그 외 옵션 (종료 ‘flag=false’)
- 입력받은 정수 유효성 검사
- 공격 진행 할지 확인하기sc.nextInt() 1 = Y / 2 = N안한다면 포켓몬 고르는 메뉴로 if(i=2){
- continue;}
- ‘1’ = 1-4. 공격진행으로
- syso “이 포켓몬으로 공격 진행하겠습니까?”
- 공격 진행 (attack())
- int randomAtt 변수 선언
- randomATT는 랜덤 값을 2까지로 설정해서 50% 확률로 공격 설정 1 or 2 랜덤
- 1이면 성공하면 ???
- int randomExp 변수 선언
- randomExp의 값을 50~500까지 수중에 랜덤으로 준다.
- 만약에 경험치가 this.exp + randomExp >100 이상이라면
- randomExp를 100으로 나누어서 몫의 값(levelCount)을 levelUp() 인자로 보내서 더해주는 함수를 실행하고 !!
- this.exp + randomExp에서 levelCount*100의 값을 빼준값을 this.exp에 저장시킨다.
- 만약에 this.exp + randomExp <100 이하
- 레벨업함수를 실현시키지 않고, randomExp의값을 this.exp에 더해서 this.exp에 저장 시킨다.
- 얼마만큼 경험치가 상승했는지 출력해준다.
- 성공실패 여부와 경험치, 레벨 내용 출력(levelUp())
- levelUp()함수에 levelCount(int i)라는 인자를 받아서
- level라는 멤버변수를 level멤버변수+i 라고 설정한다.
- 몇만큼 레벨업되었는지 출력해주고 현재레벨을 출력해준다.
- 소유하고 있는 포켓몬이 없다면
- 없다고 안내 + 포켓몬 잡으라고 안내
- sc.nextInt();
- ==================
- syso 배열 출력
- 포켓몬을 소유하고 있는지 확인
- if(만약에 menu가 1이라면)
- 전체 상태 출력이라면,
- 소유하고 있는 포켓몬이 있는지 확인
- mypoke 배열안에 있다면 인자가 있다면
- 소유하고 있는 포켓몬의 상태를 반복문을 사용해서 전체 출력 (toString)
- 없다면 없다고 안내
- mypoke 배열안에 있다면 인자가 있다면
- 소유하고 있는 포켓몬이 있는지 확인
- if(만약에 menu가 2이라면)
- 울음소리 듣기라면
- 포켓몬을 소유하고 있는지 확인
- 소유하고 있다면,
- 포켓몬 중 하나를 고름
- 옳은 값을 입력할 때까지 반복
- 울음소리 출력
- 소유하고 있는 포켓몬이 없다면
- 없다고 안내
- 소유하고 있다면,
- 포켓몬을 소유하고 있는지 확인
- if(만약에 menu가 3이라면)
- 포켓몬 잡기 라면
- 저장할 공간이 있는지 확인
- 있다면,
랜덤값 (0~99) 설정if(랜덤값이 55~99 이라면) { 배열 = 두두 객체 저장} 45%else if(랜덤값이 10~54 이라면) { 배열 = 쥬쥬 객체 저장} 45%elseif(랜덤값이 0~9 이라면) { 배열 = 뮤 객체저장} 10%syso([피카츄 전기타입 Lv5 exp10]을 잡았습니다!)(디벨롭:메뉴선택으로 잡기)- 5개의 잡을 수 있는 포켓몬을 저장할 수 있는 배열 생성
- 포켓몬 확률 지정
- 포켓몬 확률을 전부 더한 값이 100이 아니라면 프로그램 진행불가 (continue) 안내 (개발자 잘못)
- for (잡을 수 있는 포켓몬 배열 길이만큼 반복하기) {
- 랜덤값 (0~99) 설정
- if(랜덤값이 두두 범위 내라면) { 배열 = 두두 객체 저장} 45%
- else if(랜덤값이 쥬쥬 범위 내라면) { 배열 = 쥬쥬 객체 저장} 45%
- else if(랜덤값이 뮤 범위 내라면) { 배열 = 뮤 객체저장} 10%
- }
- 배열을 반복하여 랜덤으로 설정된 잡을 수 있는 포켓몬 이름을 출력 (0을 입력하면 메뉴로 돌아가기)
- int subMenu = 사용자 입력받기
- subMenu가 0~5 사이의 값일때까지 반복함
- if (subMenu가 0이라면){메뉴로 돌아감(break;)}
- else if (범위의 값이라면) {
- 랜덤값 (0~99) 지정
- 확률(82%) 기준 지정
- if 잡기에 성공하면 (랜덤값이 확률보다 작다면)
- 선택한 번호-1에 맞는 배열값을 불러와 사용자 소유 포켓몬 배열에 저장함
- syso([피카츄 전기타입 Lv5 exp10]을 잡았습니다!)
- else 잡기에 실패하면 (랜덤값이 확률과 같거나 크다면)
- syso([피카츄 전기타입 Lv5 exp10]을 놓쳤습니다…)
- if 잡기에 성공하면 (랜덤값이 확률보다 작다면)
- }
- else{syso 올바른 입력값 안내 }
- 없다면,
- 더 이상 잡을 수 없다고 안내
- if(만약에 menu가 4이라면)
- 선택지에 없는 값이라면
- 올바른 입력값에 대해 안내
- if(만약에 menu가 이상하다면)
- 선택지의 내용을 실행했다면 다시 메뉴출력부터 반복
[메소드, 함수 한글코딩]
유효성검사 함수
FullPoke (내가 가진 포켓몬(cnt)가 내 가방에 가득 찼을때(Pokemon[] myPokeList)) 만약 내가가진 포켓몬수가 내 가방보다 크다면 포켓몬을 최대로 소유하고 있습니다.
NoPoke (내가 가진 포켓몬(cnt)가 0보다 작을때) 소유하고 있는 포켓몬이 없습니다.
[코드]
package teamproject;
import java.util.Random;
import java.util.Scanner;
class Pokemon {
String type; // 모든 포켓몬은 타입이 반드시 존재한다. ex) 전기, 물, ...
String name; // 모든 포켓몬은 이름이 반드시 존재한다. ex) 피카츄, 꼬부기, ...
int level; // 새로 잡은 포켓몬의 레벨은 1~5 랜덤한 값을 가진다.
int exp; // 새로 잡은 포켓몬의 경험치는 0이다.
static Random rand = new Random();
Pokemon(String type, String name) {
this.type = type;
this.name = name;
this.level = rand.nextInt(5) + 1;
this.exp = 0;
}
void attack() {
// 50%의 확률로 성공 -> 성공 시 50~500 사이의 경험치 획득
// 50% 확률로 공격 설정
int randomAtt = Pokemon.rand.nextInt(2); // 0 or 1
if (randomAtt == 0) { // 공격 성공
System.out.println("공격에 성공하였습니다.");
int minExp = 50;
int maxExp = 500;
// 50~500 사이의 랜덤 경험치 획득
int randomExp = Pokemon.rand.nextInt(maxExp - minExp + 1) + minExp; // 50 ~500 사이
int newExp = this.exp + randomExp; // 총 경험치 합
if (newExp >= 100) {
// 레벨업 처리
int levelCount = newExp / 100; // 레벨업 카운트
this.exp = newExp % 100; // 남은 경험치
this.levelUp(levelCount); // 레벨업 메서드 실행
System.out.println(levelCount + " 만큼 레벨업하였습니다.");
} else {
// 경험치 추가
this.exp = newExp; // 100이 안될경우 그냥 경험치 저장
System.out.println(this.exp + " 경험치가 올랐습니다.");
}
} else {
// 공격 실패
System.out.println("공격에 실패하였습니다.");
}
}
void hello() {
// 피카츄는 삐까삐까, 꼬부기는 꼬북꼬북 등의 울음소리를 출력한다.
System.out.println("힝~");
}
void levelUp(int i) {
// 경험치가 100을 채울때마다 레벨은 +1
this.level = this.level + i;
}
@Override
public String toString() {
// [피카츄 전기타입 Lv5 exp10]
return "["+ this.name +" "+ this.type +"타입 Lv."+ this.level+" exp."+ this.exp + "]";
}
}
class Myu extends Pokemon {
Myu() {
super("에스퍼", "뮤");
}
@Override
void hello() {
System.out.println("뮤뮤뮤");
}
}
class Jyujyu extends Pokemon {
Jyujyu() {
super("물", "쥬쥬");
}
@Override
void hello() {
System.out.println("쮸쮸쮸");
}
}
class Dudu extends Pokemon {
Dudu() {
super("노멀", "두두");
}
@Override
void hello() {
System.out.println("뚜뚜뚜");
}
}
public class PokemonGame {
public static boolean isEmpty(int cnt) {
if (cnt <= 0) {
System.out.println("소유한 포켓몬이 없습니다!");
return true;
}
return false;
}
public static boolean isFull(int cnt, Pokemon[] datas) {
if (cnt >= datas.length) {
System.out.println("더이상 포켓몬을 소유할 수 없습니다!");
return true;
}
return false;
}
public static void main(String[] args) {
Random rand = new Random();
Scanner sc = new Scanner(System.in);
//변수
int menu; //메뉴값입력
int cnt=0; //저장되어있는 포켓몬 수
Pokemon[] myPokeList = new Pokemon[6]; //내포켓몬 저장할 배열
while (true) {
System.out.println("===================\n"
+ " ★☆★포켓몬 게임★☆★\n"
+ " (),,,()\n"
+ " ϞϞ(๑◕ܫ◕๑)\n"
+ " ( U U)\n"
+ " U U\n"
+ "===================\n"
+ "0. 게임종료\n"
+ "1. 전투시작\n"
+ "2. 전체 상태 출력\n"
+ "3. 울음소리 듣기\n"
+ "4. 포켓몬 잡기\n"
+ "===================");
System.out.println();
while (true) {
System.out.print("메뉴를 입력해주세요 : ");
menu = sc.nextInt();
if (menu >= 0 && menu <= 4) {
break;
}
else{
System.out.println("잘못된 입력입니다.");
System.out.print("다시 입력하세요 >>");
continue;
}
}
if (menu == 0) {
System.out.println("게임을 종료합니다.");
break;
}
else if (menu == 1) {//전투
if(isEmpty(cnt)) {
continue;
}
while (true) {
System.out.println("====================");
System.out.println("함께할 포켓몬을 골라주세요!");
System.out.println("====================");
for (int i = 0; i < cnt; i++) { // 현재 보유한 포켓몬 리스트 출력
System.out.println((i + 1) + ". " + myPokeList[i].name);
}
System.out.println("====================");
System.out.print("어떤 포켓몬을 선택하시겠습니까? 이름 옆 번호를 입력해주세요! : ");
int choice = sc.nextInt(); // 선택할 포켓몬 번호 입력
if (choice > 0 && choice <= cnt) { // 유효성 검사
Pokemon selectedPoke = myPokeList[choice - 1]; // (입력값 -1) 선택한 포켓몬 객체
System.out.println("선택한 포켓몬: " + selectedPoke.name);
System.out.println("이 포켓몬으로 공격하시겠습니까? (1: 공격 / 2: 포켓몬 선택 / 0: 종료)");
System.out.print("숫자 입력 : ");
int attPoke = sc.nextInt(); // 공격 여부 입력 받고
if (attPoke == 1) {
selectedPoke.attack(); // 공격 = 1
}
else if (attPoke == 2) {
System.out.println("포켓몬을 다시 선택합니다."); // 포켓몬 재선택 = 2
}
else if (attPoke == 0) {
System.out.println("전투를 종료합니다.");
break; // 1, 2 외의 답 = 게임종료 플래그
}
else {
System.out.println("잘못된 입력입니다. 다시 선택해주세요.");
}
}
else {
System.out.println("잘못된 입력입니다. 다시 선택해주세요."); // 유효성 검사
}
System.out.println("====================");
System.out.println("공격을 계속하시길 원하시면 '1'을 눌러주세요!");
System.out.println("숫자로 입력해주세요! 그 외의 답은 전투를 종료시킵니다!");
int again = sc.nextInt(); // 게임 계속 여부 입력
if (again != 1) { // 1 아닐때 반복 종료.
break; // 게임 종료 플래그 설정
}
}// 여기까지가 'while'반복문 걸리는 곳.
System.out.println("전투를 종료합니다."); // 게임 종료 메시지
}
else if (menu == 2) {//가지고 있는 전체 포켓몬 정보
if(isEmpty(cnt)) {
continue;
}
for(int i=0;i<cnt;i++) {
System.out.println(myPokeList[i]);
}
}
else if (menu == 3) {//선택한 포켓몬 울음소리 출력
if(isEmpty(cnt)) {
continue;
}
//울음소리 출력
System.out.println("포켓몬 이름을 입력하세요");
String findName = sc.next();
boolean found = false;
for (int i = 0; i < cnt; i++) {
if(findName.equals(myPokeList[i].name)) {
myPokeList[i].hello();// 중복출력 제거
found= true;
break;
}
}
if(!found) {
System.out.println("해당 포켓몬이 없어서 울지못해요");
}
}
else if (menu == 4) {
if(isFull(cnt, myPokeList)) {
continue;
}
int subMenu;//메뉴 입력값
Pokemon[] catchPoke = new Pokemon[5];
//메뉴로 제공할 포켓몬 5마리 리스트 만들기
//확률지정 myuProb + jyujyuProb + duduProb 총합 100이 되어야함
int myuProb = 2; //뮤 출현 확률
int jyujyuProb = 49; //쥬쥬 출현 확률
int duduProb = 49; //두두 출현 확률
int prob = 89; //잡기성공확률 지정 (0(완전불가)~100(무조건성공))
//확률 검증 (확률지정에 오류가 있다면 프로그램이 실행되지 않음)
if(!(myuProb + jyujyuProb + duduProb == 100)) {
//확률 총합이 100이 아니게 설정해놓았을 때 실행되는 코드 (개발자 확인용)
System.out.println("-===[오류발생]===-");
System.out.println("포켓몬 확률 지정에 오류가 있어 프로그램을 실행할 수 없습니다.");
System.out.println((myuProb + jyujyuProb + duduProb)+" != 100");
continue;
}
for(int i=0;i<catchPoke.length;i++) {//배열 길이만큼 반복하여 저장
int randNum = rand.nextInt(100);
//확률에 따라 두두 쥬쥬 뮤를 저장함
if(myuProb+jyujyuProb < randNum && randNum < 100) {//두두
catchPoke[i] = new Dudu();
}
else if(myuProb < randNum && randNum <= myuProb+jyujyuProb) {//쥬쥬
catchPoke[i] = new Jyujyu();
}
else if(0 <= randNum && randNum <= myuProb) {//뮤
catchPoke[i] = new Myu();
}
}//for(int i=0;i<catchPoke.length;i++)
while(true) {//올바른 값을 입력받을 때까지 입력값을 반복하는 반복문
System.out.println("☆*: .。. _ .。.:*☆");
for(int i=0; i<catchPoke.length; i++) {
System.out.println((i+1)+". "+catchPoke[i].name+", "+catchPoke[i].type+" 타입");
}
System.out.println("☆*: ˙\"˙ - ˙\"˙:*☆");
System.out.println("0. 메뉴로 돌아가기");
System.out.print("번호 선택 >> ");
subMenu = sc.nextInt();//메뉴 입력값 받기
if(subMenu == 0) {// 메뉴로 돌아가기
break;
}
else if (1<= subMenu && subMenu <= catchPoke.length){ //출현한 포켓몬 수의 범위
int randNum = rand.nextInt(100);
if(randNum < prob) {//잡는데 성공함!!
myPokeList[cnt++] = catchPoke[subMenu-1];
System.out.println(catchPoke[subMenu-1]+" 을 잡았습니다!");
break;
}
else {//잡는데 실패함
System.out.println(catchPoke[subMenu-1]+" 을 놓쳤습니다...");
break;
}
}
else { //메뉴 외의 입력값
System.out.println("올바른 입력값을 입력해주세요.");
}
}//while
//포켓몬 잡기 종료
}
}
}
}
[후기]
포켓몬 잡기를 할 때 선택지부터 new연산자를 사용해 객체로 보여주기 때문에 메모리를 낭비하는 부분이 있었다.
이 부분을 프로젝트 마무리 전에 보완할 수 있었다면 좋았을 것 같다.
포켓몬 게임에 대해서도 좀 더 연구했다면 더 좋은 결과물을 낼 수 있었을 것 같다.
'Project' 카테고리의 다른 글
[Team/붕어빵원정대(중중프)] 테이블 설계 (0) | 2024.08.25 |
---|---|
[Team] 알흠 프로젝트 (0) | 2024.08.02 |
[Team] 쇼핑몰 프로그램 만들기 (2) | 2024.07.24 |
[Personal/클론코딩] 숨고 : 숨은 고수 홈페이지 클론코딩 (0) | 2024.07.06 |
[Team] UpDown 게임 만들기 (0) | 2024.06.29 |