명품 JAVA Programming 제5강 자바 기본 프로그래밍 실습문제
Programming Language/Java

명품 JAVA Programming 제5강 자바 기본 프로그래밍 실습문제

728x90

[1~2] 다음 TV 클래스가 있다.

class TV {
	private int size;
	public TV(int size) { this.size=size; }
	protected int getSize() { return size; }
}

 

1. 다음 main( ) 메소드와 실행 결과를 참고하여 TV를 상속받은 ColorTV 클래스를 작성하라.

public static void main(String[] args) {
	ColorTV myTV=new ColorTV(32, 1024);
	myTV.printProperty();
}
--출력--
32인치 1024컬러

public class ColorTV extends TV {
	private int color;
	public ColorTV(int size, int color) {
		super(size);
		this.color=color;
	}
	void printProperty() {
		System.out.println(getSize()+"인치 "+color+"컬러");
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		ColorTV myTV=new ColorTV(32, 1024);
		myTV.printProperty();
	}

}

 

 

2. 다음 main( ) 메소드와 실행 결과를 참고하여 문제 1의 ColorTV를 상속받는 IPTV 클래스를 작성하라.

public static void main(String[] args) {
	IPTV iptv=new IPTV("192.1.1.2",32,2048); //"192.1.1.2" 주소에 32인치, 2048컬러
	iptv.printProperty();
}
--출력--
나의 IPTV는 192.1.1.2 주소의 32인치 2048컬러

public class IPTV extends ColorTV{
	private String address;
	public IPTV (String address,int size,int color) {
		super(size,color);
		this.address=address;
	}
	void printProperty() {
		System.out.print("나의 IPTV는 "+address+" 주소의 ");
		super.printProperty();
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		IPTV iptv=new IPTV("192.1.1.2",32,2048);
		iptv.printProperty();
	}

}

 

 

[3~4] 다음은 단위를 변환하는 추상 클래스 Converter이다.

import java.util.Scanner;
abstract class Converter {
	abstract protected double convert(double src); // 추상 메소드
	abstract protected String getSrcString(); // 추상 메소드
	abstract protected String getDestString(); // 추상 메소드
	protected double ratio; // 비율
	
	public void run() {
		Scanner scanner=new Scanner(System.in);
		System.out.println(getSrcString()+"을 "+getDestString()+" 로 바꿉니다.");
		System.out.print(getSrcString()+"을 입력하세요>> ");
		double val=scanner.nextDouble();
		double res=convert(val);
		System.out.println("변환 결과: "+res+getDestString()+"입니다");
		scanner.close();
	}
}

 

3. Converter 클래스를 상속받아 원화를 달러로 변환하는 Won2Dollar 클래스를 작성하라. main( ) 메소드와 실행 결과는 다음과 같다.

public static void main(String[] args) {
	Won2Dollar toDollar=new Won2Dollar(1200); // 1달러는 1200원
	toDollar.run();
}
--출력--
원을 달러 로 바꿉니다.
원을 입력하세요>> 24000
변환 결과: 20.0달러입니다

public class Won2Dollar extends Converter {

	protected double convert(double src) { return src/ratio; }
	protected String getSrcString() { return "원"; }
	protected String getDestString() { return "달러"; }
	Won2Dollar(double ratio) { this.ratio=ratio; }
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Won2Dollar toDollar=new Won2Dollar(1200);
		toDollar.run();
	}

}

 

 

4. Converter 클래스를 상속받아 Km를 mile(마일)로 변환하는 Km2Mile 클래스를 작성하라. main( ) 메소드와 실행 결과는 다음과 같다.

public static void main(String[] args) {
	Km2Mile toMile=new Km2Mile(1.6); // 1마일은 1.6Km
	toMile.run();
}
--출력--
Km을 mile 로 바꿉니다.
Km을 입력하세요>> 30
변환 결과: 18.75mile입니다

public class Km2Mile extends Converter {

	protected double convert(double src) { return src/ratio; }
	protected String getSrcString() { return "Km"; }
	protected String getDestString() { return "mile"; }
	Km2Mile (double ratio) { this.ratio=ratio; }
    
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Km2Mile toMile=new Km2Mile(1.6);
		toMile.run();
	}

}

 

 

[5~8] 다음은 2차원 상의 한 점을 표현하는 Point 클래스이다.

class Point {
	private int x,y;
	public Point(int x, int y) {this.x=x; this.y=y;}
	public int getX() {return x;}
	public int getY() {return y;}
	protected void move(int x, int y) { this.x=x; this.y=y;}
}

 

