我正在将俄罗斯方块作为一个有趣的Java项目。
我正在试图移动一个完整的俄罗斯方块,这是一个由4个瓷砖对象组成的对象。
当我向下移动棋子时,所有的棋盘都被其他一块瓦片阻挡 将毫无问题地向下移动。由于这两个检查,被其中一个瓷砖(例如,带有蓝色x的瓷砖)阻挡的零件的任何部分都不会移动:
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height-1;
}
public boolean isOpen(int x, int y) {
return isValidCoordinate(x, y) && getTileAt(x, y) == null;
}
从Board类中,我按原样移动Piece对象:
if(keyCode == KeyEvent.VK_DOWN) {
newPiece.movePieceDown();
然后在Piece课程中:
public void movePieceDown() {
tile1.setLocation(tile1.getX(), tile1.getY()+1);
tile2.setLocation(tile2.getX(), tile2.getY()+1);
tile3.setLocation(tile3.getX(), tile3.getY()+1);
tile4.setLocation(tile4.getX(), tile4.getY()+1);
}
有没有办法可以让俄罗斯方块的所有瓷砖一起移动?
谢谢!
编辑:
EXE:
https://www.dropbox.com/s/mg9dtf2sr0sazwq/my_tetris_test2.jar
来源:
https://www.dropbox.com/s/9kt3sl6qqo54amk/Tetris%20Two.rar
代码编辑:
使用反向Z形测试:
开始坐标:Piece "RevZ" Coordinates: (1, 1) (2, 1) (0, 2) (1, 2)
按下键给我:
Board.java类:将关键事件更改为:
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
newPiece.movePieceCheck(keyCode);
if (newPiece.movePieceValid()) {
newPiece.move();
}
repaint();
}
Piece.java类:我现在在移动之前检查......
public void calcNewPosition(int newX, int newY, int currTile) {
newPositionX[currTile] = newX;
newPositionY[currTile] = newY;
System.out.println("New Position: " + newPositionX[currTile] + ", " + newPositionY[currTile]);
}
public void clearCurrPosition(int currX, int currY, int currTile) {
currPositionX[currTile] = currX;
currPositionY[currTile] = currY;
System.out.println("Current Position: " + currPositionX[currTile] + ", " + currPositionY[currTile]);
board.setTileAt(null, currPositionX[currTile], currPositionY[currTile]);
if (board.getTileAt(currPositionX[currTile], currPositionY[currTile]) == null) {
System.out.println("curr block set to null...");
}
}
public void movePieceCheck(int keycode) {
if (keycode == KeyEvent.VK_DOWN) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);
clearCurrPosition(tile[i].getX(), tile[i].getY(), i);
}
}
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()+1, tile[i].getY(), i);
clearCurrPosition(tile[i].getX(), tile[i].getY(), i);
}
}
if (keycode == KeyEvent.VK_LEFT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getX()-1, tile[i].getY(), i);
clearCurrPosition(tile[i].getX(), tile[i].getY(), i);
}
}
}
public boolean movePieceValid() {
boolean valid = false;
for (int i = 0; i < tile.length; i++) {
if(tile[i].checkNewLocation(newPositionX[i], newPositionY[i])) {
valid = true;
}
}
return valid;
}
public void move() {
for (int i = 0; i < tile.length; i++) {
tile[i].setLocation(newPositionX[i], newPositionY[i]);
}
}
Println输出:
Piece "RevZ" Coordinates: (1, 1) (2, 1) (0, 2) (1, 2)
New Position: 1, 2
Current Position: 1, 1
curr block set to null...
New Position: 2, 2
Current Position: 2, 1
curr block set to null...
New Position: 0, 3
Current Position: 0, 2
curr block set to null...
New Position: 1, 3
Current Position: 1, 2
curr block set to null...
我先按照你说的检查所有内容,然后设置位置。
现在的问题是,除了发生支票时无法移动的区块外,它正在移动所有区域,因为原始区块在那里。但这很奇怪,因为我在移动碎片之前将旧位置设置为null,因此它应该是空的。
答案 0 :(得分:3)
嗯,这并不奇怪,因为你说你检查位置是valid
是否正如我所理解的那样,那里没有其他的东西。
你的问题是:
tile3.setLocation(tile3.getX(), tile3.getY()+1);
tile4.setLocation(tile4.getX(), tile4.getY()+1);
我打赌它是第3件卡住了。所以解决这个问题只是改变了这两个的顺序。但是现在出现了问题,当你旋转这件作品时会发生什么,然后他们会按顺序移动?
我认为最好首先计算每个方格的新位置,将它们从当前位置移除。然后将它们全部拉到新的位置:
calculateNewPositions();
clearCurrentPositions();
drawSquares();
这应该可以做到相当普遍而不会有太多麻烦,因此它可以处理不同的情况(即当您旋转对象时)而不会有太多麻烦。
答案 1 :(得分:2)
我认为你的问题是逻辑之一,每个Tile决定它是否被阻止和移动是错误的。建议:
ArrayList<Tile>
告诉每个Tile移动。为了他人的利益,这是您在一个文件中的完整程序:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class TetrisSscce extends JPanel {
static TetrisSscce runMe;
BoardSscce board;
public TetrisSscce() { // creates a new Panel window and sets properties
JFrame f = new JFrame("Tetris");
// width (height), length, tilesize
board = new BoardSscce(4, 6, 30);
f.add(board);
f.setSize(board.getWidth(), board.getHeight());
f.setVisible(true);
f.setResizable(false);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
f.setLocation((screensize.width - f.getWidth()) / 2,
(screensize.height - f.getHeight()) / 2 - 100);
}
public static void main(String[] args) {
runMe = new TetrisSscce();
}
}
class BoardSscce extends JPanel implements KeyListener {
private TileSscce grid[][];
private TileSscce activetile;
private int width, height, tilesize;
private String piece;
private PieceSscce newPiece;
public BoardSscce(int w, int h, int ts) { // add elements to the Tetris panel
width = w;
height = h;
tilesize = ts;
grid = new TileSscce[height][width];
// activetile = new TileSscce(this,0, 0); //add new tile to "this" board
newPiece = new PieceSscce(this, randomPiece());
addKeyListener(this);
setFocusable(true);
}
public String randomPiece() {
String[] Pieces = { "L", "O", "Z", "RevZ", "Bar", "T", "RevL" };
String randomShape;
int rand = (int) (Math.random() * Pieces.length);
randomShape = Pieces[rand];
return randomShape;
}
// dimensions of board = width * tilesize
public int getWidth() {
// 4 * 30 = 120 width
return width * tilesize;
}
public int getHeight() {
// 6 * 30 = 180 height
return height * tilesize;
}
public void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int row = 0; row < grid.length; row++) {
for (int col = 0; col < grid[row].length; col++) {
if (grid[row][col] != null) {
// if there is a non-null space, that is a tetris piece.. fill it
// red
if (grid[row][col].getColor() != null) {
g.setColor(grid[row][col].getColor());
g.fillRect(col * tilesize, row * tilesize, tilesize, tilesize);
}
}
}
}
}
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if (keyCode == KeyEvent.VK_DOWN) {
// checkBottomFull(0,4);
// collisionCheck(activetile.getX(),activetile.getY());
// checkEndGame(activetile.getX(), activetile.getY());
// activetile.setLocation(activetile.getX(), activetile.getY()+1);
// need to move Object newPiece down as a unit of 4 tiles
newPiece.movePieceDown();
// System.out.println("coordinates: " + activetile.getX() + ", " +
// activetile.getY());
repaint();
}
if (keyCode == KeyEvent.VK_RIGHT) {
// activetile.setLocation(activetile.getX()+1, activetile.getY());
// System.out.println("coordinates: " + activetile.getX() + ", " +
// activetile.getY());
newPiece.movePieceRight();
repaint();
}
if (keyCode == KeyEvent.VK_LEFT) {
// activetile.setLocation(activetile.getX()-1, activetile.getY());
// System.out.println("coordinates: " + activetile.getX() + ", " +
// activetile.getY());
newPiece.movePieceLeft();
repaint();
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
// check if (x, y) is a safe coordinate, ie, within the grid array bounds
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < width && y < height - 1;
}
// returns the tile at (x, y) or null if empty
public TileSscce getTileAt(int x, int y) {
if (isValidCoordinate(x, y))
return grid[y][x];
return null;
}
// sets the tile at (x, y) to tile
public void setTileAt(TileSscce tile, int x, int y) {
if (isValidCoordinate(x, y))
grid[y][x] = tile;
}
public boolean isOpen(int x, int y) {
return isValidCoordinate(x, y) && getTileAt(x, y) == null;
}
public void collisionCheck(int x, int y) {
/*
* if (activetile.getY() == this.height-2 || getTileAt(x, y+1) != null) {
* //activetile = new TileSscce(this, 0, 0); newPiece = new
* PieceSscce(this, randomPiece()); }
*/
}
public void checkBottomFull(int x, int y) {
while (getTileAt(x, y) != null) {
say("(" + x + ", " + y + ")");
if (x == 3) {
say("row is full");
// replace full row with tiles from above
for (int i = 0; i < 4; i++) {
for (int j = 5; j > 0; j--) {
grid[j][i] = getTileAt(i, j - 1);
}
}
break;
}
x++;
}
}
public void checkEndGame(int x, int y) {
if (y == 0 && !isOpen(x, y + 1)) {
say("Game over");
for (int i = 0; i < 4; i++) {
for (int j = 5; j > 0; j--) {
grid[j][i] = null;
}
}
}
}
public void say(String word) {
System.out.println(word);
}
public void sayint(int number) {
System.out.println(number);
}
}
class PieceSscce {
public int[] pieceCoordinates;
public String shape;
public BoardSscce board;
public TileSscce tile[];
public TileSscce tile1;
public TileSscce tile2;
public TileSscce tile3;
public TileSscce tile4;
// don't need to pass in board because I'm already utilizing the Tiles class,
// which knows about the board
public PieceSscce(BoardSscce b, String randomPiece) {
shape = randomPiece;
board = b;
// set what the shape coordinates should be based on what "shape" is
pieceCoordinates = new int[8];
setInitialShapeCoordinates(shape);
tile = new TileSscce[4];
tile1 = new TileSscce(board, pieceCoordinates[0], pieceCoordinates[1]);
tile2 = new TileSscce(board, pieceCoordinates[2], pieceCoordinates[3]);
tile3 = new TileSscce(board, pieceCoordinates[4], pieceCoordinates[5]);
tile4 = new TileSscce(board, pieceCoordinates[6], pieceCoordinates[7]);
}
public void movePieceDown() {
for (int i = 0; i < 4; i++) {
}
tile1.setLocation(tile1.getX(), tile1.getY() + 1);
tile2.setLocation(tile2.getX(), tile2.getY() + 1);
tile3.setLocation(tile3.getX(), tile3.getY() + 1);
tile4.setLocation(tile4.getX(), tile4.getY() + 1);
}
public void movePieceRight() {
tile1.setLocation(tile1.getX() + 1, tile1.getY());
tile2.setLocation(tile2.getX() + 1, tile2.getY());
tile3.setLocation(tile3.getX() + 1, tile3.getY());
tile4.setLocation(tile4.getX() + 1, tile4.getY());
}
public void movePieceLeft() {
tile1.setLocation(tile1.getX() - 1, tile1.getY());
tile2.setLocation(tile2.getX() - 1, tile2.getY());
tile3.setLocation(tile3.getX() - 1, tile3.getY());
tile4.setLocation(tile4.getX() - 1, tile4.getY());
}
public void setInitialShapeCoordinates(String shape) {
System.out.println(shape);
if (shape == "L") {
// piece 1
pieceCoordinates[0] = 0;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 1;
pieceCoordinates[3] = 1;
// piece3
pieceCoordinates[4] = 2;
pieceCoordinates[5] = 1;
// piece4
pieceCoordinates[6] = 2;
pieceCoordinates[7] = 2;
} else if (shape == "O") {
// piece 1
pieceCoordinates[0] = 0;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 1;
pieceCoordinates[3] = 1;
// piece3
pieceCoordinates[4] = 0;
pieceCoordinates[5] = 2;
// piece4
pieceCoordinates[6] = 1;
pieceCoordinates[7] = 2;
} else if (shape == "Z") {
// piece 1
pieceCoordinates[0] = 0;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 1;
pieceCoordinates[3] = 1;
// piece3
pieceCoordinates[4] = 1;
pieceCoordinates[5] = 2;
// piece4
pieceCoordinates[6] = 2;
pieceCoordinates[7] = 2;
} else if (shape == "RevZ") {
// piece 1
pieceCoordinates[0] = 1;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 2;
pieceCoordinates[3] = 1;
// piece3
pieceCoordinates[4] = 0;
pieceCoordinates[5] = 2;
// piece4
pieceCoordinates[6] = 1;
pieceCoordinates[7] = 2;
} else if (shape == "Bar") {
// piece 1
pieceCoordinates[0] = 0;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 1;
pieceCoordinates[3] = 1;
// piece3
pieceCoordinates[4] = 2;
pieceCoordinates[5] = 1;
// piece4
pieceCoordinates[6] = 3;
pieceCoordinates[7] = 1;
} else if (shape == "T") {
// piece 1
pieceCoordinates[0] = 1;
pieceCoordinates[1] = 1;
// piece2
pieceCoordinates[2] = 0;
pieceCoordinates[3] = 2;
// piece3
pieceCoordinates[4] = 1;
pieceCoordinates[5] = 2;
// piece4
pieceCoordinates[6] = 2;
pieceCoordinates[7] = 2;
} else if (shape == "RevL") {
// piece 1
pieceCoordinates[0] = 0;
pieceCoordinates[1] = 2;
// piece2
pieceCoordinates[2] = 1;
pieceCoordinates[3] = 2;
// piece3
pieceCoordinates[4] = 2;
pieceCoordinates[5] = 2;
// piece4
pieceCoordinates[6] = 2;
pieceCoordinates[7] = 1;
}
}
}
class TileSscce {
private BoardSscce board;
private int currX, currY;
public TileSscce(BoardSscce b, int x, int y) {
board = b;
// when TileSscce is instantiated, set its position
setLocation(x, y);
}
public int getX() {
return currX;
}
public int getY() {
return currY;
}
public void setLocation(int newX, int newY) {
if (board.isValidCoordinate(newX, newY) && board.isOpen(newX, newY)) {
board.setTileAt(null, currX, currY);
currX = newX;
currY = newY;
board.setTileAt(this, currX, currY);
}
}
public Color getColor() {
double rand = Math.random() * (2 - 0);
/*
* Random rand = new Random(); float r = rand.nextFloat(); float g =
* rand.nextFloat(); float b = rand.nextFloat();
*/
// Color randomColor = new Color(r, g, b);
if (rand == 1) {
return Color.GRAY;
} else {
return Color.RED;
}
}
public Color setColor() {
return Color.GREEN;
}
}
正如丹尼尔指出的那样,你需要分析你如何检查被阻挡件以及如何移动的逻辑。您应首先检查一块所有瓷砖上的块,然后让该块告诉所有瓷砖移动而不是您正在做的事情 - 检查每个块的块,然后在未阻塞的情况下移动它。
例如,给Tile这样的东西:
// method to check if position OK
public boolean checkNewLocation(int newX, int newY) {
boolean newLocationOK = board.isValidCoordinate(newX, newY)
&& board.isOpen(newX, newY);
return newLocationOK;
}
// method to move to new position.
public void setLocation(int newX, int newY) {
board.setTileAt(null, currX, currY);
currX = newX;
currY = newY;
board.setTileAt(this, currX, currY);
}
So Piece将遍历其Tiles调用第一个方法,然后如果一切正常,则移动Tiles调用第二个方法。