Ex) 연, 월, 일을 입력하면 태양계가 출력되도록 하라
- 태양, 지구, 달 외에 다른 행성, 인공 위성 등을 추가해도 된다.
Sol)
- Planet 클래스
- 2단계의 공전 클래스 메서드를 가져와서 조금만 수정했다.
- 지구는 검은 별, 달은 달 모양으로 표시한다.
- 은하수를 추가하는 메서드를 이용해서 은하수를 그린 다음에 태양, 지구, 달을 그린다.
- 태양, 지구, 달 그리는 메서드를 모두 따로 만들었다.
<hide/>
public class Planet {
static char[][] graph = new char[50][50];
static Set<Character> sunCharSet = Set.of('\\', '!', '/', 'O', '-', '|', '.', '*', 'Y', 'o',
'u', 'A', 'r', 'e', ' ', 'H', '"', 'V', '★', '☆', '☾', '☺', '○', '+'
);
static LocalDate enterDate;
static String tmpYear, tmpMonth, tmpDay;
static int year, month, day;
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
static ArrayList<String> milkyWayList = new ArrayList<>();
public static void addMilkyWayList1() {
milkyWayList.add(". + . . . . . .");
milkyWayList.add(" . . . *");
milkyWayList.add(" . * . . . . . . + .");
milkyWayList.add(" . . + . . .");
milkyWayList.add(" . . . . . . . .");
milkyWayList.add(" . . . +. + .");
milkyWayList.add(" . . . .");
milkyWayList.add(" . . . * . . . . + .");
milkyWayList.add(" + . . . + ");
milkyWayList.add(" . . + .+. . ");
milkyWayList.add(" . . . + . . . . .");
milkyWayList.add(" . . . . . . . . ");
milkyWayList.add(" * . . . + . . ");
milkyWayList.add(" . . . + . . * . . ");
milkyWayList.add(" . + . . . .. + .");
milkyWayList.add(". . . . * . * . +.. . * ");
milkyWayList.add(" . . . . . . . . + . . +");
milkyWayList.add(" . . . * . . . . + .");
}
public static void addMilkyWayList2() {
milkyWayList.add(" + . . . + ");
milkyWayList.add(" . . + .+. . ");
milkyWayList.add(" . . . + . . . . .");
milkyWayList.add(" . . . . . . . . ");
milkyWayList.add(" * . . . + . . ");
milkyWayList.add(" . . . + . . * . . ");
milkyWayList.add(" . + . . . .. + .");
milkyWayList.add(" . . . . * . * . +.. . * ");
milkyWayList.add(" . . . . . . . . + . . +");
milkyWayList.add(" . . . * . . . . + .");
milkyWayList.add(" + . . . + ");
milkyWayList.add(" . . + .+. . ");
milkyWayList.add(" . . . + . . . . .");
milkyWayList.add(" . . . . . . . . ");
milkyWayList.add(" * . . . + . . ");
milkyWayList.add(" . . . + . . * . . ");
milkyWayList.add(" . + . . . .. + .");
milkyWayList.add(" . . . . * . * . +.. . * ");
milkyWayList.add(" . . . . . . . . + . . +");
}
public static void drawMilkyWay(int[] centerOfSun) {
addMilkyWayList1();
addMilkyWayList2();
int row = centerOfSun[0];
int col = centerOfSun[1];
int cnt = 0;
int startRow = row - 10;
char[] chars = milkyWayList.get(cnt++).toCharArray();
while (cnt < milkyWayList.size()) {
for (int i = 0; i < chars.length; ++i) {
if (startRow + cnt < 0 || startRow + cnt >= graph.length ||
col - 20 + i < 0 || col - 20 + i >= graph[0].length) {
continue;
}
graph[startRow + cnt][col - 20 + i] = chars[i];
}
chars = milkyWayList.get(cnt++).toCharArray();
}
}
public static LocalDate enterDate() throws IOException {
StringTokenizer st = new StringTokenizer(br.readLine());
try {
tmpYear = st.nextToken();
tmpMonth = st.nextToken();
tmpDay = st.nextToken();
year = Integer.parseInt(tmpYear.substring(0, tmpYear.length() - 1));
month = Integer.parseInt(tmpMonth.substring(0, tmpMonth.length() - 1));
day = Integer.parseInt(tmpDay.substring(0, tmpDay.length() - 1));
} catch (NoSuchElementException e) {
throw new NoSuchElementException("[ERROR] 날짜는 y년 m월 d일 형태로만 입력 가능합니다.");
} catch (NumberFormatException e) {
throw new NumberFormatException("[ERROR] 날짜는 y년 m월 d일 형태로만 입력 가능합니다.");
}
try {
enterDate = LocalDate.of(year, month, day);
} catch (DateTimeException e) {
throw new DateTimeException("[ERROR] 날짜는 y년 m월 d일 형태로만 입력 가능합니다.");
}
return enterDate;
}
public static void drawSun(int[] center) { // 예외 처리 필요
int row = center[0];
int col = center[1];
graph[row - 1][col - 2] = '\\';
graph[row - 1][col - 1] = ' ';
graph[row - 1][col] = '!';
graph[row - 1][col + 1] = ' ';
graph[row - 1][col + 2] = '/';
graph[row][col - 2] = '-';
graph[row][col - 1] = ' ';
graph[row][col] = '○';
graph[row][col + 1] = ' ';
graph[row][col + 2] = '-';
graph[row + 1][col - 2] = '/';
graph[row + 1][col - 1] = ' ';
graph[row + 1][col] = '|';
graph[row + 1][col + 1] = ' ';
graph[row + 1][col + 2] = '\\';
}
public static void drawPositionMsg(int[] myPosition) {
int myPositionRow = myPosition[0];
int myPositionCol = myPosition[1];
String msg = "\"You Are Here!\"";
char[] msgArr = msg.toCharArray();
int msgRow = myPositionRow - 5;
int startCol = myPositionCol - 5;
if (startCol + msg.length() >= graph[0].length) {
startCol -= startCol + msg.length() - graph[0].length;
}
if (startCol + msg.length() < 0) {
startCol = 0;
}
for (int i = startCol; i < startCol + msg.length(); ++i) {
if (msgRow < 0 || msgRow >= graph.length || i < 0 || i >= graph[0].length ||
i - startCol < 0 || i - startCol >= msgArr.length) {
continue;
}
graph[msgRow][i] = msgArr[i - startCol];
}
}
public static void drawArrow(int[] myPosition) {
int myPositionRow = myPosition[0];
int myPositionCol = myPosition[1];
int startRow = myPositionRow - 4;
graph[startRow][myPositionCol] = '|';
graph[startRow + 1][myPositionCol] = '|';
graph[startRow + 2][myPositionCol - 1] = '\\';
graph[startRow + 2][myPositionCol] = '|';
graph[startRow + 2][myPositionCol + 1] = '/';
graph[startRow + 3][myPositionCol] = 'V';
}
public static char[][] drawPlanet(int diameter) {
char[][] circle = new char[diameter][diameter];
int radiusIdx = diameter / 2;
for (int i = 0; i < radiusIdx; ++i) {
int tmpIdx = i + radiusIdx;
int min = Math.min(tmpIdx, diameter - 1 - tmpIdx);
int max = Math.max(tmpIdx, diameter - 1 - tmpIdx);
for (int j = min; j <= max; ++j) {
circle[i][j] = '*';
}
}
for (int i = radiusIdx; i < diameter; ++i) {
int tmpIdx = i - radiusIdx;
int min = Math.min(tmpIdx, diameter - 1 - tmpIdx);
int max = Math.max(tmpIdx, diameter - 1 - tmpIdx);
for (int j = min; j <= max; ++j) {
circle[i][j] = '*';
}
}
return circle;
}
// 태양, 지구, 달이 아닌 새로운 행성 그리기
public static char[][] fillGraphWithPlanet(int[] center, int diameter) {
int centerRow = center[0];
int centerCol = center[1];
char[][] planet = drawPlanet(diameter); // diameter * diameter 크기의 행렬
int radius = diameter / 2;
for (int i = centerRow - radius; i < centerRow - radius + diameter; ++i) {
for (int j = centerCol - radius; j < centerCol - radius + diameter; ++j) {
// 그래프 범위를 벗어나면 일단 패스
if (i < 0 || i >= graph.length || j < 0 || j >= graph[0].length) {
continue;
}
if (i - centerRow + radius < 0 || i - centerRow + radius >= planet.length
|| j - centerCol + radius < 0 || j - centerCol + radius >= planet[0].length) {
continue;
}
graph[i][j] = planet[i - centerRow + radius][j - centerCol + radius];
}
}
return graph;
}
public static char[][] fillGraphWithEarth(int[] center) {
graph[center[0]][center[1]] = '★';
return graph;
}
public static char[][] fillGraphWithMoon(int[] center) {
graph[center[0]][center[1]] = '☾';
return graph;
}
public static void printSolarSystem() {
for (char[] row : graph) {
for (char c : row) {
if (sunCharSet.contains(c)) {
System.out.print(c);
continue;
}
System.out.print(" ");
}
System.out.println();
}
}
}
- SolarSystem 클래스
- 2단계와 다르게 태양, 지구, 달에 지름을 없애고 해모양, 달모양, 별모양 특수기호를 넣는다.
- 각도 구하는 부분은 공전 클래스 Revolution에 있는 메서드를 그대로 이용했다.
- 날짜를 입력 받아서 각도를 구하기 => 회전 후 행, 열 구하기 => 그래프 채우기 과정으로 실행한다.
<hide/>
public class SolarSystem {
public static void main(String[] args) throws IOException {
System.out.println("날짜를 입력하세요. ex) yyyy년 M월 d일");
LocalDate date = Planet.enterDate();
double angleBetweenSunAndEarth = Revolution.dateToAngle(date);
double angleBetweenEarthAndMoon = angleBetweenSunAndEarth * 12;
double disFromSunToEarth = 20;
double disFromEarthToMoon = 4;
int[] centerOfSun = new int[]{25, 25};
int[] centerOfEarth = Revolution.angleToCoordinate(centerOfSun, disFromSunToEarth, angleBetweenSunAndEarth);
Planet.drawMilkyWay(centerOfSun);
Planet.drawSun(centerOfSun);
Planet.fillGraphWithEarth(centerOfEarth);
Planet.drawPositionMsg(centerOfEarth);
Planet.drawArrow(centerOfEarth);
int[] centerOfMoon = Revolution.angleToCoordinate(centerOfEarth, disFromEarthToMoon, angleBetweenEarthAndMoon);
Planet.fillGraphWithMoon(centerOfMoon);
Planet.printSolarSystem();
}
}
Note) 입출력 예시
날짜를 입력하세요. ex) yyyy년 M월 d일
2020년 9월 20일
3단계 회고
- 연이 추가됨에 따라서 2단계와 다른 차별점을 줘야할 것 같았다. 그런데, 평면 상에서 차이점을 구현하는게 가능한지 모르겠다.그래서 2단계랑 차이 없이 구현했다.
- 수성, 금성, .... 등 다른 행성을 추가하고 싶었지만 거리, 위치, 공전 주기를 파악해서 그리는 게 어려워서 포기했는데 이 부분이 아쉽다. 시간이 더 있으면 공부해서 추가하면 더 멋있게 구현할 수 있었을 것 같다.
- 애니메이션(4단계)은 한 번도 해본적이 없어서 구글링해서 찾다가 결국은 이미지 띄우기까지 밖에 못했다.
- Thread.sleep() 을 이용해서 그림이 이동하도록 구현하면 되지 않을까 싶다.
'Boot Camp > [코드스쿼드] Java 백엔드 테스트' 카테고리의 다른 글
[4단계] 태양계 애니메이션 - 미완성 (0) | 2022.12.08 |
---|---|
[2단계] 지구 태양 달의 위치 표시하기 (0) | 2022.12.08 |
[1단계] 콘솔로 원 출력하기 (0) | 2022.12.08 |