5. Point를 상속받아 색을 가진 점을 나타내는 ColorPoint 클래스를 작성하라. 다음 main( ) 메소드를 포함하고 실행 결과와 같이 출력되게 하라.

public static void main(String[] args) {
	ColorPoint cp=new ColorPoint(5,5,"YELLOW");
	cp.setXY(10,20);
	cp.setColor("RED");
	String str=cp.toString();
	System.out.println(str+"입니다.");
}
--출력--
RED색의 (10,20)의 점입니다.

public class ColorPoint extends Point {

	private String color;
	
	ColorPoint (int x, int y, String color) {
		super(5,5);
		this.color=color;
	}
	
	void setXY(int x, int y) {move(x,y);}	
	void setColor(String color) {this.color=color;}
	public String toString() {
		return (color+"색의 ("+getX()+","+getY()+")의 점");
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		ColorPoint cp=new ColorPoint(5,5,"YELLOW");
		cp.setXY(10,20);
		cp.setColor("RED");
		String str=cp.toString();
		System.out.println(str+"입니다.");
	}
}

 

 

6. Point를 상속받아 색을 가진 점을 나타내는 ColorPoint 클래스를 작성하라. 다음 main( ) 메소드를 포함하고 실행 결과와 같이 출력되게 하라.

public static void main(String[] args) {
	ColorPoint zeroPoint=new ColorPoint(); // (0,0) 위치의 BLACK 색 점
	System.out.println(zeroPoint.toString()+"입니다.");
		
	ColorPoint cp=new ColorPoint(10,10); // (10,10) 위치의 BLACK 색 점
	cp.setXY(5,5);
	cp.setColor("RED");
	System.out.println(cp.toString()+"입니다.");
}
--출력--
BLACK색의 (0,0)의 점입니다.
RED색의 (5,5)의 점입니다.

public class ColorPoint extends Point {
	private String color;
	
	ColorPoint() {
		super(0,0);
		this.color="BLACK";
	}
	
	ColorPoint(int x,int y) {
		super(10,10);
		this.color="BLACK";
	}
	
	public String toString() {
		return (color+"색의 ("+getX()+","+getY()+")의 점");
	}
	void setXY(int x, int y) {move(x,y);}
	void setColor(String color) {this.color=color;}
	
	public static void main(String[] args) {
		ColorPoint zeroPoint=new ColorPoint();
		System.out.println(zeroPoint.toString()+"입니다.");
		
		ColorPoint cp=new ColorPoint(10,10);
		cp.setXY(5,5);
		cp.setColor("RED");
		System.out.println(cp.toString()+"입니다.");
	}
}

 

 

7. Point를 상속받아 3차원의 점을 나타내는 Point3D 클래스를 작성하라. 다음 main( ) 메소드를 포함하고 실행 결과와 같이 출력되게 하라.

public static void main(String[] args) {
	Point3D p=new Point3D(1,2,3); // 1, 2, 3은 각각 x, y, z축의 값.
	System.out.println(p.toString()+"입니다.");
		
	p.moveUp(); // z 축으로 위쪽 이동
	System.out.println(p.toString()+"입니다.");
		
	p.moveDown(); // z 축으로 아래쪽 이동
	p.move(10, 10); // x, y 축으로 이동
	System.out.println(p.toString()+"입니다.");
		
	p.move(100, 200, 300); // x, y, z 축으로 이동
	System.out.println(p.toString()+"입니다.");
	}
--출력--
(1,2,3)의 점입니다.
(1,2,4)의 점입니다.
(10,10,3)의 점입니다.
(100,200,300)의 점입니다.

public class Point3D extends Point{

	private int z;
	
	Point3D(int x, int y, int z) {
		super(x,y);
		this.z=z;
	}
	
	public String toString() {
		return ("("+getX()+","+getY()+","+this.z+")의 점");
	}
	
	public void moveUp() {
		this.z++;
	}
	
	public void moveDown() {
		this.z--;
	}
	
	protected void move(int x, int y, int z) { 
		super.move(x,y);
		this.z=z;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Point3D p=new Point3D(1,2,3);
		System.out.println(p.toString()+"입니다.");
		
		p.moveUp();
		System.out.println(p.toString()+"입니다.");
		
		p.moveDown();
		p.move(10, 10);
		System.out.println(p.toString()+"입니다.");
		
		p.move(100, 200, 300);
		System.out.println(p.toString()+"입니다.");
	}

}

 

 

