웹프로그래밍/Java

Java 추상클래스를 이용하여 간단한 게임 만들기(1)

피노키오이 2020. 11. 16. 20:13
반응형

개요

 

이번에는 Java의 클래스를 이용하여 간단하게 콘솔로 움직이는 게임을 만들어 보도록 하겠습니다.

우선 Java의 추상 클래스인 GameObject 클래스를 만들어 보도록 하겠습니다.

개발하기에 앞서 간단하게 추상클래스가 무엇인지 알아보도록 하겠습니다.

 


추상 (abstract) 

시체들 간에 공통되는 특성을 추출한 것입니다.

예) 사자, 호랑이, 코끼리 -> 동물(추상)

예) 삼성, 현대, 애플, LG -> 회사(추상)

 

Java에서 추상 클래스는 new를 이용하여 인스턴스를 생성하지 못합니다.

 


그렇다면 추상클래스를 왜 사용하나?

 

추상 클래스의 용도

1. 상속 계층에서 자식 멤버의 이름을 통일하기 위하여 사용

실체 클래스 설계자가 여러 사람일 경우, 실체 클래스마다 필드와 메서드가 제각기 다른 이름을 가질 수 있다.

 

2. 실체 클래스를 작성할 때 시간 절약

실체 클래스는 추가적인 필드와 메소드만 선언합니다.

 

3. 실체 클래스 설계 규격을 만들고자 할 때

실체 클래스가 가져야 할 필드와 메소드를 추상 클래스에 미리 정의합니다.

실체 클래스는 추상 클래스를 무조건 상속 받아 작성합니다.

 


추상 클래스 선언 방법

 

클래스 선언에 abstract 키워드를 사용합니다.

필드와 메소드 포함 가능합니다.

자식 객체가 부모 생성자 super()를 호출할 수 있으므로 생성자도 포함 가능합니다.

abstract 키워드로 선언하고 실체 클래스처럼 public으로 지정할 수 있음

 

추상 메소드 선언

추상 메소드도 abstract 키워드 사용합니다.

실체가 없으므로 본체 없이 세미콜론(;)으로 끝납니다.

public이나 protected로 지정할 수 있습니다.

 

주의! 추상 클래스를 상속받은 자식 클래스는 부모의 추상 메서드를 반드시 구현해야 합니다.!

 


추상클래스를 이용하여 간단한 게임을 만들어 보도록 하겠습니다.

 


GameObject.class

 

public abstract class GameObject { // 추상 클래스
	protected int distance; // 한 번 이동 거리
	protected int x, y; // 현재 위치(화면 맵 상의 위치)
	
	public GameObject(int startX, int startY, int distance) { // 초기 위치와 이동 거리 설정
		this.x = startX; this.y = startY;
		this.distance = distance;
	}
	public int getX() { return x; }
	public int getY() { return y; }
	public boolean collide(GameObject p) { // 이 객체가 객체 p와 충돌했으면 true 리턴
		if(this.x == p.getX() && this.y == p.getY())
			return true;
		else 
			return false;
	}
	
	protected abstract void move(); // 이동한 후의 새로운 위치로 x, y 변경
	protected abstract char getShape(); // 객체의 모양을 나타내는 문자 리턴
}

 


Bear.class

 

import java.util.Scanner;

public class Bear extends GameObject {
	private Scanner scanner;
	public Bear(int x, int y, int distance) {
		super(x, y, distance);
		scanner = new Scanner(System.in);
	}
	
	@Override
	public void move() {
		System.out.print("왼쪽(a), 아래(s), 위(w), 오른쪽(d) >> ");
		char c;
		c = scanner.next().charAt(0);
		switch(c) {
			case 'a' : // left
				x--; 
				if(x < 0) x = 0;
				break;
			case 'd' : // right
				x++; 
				if(x >= Game.MAX_X) x = Game.MAX_X - 1;
				break;
			case 'w' : // up
				y--; 
				if(y < 0) y = 0;
				break;
			case 's' : // down
				y++; 
				if(y >= Game.MAX_Y) y = Game.MAX_Y - 1;
				break;
		}		
	}
	
	@Override
	public char getShape() { // Bear의 모양 리턴
		return 'B';
	}
}

 


Finish.class

 

public class Fish extends GameObject {
	public Fish(int x, int y, int distance) {
		super(x, y, distance); 
	}
	 
	@Override
	public void move() { // 한 번 움직이는 과정 전개
		int n = (int)(Math.random()*5); // 0,1,2,3,4 중에서 0인 경우 + 방향, 1인 경우 - 방향, 나머지 정지
		if(n==0) x += distance;
		else if(n==1) x -= distance;

		if(x < 0) x=0;
		if(x >= Game.MAX_X) x = Game.MAX_X - 1;
		 
		n = (int)(Math.random()*5);
		if(n==0) y += distance;
		else if(n==1) y -= distance;

		if(y < 0) y=0;
		if(y >= Game.MAX_Y) y= Game.MAX_Y - 1;
	}

	@Override
	public char getShape() { // Fish의 모양 리턴
		return '@';
	}
}

 


Game.class

 

public class Game {
	public static final int MAX_X = 20;
	public static final int MAX_Y = 10;
	private char map [][] = new char [MAX_Y][MAX_X];
	private GameObject [] m = new GameObject[2];
	int state; // 0: 게임 중, 1: Monster가 winner, 2:Human이 winner
	
	public Game() {
		for(int i=0; i<MAX_Y; i++) 
			for(int j=0; j<MAX_X; j++)
				map[i][j] = '-';
		m[0] = new Bear(0, 0, 1);
		m[1] = new Fish(5, 5, 2);
		state = 0; // 게임 중
	}
	public void run() {
		System.out.println("** Bear의 Fish 먹기 게임을 시작합니다.**");;

		update(); // 초기 좌표에 따른 맵 설정
		draw(); // 초기 게임 맵을 보여줌

		while(!doesEnd()) {
			clear(); // 현재의 맵 지움
			for(int i=0; i<m.length; i++) 
				m[i].move();
			update(); // 움직인 후 좌표 변경에 따른 맵 갱신
			draw(); // 맵 그리기
		}
		System.out.println("Bear Wins!!");;
	}
	private void update() {
		for(int i=m.length-1; i>=0; i--) // Fish부터 먼저 그려서 Fish를 먹는 경우 Fish가 보이지 않기
			map[m[i].getY()][m[i].getX()] = m[i].getShape();
	}
	private void clear() {
		for(int i=0; i<m.length; i++) 
			map[m[i].getY()][m[i].getX()] = '-';
	}
	private void draw() {
		System.out.println();
		for(int i=0; i<MAX_Y; i++) {
			for(int j=0; j<MAX_X; j++)
				System.out.print(map[i][j]);
			System.out.println();
		}
	}
	private boolean doesEnd() {
		if(m[0].collide(m[1])) {// Bear ate Fish
			return true;
		}
		return false;
	}
	
	public static void main(String[] args) {
		Game game = new Game();
		game.run();
	}

}

 


다음에는 이 게임을 수정해 나가면서 Java에 대해서 학습을 진행하도록 하겠습니다.

 


 

반응형