728x90
저번 글 1: https://stickode.tistory.com/822
저번 글 2: https://stickode.tistory.com/835
저번 글 3: https://stickode.tistory.com/852
안녕하세요. 저번 시간에 이어서, 오늘은 Figure 코드에 대한 설명을 업로드하겠습니다. 주석으로 설명을 달아두었습니다.
import java.awt.*;
/**
* Tetris의 사각형 도형을 나타내는 클래스입니다. 각 도형은 일곱 가지 가능한 형태 중 하나인 네 개의 연결된 사각형으로 구성됩니다.
* 도형은 90도 단위로 회전할 수 있으며 옆으로나 아래로 움직일 수 있습니다.
* <p>
* 각 도형 인스턴스는 두 가지 상태를 가질 수 있습니다. 사각형 보드에 연결된 경우와 그렇지 않은 경우입니다.
* 연결된 경우, 모든 이동 및 회전 작업은 보드의 다른 사각형과 충돌하지 않도록 확인됩니다.
* 연결되지 않은 경우 어떤 회전도 가능하며 (보드에 다시 연결될 때 유지됨).
*/
public class Figure extends Object {
/**
* 사각형 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int SQUARE_FIGURE = 1;
/**
* 선 모양을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int LINE_FIGURE = 2;
/**
* "S" 모양을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int S_FIGURE = 3;
/**
* "Z" 모양을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int Z_FIGURE = 4;
/**
* 우각을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int RIGHT_ANGLE_FIGURE = 5;
/**
* 좌각을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int LEFT_ANGLE_FIGURE = 6;
/**
* 삼각형 모양을 형성하는 도형을 생성하는 데 사용되는 상수입니다.
*/
public static final int TRIANGLE_FIGURE = 7;
/**
* 도형이 연결된 사각형 보드입니다. 이 변수가 null로 설정되면 도형은 연결되지 않습니다.
*/
private SquareBoard board = null;
/**
* 보드에서 도형의 수평 위치입니다. 이 값은 도형이 사각형 보드에 연결되지 않은 경우 의미가 없습니다.
*/
private int xPos = 0;
/**
* 보드에서 도형의 수직 위치입니다. 이 값은 도형이 사각형 보드에 연결되지 않은 경우 의미가 없습니다.
*/
private int yPos = 0;
/**
* 도형의 방향 (또는 회전)입니다. 이 값은 보통 0부터 3 사이지만 maxOrientation 값보다 작아야 합니다.
*
* @see #maxOrientation
*/
private int orientation = 0;
/**
* 허용되는 최대 방향 번호입니다. 이 값은 사각형 도형과 같은 일부 도형에 대해 가능한 회전 수를 줄이는 데 사용됩니다.
* 사용하지 않는 경우 사각형 도형은 하나의 사각형 주위로 회전할 수 있어 잘못된 효과를 줄 수 있습니다.
*
* @see #orientation
*/
private int maxOrientation = 4;
/**
* 도형 모양의 수평 좌표입니다. 좌표는 현재 도형 위치와 방향에 상대적입니다.
*/
private int[] shapeX = new int[4];
/**
* 도형 모양의 수직 좌표입니다. 좌표는 현재 도형 위치와 방향에 상대적입니다.
*/
private int[] shapeY = new int[4];
/**
* 도형의 색상입니다.
*/
private Color color = Color.white;
/**
* 사각형 보드에 연결되지 않은 상태에서 일곱 가지 사전 정의된 유형 중 하나의 도형을 생성합니다.
* 도형에는 기본 색상과 방향이 할당됩니다.
*
* @param type 도형 유형 (도형 상수 중 하나)
* @throws IllegalArgumentException 지정된 도형 유형이 인식되지 않는 경우
* @see #SQUARE_FIGURE
* @see #LINE_FIGURE
* @see #S_FIGURE
* @see #Z_FIGURE
* @see #RIGHT_ANGLE_FIGURE
* @see #LEFT_ANGLE_FIGURE
* @see #TRIANGLE_FIGURE
*/
public Figure(int type) throws IllegalArgumentException {
initialize(type);
}
/**
* 지정된 도형 유형에 대해 인스턴스 변수를 초기화합니다.
*
* @param type 도형 유형 (도형 상수 중 하나)
* @throws IllegalArgumentException 지정된 도형 유형이 인식되지 않는 경우
* @see #SQUARE_FIGURE
* @see #LINE_FIGURE
* @see #S_FIGURE
* @see #Z_FIGURE
* @see #RIGHT_ANGLE_FIGURE
* @see #LEFT_ANGLE_FIGURE
* @see #TRIANGLE_FIGURE
*/
private void initialize(int type) throws IllegalArgumentException {
// 기본 변수 초기화
board = null;
xPos = 0;
yPos = 0;
orientation = 0;
// 도형 유형 변수 초기화
switch (type) {
case SQUARE_FIGURE:
maxOrientation = 1;
color = Configuration.getColor("figure.square", "#ffd8b1");
shapeX[0] = -1;
shapeY[0] = 0;
shapeX[1] = 0;
shapeY[1] = 0;
shapeX[2] = -1;
shapeY[2] = 1;
shapeX[3] = 0;
shapeY[3] = 1;
break;
case LINE_FIGURE:
maxOrientation = 2;
color = Configuration.getColor("figure.line", "#ffb4b4");
shapeX[0] = -2;
shapeY[0] = 0;
shapeX[1] = -1;
shapeY[1] = 0;
shapeX[2] = 0;
shapeY[2] = 0;
shapeX[3] = 1;
shapeY[3] = 0;
break;
case S_FIGURE:
maxOrientation = 2;
color = Configuration.getColor("figure.s", "#a3d5ee");
shapeX[0] = 0;
shapeY[0] = 0;
shapeX[1] = 1;
shapeY[1] = 0;
shapeX[2] = -1;
shapeY[2] = 1;
shapeX[3] = 0;
shapeY[3] = 1;
break;
case Z_FIGURE:
maxOrientation = 2;
color = Configuration.getColor("figure.z", "#f4adff");
shapeX[0] = -1;
shapeY[0] = 0;
shapeX[1] = 0;
shapeY[1] = 0;
shapeX[2] = 0;
shapeY[2] = 1;
shapeX[3] = 1;
shapeY[3] = 1;
break;
case RIGHT_ANGLE_FIGURE:
maxOrientation = 4;
color = Configuration.getColor("figure.right", "#c0b6fa");
shapeX[0] = -1;
shapeY[0] = 0;
shapeX[1] = 0;
shapeY[1] = 0;
shapeX[2] = 1;
shapeY[2] = 0;
shapeX[3] = 1;
shapeY[3] = 1;
break;
case LEFT_ANGLE_FIGURE:
maxOrientation = 4;
color = Configuration.getColor("figure.left", "#f5f4a7");
shapeX[0] = -1;
shapeY[0] = 0;
shapeX[1] = 0;
shapeY[1] = 0;
shapeX[2] = 1;
shapeY[2] = 0;
shapeX[3] = -1;
shapeY[3] = 1;
break;
case TRIANGLE_FIGURE:
maxOrientation = 4;
color = Configuration.getColor("figure.triangle", "#a4d9b6");
shapeX[0] = -1;
shapeY[0] = 0;
shapeX[1] = 0;
shapeY[1] = 0;
shapeX[2] = 1;
shapeY[2] = 0;
shapeX[3] = 0;
shapeY[3] = 1;
break;
default:
throw new IllegalArgumentException("No figure constant: " +
type);
}
}
/**
* 이 도형이 사각형 보드에 연결되었는지 확인합니다.
*
* @return 도형이 이미 연결되어 있는 경우 true, 그렇지 않은 경우 false
*/
public boolean isAttached() {
return board != null;
}
/**
* 지정된 사각형 보드에 도형을 연결합니다. 도형은 보드의 상단에 절대적으로 위치하며 하단 줄만 표시되거나
* 보드의 가운데에 중앙 정렬되어 그려집니다. 양쪽 경우 모두 새 보드의 사각형은 충돌을 확인하기 위해 검사됩니다.
* 사각형이 이미 차있는 경우에는 false를 반환하고 연결이 이루어지지 않습니다.<p>
* <p>
* 도형이 새 보드에 중앙 정렬되는 경우, 도형의 수평 및 수직 좌표가 재설정됩니다. 그러나 도형의 방향(회전)은 유지됩니다.
* 이전에 다른 보드에 연결되어있는 경우에는 해당 보드와의 연결이 끊기고 새 보드에 연결됩니다.
*
* @param board 연결할 사각형 보드
* @param center 중앙 정렬 플래그
* @return 도형이 연결되었으면 true, 그렇지 않으면 false
*/
public boolean attach(SquareBoard board, boolean center) {
int newX;
int newY;
int i;
// 이전 연결 여부 확인
if (isAttached()) {
detach();
}
// 위치 초기화 (올바른 조작을 위해)
xPos = 0;
yPos = 0;
// 위치 계산
newX = board.getBoardWidth() / 2;
if (center) {
newY = board.getBoardHeight() / 2;
} else {
newY = 0;
for (i = 0; i < shapeX.length; i++) {
if (getRelativeY(i, orientation) - newY > 0) {
newY = -getRelativeY(i, orientation);
}
}
}
// 위치 확인
this.board = board;
if (!canMoveTo(newX, newY, orientation)) {
this.board = null;
return false;
}
// 도형 그리기
xPos = newX;
yPos = newY;
paint(color);
board.update();
return true;
}
/**
* 도형을 해당 사각형 보드에서 분리합니다. 이 작업으로 인해 도형은 보드에서 제거되지 않고 그대로 남습니다.
*/
public void detach() {
board = null;
}
/**
* 도형이 사각형 보드에서 완전히 표시되는지 확인합니다. 도형이 보드에 연결되지 않은 경우 false를 반환합니다.
*
* @return 도형이 완전히 표시되면 true, 그렇지 않으면 false
*/
public boolean isAllVisible() {
if (!isAttached()) {
return false;
}
for (int i = 0; i < shapeX.length; i++) {
if (yPos + getRelativeY(i, orientation) < 0) {
return false;
}
}
return true;
}
/**
* 도형이 착륙한지 확인합니다. 이 메서드가 true를 반환하면 moveDown() 또는 moveAllWayDown() 메서드는
* 효과가 없어야 합니다. 사각형 보드가 연결되지 않은 경우 이 메서드는 true를 반환합니다.
*
* @return 도형이 착륙한 경우 true, 그렇지 않으면 false
*/
public boolean hasLanded() {
return !isAttached() || !canMoveTo(xPos, yPos + 1, orientation);
}
/**
* 도형을 왼쪽으로 한 칸 이동합니다. 사각형 보드에 대해 이동할 수 없는 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 아무 작업도 수행하지 않습니다.
*/
public void moveLeft() {
if (isAttached() && canMoveTo(xPos - 1, yPos, orientation)) {
paint(null);
xPos--;
paint(color);
board.update();
}
}
/**
* 도형을 오른쪽으로 한 칸 이동합니다. 사각형 보드에 대해 이동할 수 없는 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 아무 작업도 수행하지 않습니다.
*/
public void moveRight() {
if (isAttached() && canMoveTo(xPos + 1, yPos, orientation)) {
paint(null);
xPos++;
paint(color);
board.update();
}
}
/**
* 도형을 아래로 한 칸 이동합니다. 사각형 보드에 대해 이동할 수 없는 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 아무 작업도 수행하지 않습니다.
*/
public void moveDown() {
if (isAttached() && canMoveTo(xPos, yPos + 1, orientation)) {
paint(null);
yPos++;
paint(color);
board.update();
}
}
/**
* 도형을 가장 아래로 이동합니다. 이동 범위는 사각형 보드 하단이거나 비어 있지 않은 사각형입니다.
* 사각형 보드에 대해 이동이 불가능한 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 아무 작업도 수행하지 않습니다.
*/
public void moveAllWayDown() {
int y = yPos;
// 보드 확인
if (!isAttached()) {
return;
}
// 가장 낮은 위치 찾기
while (canMoveTo(xPos, y + 1, orientation)) {
y++;
}
// 업데이트
if (y != yPos) {
paint(null);
yPos = y;
paint(color);
board.update();
}
}
/**
* 현재 도형의 회전(방향)을 반환합니다.
*
* @return 현재 도형의 회전
*/
public int getRotation() {
return orientation;
}
/**
* 도형의 회전(방향)을 설정합니다. 사각형 보드에 대해 원하는 회전이 불가능한 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 회전이 직접 수행됩니다.
*
* @param rotation 새로운 도형의 방향
*/
public void setRotation(int rotation) {
int newOrientation;
// 새로운 방향 설정
newOrientation = rotation % maxOrientation;
// 새 위치 확인
if (!isAttached()) {
orientation = newOrientation;
} else if (canMoveTo(xPos, yPos, newOrientation)) {
paint(null);
orientation = newOrientation;
paint(color);
board.update();
}
}
/**
* 도형을 임의로 회전합니다. 사각형 보드에 대해 이 회전이 불가능한 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 회전이 직접 수행됩니다.
*/
public void rotateRandom() {
setRotation((int) (Math.random() * 4.0) % maxOrientation);
}
/**
* 도형을 시계 방향으로 회전합니다. 사각형 보드에 대해 이 회전이 불가능한 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 회전이 직접 수행됩니다.
*/
public void rotateClockwise() {
if (maxOrientation == 1) {
return;
} else {
setRotation((orientation + 1) % maxOrientation);
}
}
/**
* 도형을 반시계 방향으로 회전합니다. 사각형 보드에 대해 이 회전이 불가능한 경우 아무 작업도 수행하지 않습니다.
* 도형이 이동하면 사각형 보드가 변경되어 이전 셀이 지워집니다. 사각형 보드가 연결되지 않은 경우 회전이 직접 수행됩니다.
*/
public void rotateCounterClockwise() {
if (maxOrientation == 1) {
return;
} else {
setRotation((orientation + 3) % 4);
}
}
/**
* 지정된 (사각형) 좌표 쌍이 도형 내부에 있는지 여부를 확인합니다.
*
* @param x 수평 위치
* @param y 수직 위치
* @return 좌표가 도형 내부에 있으면 true, 그렇지 않으면 false
*/
private boolean isInside(int x, int y) {
for (int i = 0; i < shapeX.length; i++) {
if (x == xPos + getRelativeX(i, orientation)
&& y == yPos + getRelativeY(i, orientation)) {
return true;
}
}
return false;
}
/**
* 도형이 새 위치로 이동할 수 있는지 확인합니다. 현재 도형 위치는 충돌을 확인할 때 고려됩니다.
* 충돌이 감지되면 이 메서드는 false를 반환합니다.
*
* @param newX 새로운 수평 위치
* @param newY 새로운 수직 위치
* @param newOrientation 새로운 방향 (회전)
* @return 도형이 이동 가능하면 true, 그렇지 않으면 false
*/
private boolean canMoveTo(int newX, int newY, int newOrientation) {
int x;
int y;
for (int i = 0; i < 4; i++) {
x = newX + getRelativeX(i, newOrientation);
y = newY + getRelativeY(i, newOrientation);
if (!isInside(x, y) && !board.isSquareEmpty(x, y)) {
return false;
}
}
return true;
}
/**
* 지정된 사각형의 상대적인 수평 위치를 반환합니다.
* 지정된 방향에 따라 사각형이 회전됩니다.
*
* @param square 회전할 사각형 (0-3)
* @param orientation 사용할 방향 (0-3)
* @return 회전된 상대적인 수평 위치
*/
private int getRelativeX(int square, int orientation) {
switch (orientation % 4) {
case 0:
return shapeX[square];
case 1:
return -shapeY[square];
case 2:
return -shapeX[square];
case 3:
return shapeY[square];
default:
return 0; // 발생하지 않아야 함
}
}
/**
* 지정된 사각형의 상대적인 수직 위치를 회전합니다.
* 지정된 방향에 따라 사각형이 회전됩니다.
*
* @param square 회전할 사각형 (0-3)
* @param orientation 사용할 방향 (0-3)
* @return 회전된 상대적인 수직 위치
*/
private int getRelativeY(int square, int orientation) {
switch (orientation % 4) {
case 0:
return shapeY[square];
case 1:
return shapeX[square];
case 2:
return -shapeY[square];
case 3:
return -shapeX[square];
default:
return 0; // 발생하지 않아야 함
}
}
/**
* 도형을 지정된 색으로 보드에 그립니다.
*
* @param color 그릴 색상, 지우기를 위해 null을 사용합니다.
*/
private void paint(Color color) {
int x, y;
for (int i = 0; i < shapeX.length; i++) {
x = xPos + getRelativeX(i, orientation);
y = yPos + getRelativeY(i, orientation);
board.setSquareColor(x, y, color);
}
}
}
'안드로이드 자바' 카테고리의 다른 글
[Android][Java]엑셀 파일 등록,읽기 (0) | 2023.07.21 |
---|---|
[Android][JAVA]Shimmer 사용한 스켈레톤 UI 로딩화면 구현 (0) | 2023.07.18 |
[Android][Java] Joda-Time 활용해서 현재 시간 알아내기 (0) | 2023.07.08 |
[Android][Java] WebRTC library 사용해서 내 화면 가져오기 (0) | 2023.07.07 |
[Android][JAVA] ListView로 구현하는 TodoList (0) | 2023.07.03 |