8. Point를 상속받아 양수의 공간에서만 점을 나타내는 PositivePoint 클래스를 작성하라. 다음 main( ) 메소드를 포함하고 실행 결과와 같이 출력되게 하라.

public static void main(String[] args) {
	PositivePoint p= new PositivePoint();
	p.move(10,10);
	System.out.println(p.toString()+"입니다.");
		
	p.move(-5, 5); // 객체 p는 음수 공간으로 이동되지 않음
	System.out.println(p.toString()+"입니다.");
		
	PositivePoint p2=new PositivePoint(-10, -10);
	System.out.println(p2.toString()+"입니다.");
}
--출력--
(10,10)의 점입니다.
(10,10)의 점입니다.
(0,0)의 점입니다.

 

힌트 :

Point 클래스의 move( )를 PositivePoint 클래스에서 오버라이딩하여 재작성하고 적절히 super.move( )를 호출해야 한다. PositivePoint의 2 개의 생성자에서도 적절히 super( ) 생성자와 super.move( )를 호출해야 한다.


public class PositivePoint extends Point {

	PositivePoint () {
		super(0,0);
	}
	
	PositivePoint(int x, int y) {
		super(0,0);
		move(x, y);
	}
	
	public String toString() {
		int x=getX();
		int y=getY();
		String str="("+x+","+y+")의 점";
		return str;
	}
	
	@Override
	protected void move(int x, int y) {
		if ((x>0)&&(y>0))
			super.move(x, y);
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		PositivePoint p= new PositivePoint();
		p.move(10,10);
		System.out.println(p.toString()+"입니다.");
		
		p.move(-5, 5);
		System.out.println(p.toString()+"입니다.");
		
		PositivePoint p2=new PositivePoint(-10, -10);
		System.out.println(p2.toString()+"입니다.");
	}

}
728x90

9. 다음 Stack 인터페이스를 상속받아 실수를 저장하는 StringStack 클래스를 구현하라.

public interface Stack {
	int length(); //현재 스택에 저장된 개수 리턴
	int capacity(); //스택의 전체 저장 가능한 개수 리턴
	String pop(); //스택의 톱(top)에 저장된 문자열 리턴
	boolean push (String val); //스택의 톱(top)에 문자열 저장
}

내 생각 :

pop과 push 메소드에 달린 주석이 이상하다.
원래 주석은
//pop은 스택의 톱(top)에 실수 저장
//push는 스택의 톱(top)에  저장된 실수 리턴

 

그리고 다음 실행 사례와 같이 작동하도록 StackApp 클래스에 main( ) 메소드를 작성하라.

--출력--
총 스택 저장 공간의 크기 입력 >>3
문자열 입력 >> hello
문자열 입력 >> sunny
문자열 입력 >> smile
문자열 입력 >> happy
스택이 꽉 차서 푸시 불가!
문자열 입력 >> 그만
스택에 저장된 모든 문자열 팝 :smile sunny hello 

import java.util.Scanner;

public class StackApp implements Stack{
	private int top=0;
	private String arr[];
	
	StackApp(int size) {arr=new String[size];}
	
	@Override
	public int length() {return top;}
	
	@Override
	public int capacity() {return arr.length;}
	
	@Override
	public String pop() {
		String val;
		if (top==0)
			val="0";
		else {
			top--;
			val=arr[top];
		}
		return val;
	}
	
	@Override
	public boolean push (String val) {
		if (top==arr.length)
			return false;
		else {
			arr[top]=val;
			top++;
			return true;
		}
	}
	
	void run() {
		Scanner scan=new Scanner(System.in);
		
		while(true) {
			System.out.print("문자열 입력 >> ");
			String val=scan.next();
			if (val.equals("그만"))
				break;
			else {
				boolean bool=push(val);
				if (bool==false)
					System.out.println("스택이 꽉 차서 푸시 불가!");
			}
		}
		
		System.out.print("스택에 저장된 모든 문자열 팝 :");
		while (true) {
			String val=pop();
			if (val.equals("0")) {
				System.out.println();
				break;
			}
			else
				System.out.print(val+" ");
		}
	}
		
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		Scanner scan=new Scanner(System.in);
		
		System.out.print("총 스택 저장 공간의 크기 입력 >>");
		int size=scan.nextInt();
		StackApp sa=new StackApp(size);
		sa.run();
	}

}

 

 

