我正在使用俄羅斯方塊旋轉算法。前段時間我在另一個winforms應用程序中使用了算法,它工作得很好。現在我想在Android中編寫一個俄羅斯方塊遊戲,所以我再次用Java編寫算法。俄羅斯方塊旋轉算法不起作用
但是,這次它不起作用。我很早以前就寫過算法,當時我是一名初學者程序員,所以代碼很糟糕。這裏是Java中的算法:
public static final int CLOCKWISE = 1;
public static final int ANTICLOCKWISE = -1;
public static Point rotateClockwise (int x, int y) {
int temp;
temp = y;
y = x;
x = -temp;
return new Point (x, y);
}
public static Point rotateAnticlockwise (int x, int y) {
int temp;
temp = x;
x = y;
y = -temp;
return new Point (x, y);
}
public static boolean tryRotateTetrimino (Tetrimino tetrimino,
int rotationPointBlockIndex, int direction) {
//Local variable declarations
boolean a, b, c, d;
TetrisBlock rotationBlock = tetrimino.blocks[rotationPointBlockIndex];
int X1, Y1, X2, Y2, X3, Y3, X4, Y4;
//Assign coordinates relative to the centre of rotation.
X1 = tetrimino.blocks[0].getX() - rotationBlock.getX();
Y1 = tetrimino.blocks[0].getY() - rotationBlock.getY();
X2 = tetrimino.blocks[1].getX() - rotationBlock.getX();
Y2 = tetrimino.blocks[1].getY() - rotationBlock.getY();
X3 = tetrimino.blocks[2].getX() - rotationBlock.getX();
Y3 = tetrimino.blocks[2].getY() - rotationBlock.getY();
X4 = tetrimino.blocks[3].getX() - rotationBlock.getX();
Y4 = tetrimino.blocks[3].getY() - rotationBlock.getY();
//Rotate the coordinates.
if (direction == CLOCKWISE) {
X1 = rotateClockwise (X1, Y1).x;
Y1 = rotateClockwise (X1, Y1).y;
X2 = rotateClockwise (X2, Y2).x;
Y2 = rotateClockwise (X2, Y2).y;
X3 = rotateClockwise (X3, Y3).x;
Y3 = rotateClockwise (X3, Y3).y;
X4 = rotateClockwise (X4, Y4).x;
Y4 = rotateClockwise (X4, Y4).y;
} else {
X1 = rotateAnticlockwise (X1, Y1).x;
Y1 = rotateAnticlockwise (X1, Y1).y;
X2 = rotateAnticlockwise (X2, Y2).x;
Y2 = rotateAnticlockwise (X2, Y2).y;
X3 = rotateAnticlockwise (X3, Y3).x;
Y3 = rotateAnticlockwise (X3, Y3).y;
X4 = rotateAnticlockwise (X4, Y4).x;
Y4 = rotateAnticlockwise (X4, Y4).y;
}
//Declares two arrays of absolute x and y coordinates.
int[] xArray = new int[] { rotationBlock.getX() + X1,
rotationBlock.getX() + X2,
rotationBlock.getX() + X3,
rotationBlock.getX() + X4 };
int[] yArray = new int[] { rotationBlock.getY() + Y1,
rotationBlock.getY() + Y2,
rotationBlock.getY() + Y3,
rotationBlock.getY() + Y4 };
//Check if the coordinates are valid
a = tetrimino.checkPositionValid (xArray[0], yArray[0]);
b = tetrimino.checkPositionValid (xArray[1], yArray[1]);
c = tetrimino.checkPositionValid (xArray[2], yArray[2]);
d = tetrimino.checkPositionValid (xArray[3], yArray[3]);
//If the coordinates are valid, assign them to each of the blocks.
if (a && b && c && d) {
for (int i = 0 ; i < 4 ; i++) {
tetrimino.blocks[i].setX (xArray[i]);
tetrimino.blocks[i].setY (yArray[i]);
}
return true;
}
return false;
}
我認爲這個代碼真的很難理解除了我以外的每個人。我曾經寫過世界上最糟糕的代碼。當terimino可以旋轉並旋轉時,此方法返回true。參數rotationPointBlockIndex指示旋轉中心。因此,我可以嘗試旋轉的俄羅斯大約每俄羅斯方塊塊,像這樣:
if (TetrisUtility.tryRotateTetrimino (this, 0, TetrisUtility.CLOCKWISE))
TetrisUtility.addRotationIndex (this);
else if (TetrisUtility.tryRotateTetrimino (this, 1, TetrisUtility.CLOCKWISE))
TetrisUtility.addRotationIndex (this);
else if (TetrisUtility.tryRotateTetrimino (this, 2, TetrisUtility.CLOCKWISE))
TetrisUtility.addRotationIndex (this);
else if (TetrisUtility.tryRotateTetrimino (this, 3, TetrisUtility.CLOCKWISE))
TetrisUtility.addRotationIndex (this);
請注意,setX的和SETY方法將改變俄羅斯方塊塊的物理位置。
我和以前完全一樣,但它不起作用。 例如:
O
O
O O
旋轉,並且變成
O
O
O
這似乎是兩個俄羅斯方塊塊都重疊。
如果您認爲我的算法錯誤並且想要推薦另一個算法,那麼您可以使用Tetrimino類和TetrisBlock類來解釋它嗎?
Tetrimino.java
public abstract class Tetrimino {
public TetrisBlock[] blocks;
protected int interval = 1000;
protected boolean paused = false;
protected Handler handler;
protected TetrisBlock[][] tetrisBlockMatrix;
protected ArrayList<ITetrisEventListener> landedEventListeners;
protected Runnable task = new TimerTask() {
@Override
public void run() {
if (!paused) {
moveDown();
if (handler != null)
handler.postDelayed (task, interval);
}
}
};
public static final int LEFT = -1;
public static final int RIGHT = 1;
protected abstract TetrisBlock[] getTouchingSides();
protected void landed() {
for (int i = 0 ; i < landedEventListeners.size() ; i++) {
landedEventListeners.get (i).onLanded (this);
}
}
public void registerLandedListeners (ITetrisEventListener listener) {
landedEventListeners.add (listener);
}
public void moveDown() {
if (!checkLanded()) {
for (TetrisBlock block:blocks) {
block.moveDown();
}
} else {
handler = null;
landed();
}
}
protected boolean checkLanded() {
TetrisBlock[] touchingSides = getTouchingSides();
for (TetrisBlock block:touchingSides) {
if (block.getY() >= 21) {
return true;
}
if (tetrisBlockMatrix[block.getX()][block.getY() + 1] != null) {
return true;
}
}
return false;
}
public boolean checkPositionValid (int x, int y) {
if (x < 0 || y < 0 ||
x > 15 || y > 21)
return false;
if (tetrisBlockMatrix[x][y] == null)
return true;
return false;
}
public void move (int side) {
if (side == 1 || side == -1) {
for (TetrisBlock block:blocks) {
block.setX (block.getX() + side);
}
for (TetrisBlock block:blocks) {
if (!checkPositionValid (block.getX(), block.getY())) {
if (side == LEFT)
move (RIGHT);
else
move (LEFT);
}
}
} else {
throw new IllegalArgumentException();
}
}
public void addTetrisBlocksToMatrix (TetrisBlock[][] matrix) {
for (TetrisBlock block:blocks) {
if (matrix[block.getX()][block.getY()] == null) {
matrix[block.getX()][block.getY()] = block;
} else {
throw new IllegalArgumentException();
}
}
}
public void setTimerEnabled (boolean value) {
if (value && paused) {
handler.post (task);
} else {
paused = true;
}
}
public void setTimerInterval (int milliseconds) {
interval = milliseconds;
}
protected Tetrimino (TetrisBlock[][] matrix, TetrisActivity activity) {
this.tetrisBlockMatrix = matrix;
handler = new Handler();
handler.post (task);
landedEventListeners = new ArrayList<>();
blocks = new TetrisBlock[4];
}
}
TetrisBlock.java
public class TetrisBlock {
private static final int LENGTH_IN_DP = 20;
private TetrisActivity activity;
private ImageView picture;
private int color;
private int x;
private int y;
private AbsoluteLayout.LayoutParams getLayoutParams() {
return (AbsoluteLayout.LayoutParams) picture.getLayoutParams();
}
public TetrisActivity getActivity() {
return activity;
}
public ImageView getPicture() {
return picture;
}
public int getY() {
AbsoluteLayout.LayoutParams params = getLayoutParams();
return params.y/getLengthInPixels();
}
public void setY(int y) {
this.y = y;
AbsoluteLayout.LayoutParams params = getLayoutParams();
params.y = y * getLengthInPixels();
picture.setLayoutParams (params);
}
public int getX() {
AbsoluteLayout.LayoutParams params = getLayoutParams();
return params.x/getLengthInPixels();
}
public void setX(int x) {
this.x = x;
AbsoluteLayout.LayoutParams params = getLayoutParams();
params.x = x * getLengthInPixels();
picture.setLayoutParams (params);
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
picture.setBackgroundColor (color);
}
public TetrisBlock (int color, int x, int y, TetrisActivity activity) {
this.activity = activity;
picture = new ImageView (activity);
setColor (color);
picture.setImageResource (R.drawable.tetrisblock);
int w, h;
w = getLengthInPixels();
h = getLengthInPixels();
AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams (w,
h, x * getLengthInPixels(), y * getLengthInPixels());
picture.setLayoutParams (params);
picture.setScaleType (ImageView.ScaleType.FIT_CENTER);
((AbsoluteLayout)activity.findViewById (R.id.main_frame)).addView (picture);
}
public void moveDown() {
setY (getY() + 1);
}
public int getLengthInPixels() {
return (int)(LENGTH_IN_DP * activity.getScale() + 0.5F);
}
}
哦,是的,我明白了!非常感謝你!我嘗試。 – Sweeper
哦,它的工作!接受答案! – Sweeper