Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java俄罗斯方块旋转错误_Java_Swing_Debugging_Rotation_Tetris - Fatal编程技术网

Java俄罗斯方块旋转错误

Java俄罗斯方块旋转错误,java,swing,debugging,rotation,tetris,Java,Swing,Debugging,Rotation,Tetris,我对俄罗斯方块有些问题。首先,我有一个类Shape,然后是每个Shape类型的Shape子类。这是形状子类的外观: public class SquareShape extends Shape { public SquareShape(){ coords = squareShapeCoords; shape = SQUARESHAPE; } } 在Shape类中,我有一个旋转方法,如下所示: protected void setX(int i,

我对俄罗斯方块有些问题。首先,我有一个类Shape,然后是每个Shape类型的Shape子类。这是形状子类的外观:

public class SquareShape extends Shape {
    public SquareShape(){
        coords = squareShapeCoords;
        shape = SQUARESHAPE;
    }
}
在Shape类中,我有一个旋转方法,如下所示:

protected void setX(int i, int x) { coords[i][0] = x; }
protected void setY(int i, int y) { coords[i][1] = y; }
public int x(int i) { return coords[i][0]; }
public int y(int i) { return coords[i][1]; }

public Shape rotate(){
        if (this.getShape().equals(SQUARESHAPE)) return this;
        Shape newShape = new Shape();
        newShape.shape = this.shape;
        for (int i = 0; i < 4; i++) {
            newShape.setX(i, y(i));
            newShape.setY(i, -x(i));
        }
        return newShape;
}
public Shape rotate(){
        if (this.getShape().equals(SQUARESHAPE)) return this;
        Shape newShape = new Shape();
        newShape.shape = this.shape;
        int[] oldX = {this.x(0), this.x(1), this.x(2), this.x(3)};
        for (int i = 0; i < 4; i++) {
            newShape.setX(i, -y(i));
            newShape.setY(i, oldX[i]);
        }
        return newShape;
}
protectedvoidsetx(inti,intx){coords[i][0]=x;}
受保护的void setY(inti,inty){coords[i][1]=y;}
公共整数x(整数i){返回坐标[i][0];}
公共整数y(整数i){返回坐标[i][1];}
公共形状旋转(){
如果(this.getShape().equals(SQUARESHAPE))返回该值;
形状newShape=新形状();
newShape.shape=this.shape;
对于(int i=0;i<4;i++){
新闻形态setX(i,y(i));
新闻形态setY(i,-x(i));
}
返回新闻形状;
}
请注意,我将每个形状的坐标存储在二维数组中。 另外,这是我的游戏引擎类:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class GameEngine extends JPanel implements ActionListener{

    private final int HEIGHT = 15;
    private final int WIDTH = 10;
    private int score;
    int coordX = 0;
    int coordY = 0;
    Timer timer;
    boolean isFinishedFalling = false;
    boolean isRunning = false;
    boolean isPaused = false;
    Shape block;
    String[] shapes;


    public GameEngine(){
        setFocusable(true);
        block = new Shape();
        timer = new Timer(600, this);
        timer.start();
        addMouseListener(new MAdapter());
        addMouseWheelListener(new WheelAdapter());
        addKeyListener(new KAdapter());
        setBackground(Color.BLACK);
        shapes = new String[WIDTH * HEIGHT];
        clearShapes();
    }

    int squareWidth() { return (int) getSize().getWidth() / WIDTH; }
    int squareHeight() { return (int) getSize().getHeight() / HEIGHT; }
    String shapeAt(int x, int y) { return shapes[(y * WIDTH) + x]; }
    public int getScore() {return score;}

    public void actionPerformed(ActionEvent e){
        if(isFinishedFalling){
            isFinishedFalling = false;
            newBlock();
        } else moveDown();
    }

    private boolean move(Shape newShape, int newCoordX, int newCoordY)
    {
        for (int i = 0; i < 4; ++i) {
            int x = newCoordX + newShape.x(i);
            int y = newCoordY - newShape.y(i);
            if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return false;
            if (!shapeAt(x, y).equals(Shape.DEFAULTSHAPE)) return false;
        }

        block = newShape;
        coordX = newCoordX;
        coordY = newCoordY;
        repaint();
        return true;
    }

    private boolean moveLeft() { return move(block, coordX-1, coordY);}
    private boolean moveRight() { return move(block, coordX+1, coordY);}
    private boolean moveDown(){
        if(!move(block, coordX, coordY-1)){
            blockIsDown();
            return false;
        } else return true;
    }

    private void dropDown(){
        int y = coordY;
        while(y>0){
            if(!move(block, coordX, y-1)) break;
            y -= 1;
        }
        blockIsDown();
    }

    private boolean rotate() { return move(block.rotate(), coordX, coordY);}

    private void blockIsDown(){
        for(int i=0; i<4; i++){
            int a = coordX + block.x(i);
            int b = coordY - block.y(i);
            shapes[b * WIDTH + a] = block.getShape();
        }
        clearFullLines();
        if(!isFinishedFalling) newBlock();
    }

    private void clearFullLines(){
        int fullLines = 0;
        for(int i = HEIGHT-1; i>=0; i--){
            boolean lineFull = true;
            for(int j=0; j<WIDTH; j++){
                if(shapeAt(j, i).equals(Shape.DEFAULTSHAPE)){
                    lineFull = false;
                    break;
                }
            }
            if(lineFull){
                fullLines++;
                for(int m=i; m<HEIGHT-1; m++){
                    for(int n=0; n<WIDTH; n++)
                        shapes[(m*WIDTH) + n] = shapeAt(n, m+1);
                }
            }
        }
        if(fullLines>0){
            score += fullLines*100;
            isFinishedFalling = true;
            block.setShape(Shape.DEFAULTSHAPE);
            repaint();
        }

    }

    private void newBlock()
    {
        block = new RandomShape();
        coordX = WIDTH / 2 + 1;
        coordY = HEIGHT - 1 + block.minY();

        if (!move(block, coordX, coordY)) {
            block.setShape(Shape.DEFAULTSHAPE);
            timer.stop();
            isRunning = false;
        }
    }

    private void clearShapes(){
        for(int i=0; i< WIDTH * HEIGHT; i++) shapes[i] = Shape.DEFAULTSHAPE;
    }

    private void drawSquare(Graphics g, int x, int y, String shape){
        Color color = Color.BLACK;
        if(shape.equals(Shape.ZSHAPE)) color = Color.GREEN;
        if(shape.equals(Shape.SSHAPE)) color = Color.RED;
        if(shape.equals(Shape.LINESHAPE)) color = Color.CYAN;
        if(shape.equals(Shape.TSHAPE)) color = Color.BLUE;
        if(shape.equals(Shape.SQUARESHAPE)) color = Color.YELLOW;
        if(shape.equals(Shape.LSHAPE)) color = Color.MAGENTA;
        if(shape.equals(Shape.MIRROREDLSHAPE)) color = Color.ORANGE;

        g.setColor(color);
        g.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2);
        g.setColor(color.brighter());
        g.drawLine(x, y + squareHeight() - 1, x, y);
        g.drawLine(x, y, x + squareWidth() - 1, y);

        g.setColor(color.darker());
        g.drawLine(x + 1, y + squareHeight() - 1,  x + squareWidth() - 1, y + squareHeight() - 1);
        g.drawLine(x + squareWidth() - 1, y + squareHeight() - 1, x + squareWidth() - 1, y + 1);
    }

    public void paint(Graphics g){
        super.paint(g);
        Dimension size = getSize();
        int top = (int) size.getHeight() - HEIGHT * squareHeight();
        for(int i=0; i<HEIGHT; i++){
            for(int j=0; j<WIDTH; j++){
                String s = shapeAt(j, HEIGHT-i-1);
                if(!s.equals(Shape.DEFAULTSHAPE))
                    drawSquare(g, j * squareWidth(), top + i * squareHeight(), s);
            }
        }
        if(!block.getShape().equals(Shape.DEFAULTSHAPE)){
            for(int i=0; i<4; i++){
                int x = coordX + block.x(i);
                int y = coordY - block.y(i);
                drawSquare(g, x * squareWidth(), top + (HEIGHT - y - 1) * squareHeight(), block.getShape());
            }
        }
    }

    public void start(){
        if(isPaused) return;
        isRunning = true;
        isFinishedFalling = false;
        score = 0;
        clearShapes();
        newBlock();
        timer.start();
    }

    private void pause(){
        if(!isRunning) return;
        isPaused = !isPaused;
        if(isPaused){
            timer.stop();

        } else{
            timer.start();

        }
        repaint();
    }

    class MAdapter extends MouseAdapter{
        public void mouseClicked(MouseEvent e){
            if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return;
            int buttonPressed = e.getButton();
            if(buttonPressed == MouseEvent.BUTTON1) moveLeft();
            if(buttonPressed == MouseEvent.BUTTON2) rotate();
            if(buttonPressed == MouseEvent.BUTTON3) moveRight();
        }
    }

    class WheelAdapter implements MouseWheelListener{
        public void mouseWheelMoved(MouseWheelEvent e){
            if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return;
            int wheelRotation = e.getWheelRotation();
            if(wheelRotation == 1) moveDown();
            if(wheelRotation == -1) dropDown();
        }
    }

    class KAdapter extends KeyAdapter{
        public void keyPressed(KeyEvent e){
            if (!isRunning || block.getShape().equals(Shape.DEFAULTSHAPE) || isPaused) return;
            int key = e.getKeyCode();
            if(key == KeyEvent.VK_SPACE) pause();
        }
    }
}
import javax.swing.*;
导入java.awt.*;
导入java.awt.event.*;
公共类GameEngine扩展JPanel实现ActionListener{
私人最终内部高度=15;
私有最终整数宽度=10;
个人智力得分;
int-coordX=0;
int-coordY=0;
定时器;
布尔值isFinishedFalling=false;
布尔值isRunning=false;
布尔值isPaused=false;
形状块;
字符串[]形状;
公共游戏引擎(){
设置聚焦(真);
块=新形状();
定时器=新定时器(600,此);
timer.start();
addMouseListener(新MAdapter());
addMouseWheelListener(新的WheelAdapter());
addKeyListener(新的KAdapter());
挫折背景(颜色:黑色);
形状=新字符串[宽度*高度];
透明形状();
}
int squareWidth(){return(int)getSize().getWidth()/WIDTH;}
int squareHeight(){return(int)getSize().getHeight()/HEIGHT;}
字符串shapeAt(intx,inty){returnshapes[(y*WIDTH)+x];}
public int getScore(){return score;}
已执行的公共无效操作(操作事件e){
如果(已完成校准){
isFinishedFalling=错误;
纽布洛克();
}else向下移动();
}
私有布尔移动(形状新形状、int-newCoordX、int-newCoordY)
{
对于(int i=0;i<4;++i){
int x=newCoordX+newShape.x(i);
int y=newCoordY-newShape.y(i);
如果(x<0 | | x>=宽度| | y<0 | | y>=高度)返回false;
如果(!shapeAt(x,y).equals(Shape.DEFAULTSHAPE))返回false;
}
块=新闻形状;
coordX=newCoordX;
coordY=新coordY;
重新油漆();
返回true;
}
私有布尔moveLeft(){返回move(block,coordX-1,coordY);}
私有布尔moveRight(){return move(block,coordX+1,coordY);}
私有布尔moveDown(){
如果(!移动(块,坐标x,坐标-1)){
blockIsDown();
返回false;
}否则返回true;
}
私有无效下拉列表(){
int y=坐标;
而(y>0){
如果(!move(block,coordX,y-1))中断;
y-=1;
}
blockIsDown();
}
私有布尔旋转(){返回移动(block.rotate(),coordX,coordY);}
私有void blockIsDown(){
对于(int i=0;i=0;i--){
布尔lineFull=true;

对于(int j=0;j删除旋转方法,为每个形状和所有4个旋转添加硬编码旋转数组。第一个索引应为旋转索引(0-3)

然后将成员变量添加到形状基类,并将旋转更改为类似以下内容:

public void rotate(Boolean rotateRight) {
  if (rotateRight) {
    rotation++;
  else { 
    rotation--;
  }
  if (rotation < 0) {
    rotation = 3;
  }
  if (rotation > 3) {
    rotation = 0;
  }
}

然后用这个int[][](或者int[]如果你想展平数组)画出合适的正方形

谢谢你的回复,但是在进一步调查之后,我发现了问题所在。 问题在于旋转方法:

public Shape rotate(){
        if (this.getShape().equals(SQUARESHAPE)) return this;
        Shape newShape = new Shape();
        newShape.shape = this.shape;
        for (int i = 0; i < 4; i++) {
            newShape.setX(i, -y(i));
            newShape.setY(i, x(i));
        }
        return newShape;
}
这是SShape的输出:

[[0, -1], [0, 0], [1, 0], [1, 1]]
[[1, 0], [0, 0], [0, 1], [-1, 1]]
[[0, 0], [0, 0], [-1, -1], [-1, -1]]
[[0, 0], [0, 0], [1, 1], [1, 1]]
[[0, 0], [0, 0], [-1, -1], [-1, -1]]
[[0, 0], [0, 0], [1, 1], [1, 1]]
[[0, 0], [0, 0], [-1, -1], [-1, -1]]
第一行包含我为SShape提供的初始坐标。第二行包含修改后的坐标,位于rotate()之后方法。如您所见,X取-Y值,Y取X值。但是,在第三行中,X取-Y值,但Y取更新后的X值,而不是上一行,因此从第三行开始X=Y。为了解决此问题,我制作了一个数组,在更新X值之前保存X值,如下所示:

protected void setX(int i, int x) { coords[i][0] = x; }
protected void setY(int i, int y) { coords[i][1] = y; }
public int x(int i) { return coords[i][0]; }
public int y(int i) { return coords[i][1]; }

public Shape rotate(){
        if (this.getShape().equals(SQUARESHAPE)) return this;
        Shape newShape = new Shape();
        newShape.shape = this.shape;
        for (int i = 0; i < 4; i++) {
            newShape.setX(i, y(i));
            newShape.setY(i, -x(i));
        }
        return newShape;
}
public Shape rotate(){
        if (this.getShape().equals(SQUARESHAPE)) return this;
        Shape newShape = new Shape();
        newShape.shape = this.shape;
        int[] oldX = {this.x(0), this.x(1), this.x(2), this.x(3)};
        for (int i = 0; i < 4; i++) {
            newShape.setX(i, -y(i));
            newShape.setY(i, oldX[i]);
        }
        return newShape;
}
公共形状旋转(){
如果(this.getShape().equals(SQUARESHAPE))返回该值;
形状newShape=新形状();
newShape.shape=this.shape;
int[]oldX={this.x(0),this.x(1),this.x(2),this.x(3)};
对于(int i=0;i<4;i++){
新闻形态setX(i,-y(i));
新闻形态setY(i,oldX[i]);
}
返回新闻形状;
}

您应该为每个形状创建一个颜色字段,而不是一系列if语句。您不需要旋转方法,只需在一个静态数组中硬编码每个工件配置。这是工件的4个数组。