10. 다음은 키와 값을 하나의 아이템으로 저장하고 검색 수정이 가능한 추상 클래스가 있다.

abstract class PairMap {
	protected String keyArray []; //key 들을 저장하는 배열
	protected String valueArray []; //value 들을 저장하는 배열
	abstract String get(String key); //key 값을 가진 value를 리턴, 없으면 null 리턴
	abstract void put(String key, String value); //key와 value를 쌍으로 저장. 기존에 key가 있으면, 값을 value로 수정
	abstract String delete(String key); //key 값을 가진 아이템(value와 함께) 삭제. 삭제된 value 값 리턴
	abstract int length(); //현재 저장된 아이템 개수 리턴
}

PairMap을 상속받는 Dictionary 클래스를 구현하고, 이를 다음과 같이 활용하는 main( ) 메소드를 가진 클래스 DictionaryApp도 작성하라.

public static void main(String[] args) {
	Dictionary dic=new Dictionary(10);
	dic.put("황기태", "자바");
	dic.put("이재문", "파이선");
	dic.put("이재문", "C++"); //이재문의 값을 C++로 수정
	System.out.println("이재문의 값은 "+dic.get("이재문"));
	System.out.println("황기태의 값은 "+dic.get("황기태"));
	dic.delete("황기태"); //황기태 아이템 삭제
	System.out.println("황기태의 값은 "+dic.get("황기태")); //삭제된 아이템 접근
}
--출력--
이재문의 값은 C++
황기태의 값은 자바
황기태의 값은 null

public class Dictionary extends PairMap {
	
	Dictionary(int arrLength) {
		keyArray=new String[arrLength];
		valueArray=new String[arrLength];
		
		for(int i=0;i<arrLength;i++) {
			keyArray[i]="null"; /*나중에 keyArray의 값과 입력 받은 key의 값을 비교하기 위해서 
            					      "null" 문자열로 초기화해준다.*/
			valueArray[i]="null";
		}
	}

	@Override
	public String get(String key) {
		String ans="null";
		for (int i=0;i<keyArray.length;i++)
			if (keyArray[i].equals(key))
				ans=valueArray[i];
		return ans;
	}
	
	@Override
	public void put(String key, String value) {
		int i;
		for (i=0;i<keyArray.length;i++)
			if (keyArray[i].equals(key)) { //기존의 key 값이 있는 경우
				valueArray[i]=value;
				break;
			}
		if (i==keyArray.length) {//기존의 key 값이 없는 경우
			int j;
			for (j=0;j<keyArray.length;j++)
				if (keyArray[j].equals("null")) { //배열에 남은 공간이 있으면 저장
					keyArray[j]=key;
					valueArray[j]=value;
					break;
				}
			if (j==keyArray.length) /*배열에 남은 공간이 없으면
            						    (문제에서 제시한 main메소드 대로 구현한다면 필요없는 조건)*/
				System.out.println("Dictionary full");
		}
	}
	
	@Override
	public String delete(String key) {
		String str="null";
		for (int i=0;i<keyArray.length;i++)
			if (keyArray[i].equals(key)) {
				str=valueArray[i];
				keyArray[i]="null";
				valueArray[i]="null";
			}
		return str;
	}
	
	@Override
	public int length() {
		int count=0;
		for (int i=0;i<keyArray.length;i++) {
			if (keyArray[i].equals(null)); //null 상태면 그냥 넘어감
			else //뭔가 저장되어 있으면 count를 늘려준다
				count++; 
		}
		return count;
	}
}
public class DictionaryApp {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Dictionary dic=new Dictionary(10);
		dic.put("황기태", "자바");
		dic.put("이재문", "파이선");
		dic.put("이재문", "C++"); //이재문의 값을 C++로 수정
		System.out.println("이재문의 값은 "+dic.get("이재문"));
		System.out.println("황기태의 값은 "+dic.get("황기태"));
		dic.delete("황기태"); //황기태 아이템 삭제
		System.out.println("황기태의 값은 "+dic.get("황기태")); //삭제된 아이템 접근
	}

}

 

11. 철수 학생은 다음 3개의 필드와 메소드를 가진 4개의 클래스 Add, Sub, Mul, Div를 작성하려고 한다(4장 실습문제 11 참고)

  • int 타입의 a, b 필드: 2개의 피연산자
  • void setValue(int a, int b): 피연산자 값을 객체 내에 저장한다.
  • int calculate( ): 클래스의 목적에 맞는 연산을 실행하고 결과를 리턴한다.

곰곰 생각해보니, Add, Sub, Mul, Div 클래스에 공통된 필드와 메소드가 존재하므로 새로운 추상 클래스 Calc를 작성하고 Calc를 상속받아 만들면 되겠다고 생각했다. 그리고 main( ) 메소드에서 다음 실행 사례와 같이 2개의 정수와 연산자를 입력받은 후, Add, Sub, Mul, Div 중에서 이 연산을 처리할 수 있는 객체를 생성하고 setValue( )와 calculate( )를 호출하여 그 결과 값을 화면에 출력하면 된다고 생각하였다. 철수처럼 프로그램을 작성하라.

--출력--
두 정수와 연산자를 입력하시오>>5 7 +
12

abstract class Calc {
	protected int a;
	protected int b;
	abstract void setValue(int a, int b);
	abstract int calculate();
}
class Add extends Calc {
	Add(int a, int b) {setValue(a,b);}
	
	public void setValue(int a, int b) {this.a=a; this.b=b;}
	
	public int calculate() {return a+b;}
}
class Sub extends Calc {
	Sub(int a, int b) {setValue(a,b);}
	
	public void setValue(int a, int b) {this.a=a; this.b=b;}
	
	public int calculate() {return a-b;}
}
class Mul extends Calc {
	Mul(int a, int b) {setValue(a,b);}
	
	public void setValue(int a, int b) {this.a=a; this.b=b;}
	
	public int calculate() {return a*b;}
}
class Div extends Calc {
	Div(int a, int b) {setValue(a,b);}
	
	public void setValue(int a, int b) {this.a=a; this.b=b;}
	
	public int calculate() {return a/b;}
}
import java.util.Scanner;

public class Calculater {

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		Scanner scan=new Scanner(System.in);
		
		System.out.print("두 정수와 연산자를 입력하시오>>");
		int a=scan.nextInt();
		int b=scan.nextInt();
		String oper=scan.next();
		
		switch (oper) {
		case "+":
			Add add=new Add(a,b);
			System.out.println(add.calculate());
			break;
		case "-":
			Sub sub=new Sub(a,b);
			System.out.println(sub.calculate());
			break;
		case "*":
			Mul mul=new Mul(a,b);
			System.out.println(mul.calculate());
			break;
		case "/":
			Div div=new Div(a,b);
			System.out.println(div.calculate());
			break;
		}
	}

}

 

 

12. 텍스트로 입출력하는 간단한 그래픽 편집기를 만들어보자. 본문 5.6절과 5.7절에서 사례로 든 추상 클래스 Shape과 Line, Rect, Circle 클래스 코드를 잘 완성하고 이를 활용하여 아래 시행 예시처럼 "삽입", "삭제", "모두 보기", "종료"의 4가지 그래픽 편집 기능을 가진 클래스 GraphicEditor을 작성하라.

--출력--
그래픽 에디터 beauty을 실행합니다.
삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>1
Line(1), Rect(2), Circle(3)>>2
삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>1
Line(1), Rect(2), Circle(3)>>3
삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>3
Rect
Circle
삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>2
삭제할 도형의 위치>>3
삭제할 수 없습니다.
삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>4
beauty을 종료합니다.

 

힌트 :

Shape을 추상 클래스로 작성한 사례는 다음과 같다. 

public abstract class Shape {
	private Shape next;
	public Shape() {next=null;}
	public void setNext(Shape obj) {next=obj;} // 링크 연결
	public Shape getNext() {return next;}
	public abstract void draw(); // 추상 메소드
}

class Line extends Shape {
	public void draw() {System.out.println("Line");}
}

class Rect extends Shape {
	public void draw() {System.out.println("Rect");}
}

class Circle extends Shape {
	public void draw() {System.out.println("Circle");}
}
import java.util.Scanner;

public class GraphicEditor {
	static int count=0;
	Shape start, last, obj, next_obj;
	
	void insert() {
		Scanner scan=new Scanner(System.in);
		System.out.print("Line(1), Rect(2), Circle(3)>>");
		int c=scan.nextInt();
		
		if (count==0) {
			if (c==1)
				start=new Line();
			else if (c==2)
				start=new Rect();
			else
				start=new Circle();
			last=start;
		}
		else {
			if (c==1)
				obj=new Line();
			else if (c==2)
				obj=new Rect();
			else
				obj=new Circle();
			last.setNext(obj);
			last=obj;
		}
		count++; //몇 번째 삽입인지 알 수 있음.
	}
	
	void delete() {
		Scanner scan=new Scanner(System.in);
		System.out.print("삭제할 도형의 위치>>");
		int order=scan.nextInt();
		
		if (order>count)
			System.out.println("삭제할 수 없습니다.");
		else {
			if (order==1) {//첫번째 그래픽을 삭제할 경우
				if (last==start)//그래픽이 하나 밖에 없을 경우
					last=start=null;
				else //그래픽이 한개 이상일 경우
					start=start.getNext();
			}
			else if (order==count) { //마지막 그래픽을 삭제할 경우
				obj=start;
				next_obj=obj.getNext();
				for (int i=2;i<order;i++) {
					obj=next_obj;
					next_obj=next_obj.getNext();
				}
				obj.setNext(null);
			}
			else {//첫번째나 마지막이 아닌 그래픽을 삭제할 경우
				obj=start;
				next_obj=obj.getNext();
				for (int i=2;i<order;i++) {
					obj=next_obj;
					next_obj=next_obj.getNext();
				}
				obj.setNext(next_obj.getNext());
			}
			count--;
		}
	}
	
	void printAll() {
		if (count==0)
			System.out.println("나타낼 그래픽이 존재하지 않습니다.");
		else if (count==1)
			start.draw();
		else {
			start.draw();
			obj=start.getNext();
			for (int i=2;i<count;i++) {
				obj.draw();
				obj=obj.getNext();
			}
			obj.draw();
		}
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner scan=new Scanner(System.in);
		int test=1;
		int c=0;
		
		System.out.println("그래픽 에디터 beauty을 실행합니다.");
		GraphicEditor ge=new GraphicEditor();
		
		while (test==1) {
			System.out.print("삽입(1), 삭제(2), 모두 보기(3), 종료(4)>>");
			c=scan.nextInt();
			
			switch (c) {
			case 1:
				ge.insert();
				break;
			case 2:
				ge.delete();
				break;
			case 3:
				ge.printAll();
				break;
			case 4:
				System.out.println("beauty을 종료합니다.");
				test=0;
				break;
			}
		}
	}

}

 

내 생각 :

이 문제는 구조를 딱 잡고 풀지 못했다.
클래스들 상속받고 insert 메소드까지만 처음부터 구조를 잡고 풀 수 있었고,
delete메소드나 printAll 메소드는 출력 값 보고 왜 이렇게 나오는지 생각하면서 조금조금씩 고쳐서 풀었다.
그래서 코드도 가독성이 좋지 못하고 엉망진창인 감이 없지 않아 있는데...
그래도 다 수정하고 난 뒤에 구조를 어느 정도 이해하고 원하는 대로 돌아가는 것만으로 일단 만족.
일단 전체적인 구조는 linked list로 생각하고 구현하면 된다.
각 노드를 연결하는 insert 메소드와 첫번째 노드, 중간 노드, 마지막 노드를 삭제해주는 delete 메소드도 linked list를 구현할 때 쓰는 알고리즘을 사용하면 된다.

 

 

13. 다음은 도형의 구성을 묘사하는 인터페이스이다.

interface Shape {
	final double PI = 3.14; //상수
	void draw(); //도형을 그리는 추상 메소드
	double getArea(); //도형의 면적을 리턴하는 추상 메소드
	default public void redraw() { //디폴트 메소드
		System.out.print("--- 다시 그립니다. ");
		draw();
	}
}

다음 main( ) 메소드와 실행 결과를 참고하여, 인터페이스 Shape을 구현한 클래스 Circle를 작성하고 전체 프로그램을 완성하라.

public static void main(String[] args) {
		Shape donut=new Circle(10); // 반지름이 10인 원 객체
		donut.redraw();
		System.out.println("면적은 "+donut.getArea());
	}
--출력--
--- 다시 그립니다. 반지름이 10인 원입니다.
면적은 314.0

public class Circle implements Shape {
	private int radius;
	private double area;
	
	Circle (int radius) {
		this.radius=radius;
		area=this.radius*this.radius*PI;
	}
	
	public void draw() {
		System.out.println("반지름이 "+radius+"인 원입니다.");
	}
	
	public double getArea() {
		return area;
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Shape donut=new Circle(10);
		donut.redraw();
		System.out.println("면적은 "+donut.getArea());
	}

}

 

 

14. 다음 main( ) 메소드와 실행 결과를 참고하여, 문제 13의 Shape 인터페이스를 구현한 클래스 Oval, Rect를 추가 작성하고 전체 프로그램을 완성하라.

public static void main(String[] args) {
	Shape [] list= new Shape[3]; // Shape을 상속받은 클래스 객체의 래퍼런스 배열
	list[0]= new Circle(10); // 반지름이 10인 원 객체
	list[1]= new Oval(20, 30); // 20x30 사각형에 내접하는 타원
	list[2]= new Rect(10, 40); // 10x40 크기의 사각형
		
	for (int i=0; i<list.length; i++) list[i].redraw();
	for (int i=0; i<list.length;i++) System.out.println("면적은 "+list[i].getArea());
}
--출력--
--- 다시 그립니다. 반지름이 10인 원입니다.
--- 다시 그립니다. 20x30에 내접하는 타원입니다.
--- 다시 그립니다. 10x40크기의 사각형 입니다.
면적은 314.0
면적은 1884.0
면적은 400.0

public class Oval implements Shape {
	private int radius1;
	private int radius2;
	private double area;
	
	Oval (int radius1, int radius2) {
		this.radius1=radius1;
		this.radius2=radius2;
		area=radius1*radius2*PI;
	}
	
	public void draw() {
		System.out.println(radius1+"x"+radius2+"에 내접하는 타원입니다.");
	}
	
	public double getArea() {return area;}
}
public class Rect implements Shape {
	private int width;
	private int height;
	private double area;
	
	Rect (int width, int height) {
		this.width=width;
		this.height=height;
		area=this.width*this.height;
	}
	
	public void draw() {
		System.out.println(width+"x"+height+"크기의 사각형 입니다.");
	}
	
	public double getArea() {return area;}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Shape [] list= new Shape[3];
		list[0]= new Circle(10);
		list[1]= new Oval(20, 30);
		list[2]= new Rect(10, 40);
		
		for (int i=0; i<list.length; i++)
			list[i].redraw();
		for (int i=0; i<list.length;i++)
			System.out.println("면적은 "+list[i].getArea());
	}

}

 

 

Open Challenge Bear의 Fish 먹기 게임 만들기

이 게임에는 Bear와 Fish 객체가 등장하며, 이들은 10행 20열의 격자판에서 각각 정해진 규칙에 의해 움직인다. Bear는 사용자의 키에 의해 왼쪽(a 키), 아래(s 키), 위(d 키), 오른쪽(f 키)으로 한 칸씩 움직이고, Fish는 다섯 번 중 세 번은 제자리에 있고, 나머지 두 번은 4가지 방향 중 랜덤 하게 한 칸씩 움직인다. 게임은 Bear가 Fish를 먹으면(Fish의 위치로 이동) 성공으로 끝난다. 다음은 각 객체의 이동을 정의하는 move( )와 각 객체의 모양을 정의하는 getShape( )을 추상 메소드로 가진 추상 클래스 GameObject이다. GameObject를 상속받아 Bear와 Fish 클래스를 작성하라. 그리고 전체적인 게임을 진행하는 Game 클래스와 main( ) 함수를 작성하고 프로그램을 완성하라.

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와 Fish 객체의 move( )가 순서대로 호출된다. 게임이 진행되는 과정은 다음 그림과 같으며, 게임의 종료 조건에 일치하면 게임을 종료한다.

--출력--
** Bear의 Fish 먹기 게임을 시작합니다.**
B---------
----------
----------
----------
----------
-----@----
----------
----------
----------
----------
왼쪽(a), 아래(s), 위(d), 오른쪽(f) >> s
----------
B---------
----------
----------
----------
-----@----
----------
----------
----------
----------
왼쪽(a), 아래(s), 위(d), 오른쪽(f) >> s
----------
----------
B---------
----------
----------
-----@----
----------
----------
----------
----------
왼쪽(a), 아래(s), 위(d), 오른쪽(f) >> s
<------------------------------------------------------중간 과정 생략------------------------------------------------------>
----------
----------
----------
----------
-----B@---
----------
----------
----------
----------
----------
왼쪽(a), 아래(s), 위(d), 오른쪽(f) >> f
----------
----------
----------
----------
------B---
----------
----------
----------
----------
----------
Bear wins!!

// 출력은 Fish가 랜덤으로 바뀌기 때문에 매번 다르다.


public class Bear extends GameObject {
	Scanner scan=new Scanner(System.in);
	Bear() {
		super(1,1,1);
	}
	
	@Override
	protected void move() {
		while (true) {
			System.out.print("왼쪽(a), 아래(s), 위(d), 오른쪽(f) >> ");
			String direction=scan.next(); //방향 입력
			switch (direction) {
			case "a": //왼쪽
				if (x>1) {
					x-=distance;
					break;
				}
				else { //x=1이라면 왼쪽으로 갈 수 없음
					System.out.println("더 이상 왼쪽으로 갈 수 없습니다. 다시 입력하세요.");
					scan.nextLine(); //scanner를 비워준다.
					continue;
				}
			case "s": //아래
				if (y<10) {
					y+=distance;
					break;
				}
				else { //y=10이라면 아래쪽으로 갈 수 없음
					System.out.println("더 이상 아래쪽으로 갈 수 없습니다. 다시 입력하세요.");
					scan.nextLine();
					continue;
				}
			case "d": //위
				if (y>1) {
					y-=distance;
					break;
				}
				else { //y=1이라면 위쪽으로 갈 수 없음
					System.out.println("더 이상 위쪽으로 갈 수 없습니다. 다시 입력하세요.");
					scan.nextLine();
					continue;
				}
			case "f": //오른쪽
				if (x<10) {
					x+=distance;
					break;
				}
				else { //x=10이라면 오른쪽으로 갈 수 없음
					System.out.println("더 이상 오른쪽으로 갈 수 없습니다. 다시 입력하세요.");
					continue;
				}
			}
			break;
		}
	}
	
	@Override
	protected char getShape() {
		return 'B';
	}
}
import java.util.*;

public class Fish extends GameObject {
	Fish() {
		super(6,6,1);
	}
	
	@Override
	protected void move() {
		while (true) {
			int ran=(int)(Math.random()*4);
			switch (ran) {
			case 0: //왼쪽
				if (x>1) {
					x-=distance;
					break;
				}
				else { //x=1이라면 왼쪽으로 갈 수 없음
					System.out.println("더 이상 왼쪽으로 갈 수 없습니다. 다시 입력하세요.");
					continue;
				}
			case 1: //아래
				if (y<10) {
					y+=distance;
					break;
				}
				else { //y=10이라면 아래쪽으로 갈 수 없음
					System.out.println("더 이상 아래쪽으로 갈 수 없습니다. 다시 입력하세요.");
					continue;
				}
			case 2: //위
				if (y>1) {
					y-=distance;
					break;
				}
				else { //y=1이라면 위쪽으로 갈 수 없음
					System.out.println("더 이상 위쪽으로 갈 수 없습니다. 다시 입력하세요.");
					continue;
				}
			case 3: //오른쪽
				if (x<10) {
					x+=distance;
					break;
				}
				else { //x=10이라면 오른쪽으로 갈 수 없음
					System.out.println("더 이상 오른쪽으로 갈 수 없습니다. 다시 입력하세요.");
					continue;
				}
			}
			break;
		}
	}
	
	@Override
	protected char getShape() {
		return '@';
	}
}
import java.util.*;

public class Game {
	Bear bear=new Bear();
	Fish fish=new Fish();
	
	void printMap() {
		for(int i=1;i<=10;i++) {
			for(int j=1;j<=10;j++) {
				if ((i==bear.getY())&&(j==bear.getX())) //bear shape 출력
					System.out.print(bear.getShape());
				else if ((i==fish.getY())&&(j==fish.getX())) { //fish shape 출력
					if (!bear.collide(fish)) /*bear.collide(fish)가 true라면 bear가 fish를 먹기 성공, 
                    							 fish shape은 출력하지 않는다.*/
						System.out.print(fish.getShape());
				}
				else
					System.out.print("-");
			}
			System.out.println();
		}
	}
	
	void playing() {
		System.out.println("** Bear의 Fish 먹기 게임을 시작합니다.**");
		printMap();
		while (true) {
			for (int i=1;i<=5;i++) {
				if ((i==4)||(i==5)) //5번 중 4,5번째 일 때는 fish도 move
					fish.move();
				bear.move(); //bear는 매번 move
				printMap();
				if (bear.collide(fish))
					break;
			}
			if (bear.collide(fish)) {
				System.out.println("Bear wins!!");
				break;
			}
		}
	}
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Game game=new Game();
		game.playing();
	}

}
728x90