1

我在java中制作俄罗斯方块是为了好玩......我几乎让一切正常......但后来发现当我想改变尺寸时它是方形的([10 row] [10 col]矩阵,而是[12 行][10 列] 矩阵),我开始收到索引超出范围异常...请参见此处:Java Tetris - 奇怪的行清除问题

因此,我尝试修复所有内容,以使行和列不会翻转...但是现在我对网格占用 [row] [col] 的事实感到困惑,但我正在围绕瓷砖移动(x , y) 坐标…

让我感到困惑的是 row = y 和 col = x ……这是相反的……所以当我传入坐标时,我不确定何时交换它们。

我知道这是一件简单的事情,但它让我很困惑,每当我认为我做对了时,我就会不断地越界。

我不确定确切的问题出在哪里,所以我发布了我的程序的完整 Sscce ......我认为问题出在董事会课程中......

在这里,块应该仍然能够向下移动......但如果它试图向下移动比这更远...... 在此处输入图像描述

我得到:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
    at Board.getTileAt(Board.java:177)
    at Tile.collision(Tile.java:31)
    at Piece.isCollision(Piece.java:172)
    at Board.collisionCheck(Board.java:192)
    at Piece.movePieceCheck(Piece.java:87)
    at Board.keyPressed(Board.java:160)

选址:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class MainSscce extends JPanel {
       static MainSscce runMe;
       BoardSscce gameBoard, scoreBoard;

       public MainSscce() {    //creates a new frame window and sets properties
              JFrame f = new JFrame("Tetris");
              //width (height), length, tilesize
              gameBoard = new BoardSscce(12, 10, 35);
             // scoreBoard = new BoardSscce(10, 10, 35);
              f.add(gameBoard);
              f.setSize(gameBoard.getWidth(), gameBoard.getHeight());
              f.setVisible(true);
              f.setResizable(false);
              f.setVisible(true);
              f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
              Dimension screensize = Toolkit.getDefaultToolkit().getScreenSize();
              //set j frame location to appear in middle of screen
              f.setLocation( (screensize.width - f.getWidth())/2,
                   (screensize.height - f.getHeight())/2-100 );
       }

       public static void main(String[] args) {
              runMe = new MainSscce();
       }

}


import java.awt.Graphics;
import java.awt.Color;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.Timer;

import java.awt.event.*; // for ActionListener and ActionEvent
import java.util.Random;

public class BoardSscce extends JPanel implements KeyListener {
    private TileSscce grid[][];
    private int totalRows, totalCols, tilesize, level, totalScore;
    private final int changeLevelMultiplier;
    private PieceSscce newPiece, nextPiece;
    private String randomPiece;
    private boolean gameLost;

    public BoardSscce(int r, int c, int ts) {
        totalRows = r;
        totalCols = c;
        tilesize = ts;
        //set grid size to [# rows][# columns], aka [height][width]
        grid = new TileSscce[totalRows][totalCols];
        gameLost = false;

        System.out.println("TotalRows: " + totalRows + ", " + "TotalCols: " + totalCols);

        //multiplier to determine what score the level changes, which is:
        //level * changeLevelMultiplier;
        changeLevelMultiplier = 40;

        //initialize score to 0
        totalScore = 0;

        //initialize level to 0
        level = 0;

        newPiece = new PieceSscce(this, randomPiece(), getColor());
        addKeyListener(this);
        setFocusable(true);
        //getTranspose();

        timer();

    }

    public String randomPiece() {
        String[] Pieces = {"L", "O", "Z", "RevZ", "Bar", "T", "RevL"};

        int rand = (int) (Math.random() * Pieces.length);
        randomPiece = Pieces[rand];

        return randomPiece;
    }

    public Color getColor() {
        Color color;
        if (randomPiece.equals("L")) 
            color = new Color(17, 255, 0);
        else if(randomPiece.equals("O"))
            color = new Color(117, 168, 255);
        else if(randomPiece.equals("Z"))
            color = new Color(255, 187, 82);
        else if(randomPiece.equals("RevZ"))
            color = new Color(206, 27, 72);
        else if(randomPiece.equals("Bar"))
            color = new Color(50, 216, 219);
        else if(randomPiece.equals("T"))
            color = new Color(252, 148, 240);
        else 
            color = new Color(255, 255, 52);    

        //Random rand = new Random();
        //float r = rand.nextFloat();
        //float g = rand.nextFloat();
        //float b = rand.nextFloat();
        //Color randomColor = new Color(r, g, b);

        return color;
    }

    //dimensions of board = width * tilesize
    public int getWidth() {
        return totalCols * tilesize; 
    }

    public int getHeight() {
        return totalRows * tilesize;
    }

    public int getTileSize() {  
        return 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++) {
                //System.out.println(row + ", " + col);
                g.drawString("[" + row + "][" + col + "]", col * tilesize, row * tilesize+10);
                System.out.println(row + ", " + col);
                //if there is a non-null space, that is a Tetris piece... fill it
                if(grid[row][col] != null) {            
                    g.setColor(grid[row][col].getColor());
                    g.fillRect(row * tilesize, col * tilesize, tilesize, tilesize);
                    g.setColor(Color.WHITE);
                }
            }
        }
        //  g.drawString("Level: " + level, this.getWidth()/2, this.getHeight()/2-130);
        //  g.drawString("Score: " + totalScore, this.getWidth()/2, this.getHeight()/2-100);

            if (gameLost == true) {
                g.drawString("Way to go, loser...", this.getWidth()/2, this.getHeight()/2);
                messageTimer();
            }
        }

    //Auto move piece
    public void timer () {
        int interval;
        switch (level) {
        //each level increases drop speed by .10 seconds
            case 1: interval = 800;
                    break;
            case 2: interval = 700;
                    break;
            case 3: interval = 600;
                    break;
            case 4: interval = 500;
                    break;
            default: interval = 1000;
                    break;
        }
        Timer t = new Timer(interval, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
               //newPiece.autoMove();
               //repaint();
            }
         });
        t.start();
    }    

    public void messageTimer()   {
        Timer t = new Timer(5000, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                gameLost = false;
            }
         });
        t.start();      
    }

    //move piece on key input
    public void keyPressed(KeyEvent e) {
        newPiece.movePieceCheck(e.getKeyCode());        
        repaint();  
    }

    public void keyReleased(KeyEvent e) {
    }

    public void keyTyped(KeyEvent e) {
    }

    public boolean isValidCoordinate(int x, int y) {
        return x >= 0 && y >= 0 && x < totalCols && y < totalRows; 
    }

    // returns the tile at (x, y) or null if empty
    public Tile getTileAt(int x, int y) {
        if(isValidCoordinate(x, y))
            return grid[x][y];
        return null;
    }

    // sets the tile at (x, y) to tile
    public void setTileAt(Tile tile, int x, int y) {
        if(isValidCoordinate(x, y))     
            grid[x][y] = tile;
    }

    public boolean isOpen(int x, int y) {
        return isValidCoordinate(x, y) && (getTileAt(x, y) == null);
    }

    public void collisionCheck() {
        if (newPiece.isCollision()){
            newPiece = new PieceSscce(this, randomPiece(), getColor());
        }       
    }

    public void changeLevel () {
        int max = (level+1)*changeLevelMultiplier;
        if (totalScore >= max) {
            System.out.println(max + "reached... next level");
            level++;
            totalScore = 0;
            timer();
        }
    }

    public int tallyScore(int totalLines) {
        int score = 0;
        switch (totalLines) {
            case 1: score = 40 * (level + 1);
                    break;
            case 2: score = 100 * (level + 1);
                    break;
            case 3: score = 300 * (level + 1);
                    break;
            case 4: score = 1200 * (level + 1);
                    break;
            default: break;
        }
        return score;
    }

    //loop through all rows starting at bottom (12 rows)
    public void checkBottomFull() {
        int lines = 0;
        for(int row = 12; row > 0; row--) {
        /*  while (isFull(row)) {       
                lines++;
               // clearRow(row);   
            }*/
        }
        totalScore += tallyScore(lines);    
        //check if level needs to be changed based on current score...
        changeLevel();
        //reset lines after score has been incremented
        lines=0;
    }
    //loop through all columns in that row (10 columns)
    public boolean isFull(int row) {
        for (int col = 0; col <= 10; col++) {
          System.out.println(row + ", " + col);
              if(grid[row][col] == null) {
                 return false;
            }
        }
        return true;
    }

    public void clearRow(int rowToClear) {
         for(int row = rowToClear; row > 0; row--) {
             for(int col = 0; col < grid[row].length; col++) {
                grid[col][row] = grid[col][row-1];
             }
         }
    }

    public void checkEndGame(int x, int y) {
        //if currPiece y location = 0 AND the space below is filled... 
        if (y <= 2 && !isOpen(x, y+1)) {
            gameLost = true;
            level = 0;
            totalScore = 0;
            //reset timer
            timer();
            for(int row = 0; row < grid.length; row++) {
                for(int col = 0; col < grid[row].length; col++) {
                    grid[row][col] = null;              
                }       
            }
        }       
    }
}




import java.awt.Color;
import java.awt.event.KeyEvent;


public class PieceSscce {
    public int[] pieceCoordinates;
    public String shape, currRotation;
    public Color color;
    public BoardSscce board;    
    public int rotationsCounter;
    public TileSscce tile[];

    public int[] newPositionX, newPositionY, currPositionX, currPositionY;

    //don't need to pass in board because I'm already utilizing the Tiles class, which knows about the board
    public Piece(Board b, String randomPiece, Color randomColor) {
        shape = randomPiece;
        color = randomColor;
        board = b;

        newPositionX = new int[4];
        newPositionY = new int[4];
        currPositionX = new int[4];
        currPositionY = new int[4];
        pieceCoordinates = new int[8];


        //set pieceCoordinates global variable
        getShape(shape);
        tile = new TileSscce[4];

        int counterX = 0, counterY = 1;
        System.out.print("\"" + shape + "\" Coordinates: ");
        //generate 4 new Tiles at specified coordinates that will compose the Piece
        for (int i = 0; i < tile.length; i++) {
            tile[i] = new TileSscce(board, pieceCoordinates[counterX], pieceCoordinates[counterY]);
            System.out.print("(" + pieceCoordinates[counterX] + ", " + pieceCoordinates[counterY] + ") ");
            //increment by 2 because x,y values are next to each other in array
            counterX+=2;
            counterY+=2;    
        }
        System.out.println("\n");

        for (int i = 0; i < tile.length; i++) {
            tile[i].setColor(color);
        }
    }

    public void calcNewPosition(int newX, int newY, int currTile) {             
        newPositionX[currTile] = newX;
        newPositionY[currTile] = newY;
    }

    public void clearCurrPosition() {   
        for (int i = 0; i < tile.length; i++) {
            currPositionX[i] = tile[i].getX();
            currPositionY[i] = tile[i].getY();  
            board.setTileAt(null, currPositionX[i], currPositionY[i]);
        }   
    }       

    public void autoMove() {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getX(), tile[i].getY()+1, i);                               
        }       
        clearCurrPosition();
        for (int i = 0; i < tile.length; i++) {
            board.checkEndGame(tile[i].getX(), tile[i].getY());
            System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
        }
        board.checkBottomFull();
        board.collisionCheck(); 
        move();
    }

    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();
            for (int i = 0; i < tile.length; i++) {
                board.checkEndGame(tile[i].getX(), tile[i].getY());
                System.out.println("Checking..." + tile[i].getX() + ", " + tile[i].getY());
            }   
            board.checkBottomFull();
            board.collisionCheck(); 
            move();
        }
        if (keycode == KeyEvent.VK_RIGHT) {
            for (int i = 0; i < tile.length; i++) {
                calcNewPosition(tile[i].getX()+1, tile[i].getY(), i);
            }       
            clearCurrPosition();
            move();
        }
        if (keycode == KeyEvent.VK_LEFT) {
            for (int i = 0; i < tile.length; i++) {
                calcNewPosition(tile[i].getX()-1, tile[i].getY(), i);
            }       
            clearCurrPosition();
            move();
        }
        //rotate left
        if (keycode == KeyEvent.VK_A) {     
            int[] rotatedCoords = calcRotation("left");
            clearCurrPosition();
            rotate(rotatedCoords, "left");
        }

        //rotate right
        if (keycode == KeyEvent.VK_D) {
            int[] rotatedCoords = calcRotation("right");
            clearCurrPosition();
            rotate(rotatedCoords, "right");     
        }
    }

    public boolean movePieceValid() {   
        boolean valid = true;
        for (int i = 0; i < tile.length; i++) {
            if(!tile[i].checkNewLocation(newPositionX[i], newPositionY[i])) 
                valid = false;

        }       
        return valid;
    }       

    public boolean validRotation(int[] rotatedCoordinates) {
        boolean valid = true;
        int counterX = 0, counterY = 1;
        for (int i = 0; i < tile.length; i++) {
            if(!tile[i].checkNewLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY])) 
                valid = false;
            counterX +=2;
            counterY +=2;
        }       
        return valid;
    }

    public void move()   {      
        if (movePieceValid()) {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(newPositionX[i], newPositionY[i]);              
            }       
        } else {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(currPositionX[i], currPositionY[i]);                
            }   
        }       
    }

    public void rotate(int[] rotatedCoordinates, String rotation) {
        int counterX = 0, counterY = 1;
        if (validRotation(rotatedCoordinates)) {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(rotatedCoordinates[counterX], rotatedCoordinates[counterY]);                
                counterX+=2;
                counterY+=2;
            }
        //else, if not valid move set the original location
        } else {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(currPositionX[i], currPositionY[i]);                
            }   
        }           
    }

    public boolean isCollision()    {
        boolean collision = false;
        for (int i = 0; i < tile.length; i++) {
            if(tile[i].collision(newPositionX[i], newPositionY[i])) {
                collision = true;
            }
        }
        return collision;
    }

    //calc curr coordinates, send them to getRotation... which will create new piece based on coords
    public int[] calcRotation(String direction) {   
        for (int i = 0; i < tile.length; i++) {
            currPositionX[i] = tile[i].getX();
            currPositionY[i] = tile[i].getY();  
            System.out.println("Current position: (" + currPositionX[i] + "," + currPositionY[i]+")");
        } 
        return getRotation(currPositionX, currPositionY, direction);
    }

    public int[] getRotation (int coordinatesX[], int coordinatesY[], String direction) {

        int[] rotationDirection;

        int[] coordinates = new int[8];
        int[] origin = new int[2];
        int[] newCoordinates = new int[8];
        int[] resultCoordinates = new int[8];
        int[] finalCoordinates = new int[8];

        int vectorMatrix[][] = new int[2][4];

        //set either R(90) or R(-90) rotation matrix values:
        if (direction.equals("right")) {
            rotationDirection = new int[] {0, -1, 1, 0}; 
        }
        else {
            rotationDirection = new int[] {0, 1, -1, 0}; 
        }

        int counterX = 0, counterY = 1, x = 0;
        while (counterY < coordinates.length) {
            //add arrays coordinatesX and coordinatesY into a single array: coordinates 
            coordinates[counterX] = coordinatesX[x];
            coordinates[counterY] = coordinatesY[x];
            counterX+=2;
            counterY+=2;
            x++;
        }   

        //set origin so it rotates around center...
        if (shape.equals("RevZ")) {
            origin[0] = coordinates[6];
            origin[1] = coordinates[7];
        }
        else if (shape.equals("T")) {
            origin[0] = coordinates[4];
            origin[1] = coordinates[5];         
        }
        else {
            origin[0] = coordinates[2];
            origin[1] = coordinates[3];
        }


        //subtract origin from vectors
        System.out.println();
        counterX = 0;
        counterY = 1;
        while (counterY < newCoordinates.length) {
            //System.out.println(coordinates[counterX] + ", " + coordinates[counterY]);
            newCoordinates[counterX] = coordinates[counterX] - origin[0];
            newCoordinates[counterY] = coordinates[counterY] - origin[1];
            System.out.println("Translated coordinates: (" + newCoordinates[counterX] + ", " + newCoordinates[counterY] + ")");
            counterX+=2;
            counterY+=2;
        }
        System.out.println();
        System.out.println("vector matrix:");

        //fill up vectorMatrix with coordinates
        int k = 0;
        for (int col = 0; col < 4; col++) {
            for (int row = 0; row < 2; row++) {
                vectorMatrix[row][col] = newCoordinates[k++];
            }
        }

        //print vectorMatrix:
        for (int i = 0; i < vectorMatrix.length; i++) {
            System.out.print("[");
            for (int j = 0; j < vectorMatrix[i].length; j++) {
                System.out.print(vectorMatrix[i][j]);
            }
            System.out.println("]");
        }

        int rotationMatrix[][] = new int[2][2];

        //fill up rotationMatrix
        System.out.println();
        System.out.println("multiplicative matrix:");
        k = 0;
        for (int row = 0; row < 2; row++) {
            System.out.print("[");
            for (int col = 0; col < 2; col++) {
                rotationMatrix[row][col] = rotationDirection[k++];
                System.out.print(rotationMatrix[row][col]);
            }
            System.out.println("]");
        }   

        //perform matrix multiplication
        int[][] result = multiplyMatrices(rotationMatrix, vectorMatrix);

        //print resulting matrix
        System.out.println();
        System.out.println("result matrix:");
        for (int i = 0; i < result.length; i++) {
            System.out.print("[");
            for (int j = 0; j < result[i].length; j++) {
                System.out.print(result[i][j]);
            }
            System.out.println("]");
        }       

        //load new matrix coordinates back into array
        k = 0;
        for (int col = 0; col < 4; col++) {
            for (int row = 0; row < 2; row++) {
                resultCoordinates[k] = result[row][col];
                k++;
            }
        }       

        System.out.println();
        System.out.println("result coordinates:");
        counterX = 0;
        counterY = 1;

        while (counterY < resultCoordinates.length) {
            finalCoordinates[counterX] = resultCoordinates[counterX] + origin[0];
            finalCoordinates[counterY] = resultCoordinates[counterY] + origin[1];
            System.out.print("("+finalCoordinates[counterX] + ", " + finalCoordinates[counterY]+")");

            counterX+=2;
            counterY+=2;
        }   

        return finalCoordinates;    
    }   

    public int[][] multiplyMatrices(int rotationMatrix[][], int vectorMatrix[][]) {
        int mA = rotationMatrix.length;
        int nA = rotationMatrix[0].length;
        int mB = vectorMatrix.length;
        int nB = vectorMatrix[0].length;
        if (nA != mB) throw new RuntimeException("Illegal matrix dimensions.");
        int[][] C = new int[mA][nB];
        for (int i = 0; i < mA; i++) {
            for (int j = 0; j < nB; j++) {
                for (int k = 0; k < nA; k++) {
                    C[i][j] += (rotationMatrix[i][k] * vectorMatrix[k][j]);
                }
            }
        }
        return C;
    }

    public int[] getShape(String shape) {

        if (shape.equals("L")) {
            //pieceCoordinates = new int[] {0, 1, 0, 2, 1, 2, 2, 2}; 
            pieceCoordinates = new int[] {4, 0, 4, 1, 5, 1, 6, 1}; 
        }
        else if (shape.equals("O")) {
            pieceCoordinates = new int[] {0, 1, 1, 1, 0, 2, 1, 2};                              
        }
        else if (shape.equals("Z")) {

            pieceCoordinates = new int[] {0, 1, 1, 1, 1, 2, 2, 2};                          
        }
        else if (shape.equals("RevZ")) {
            pieceCoordinates = new int[] {1, 1, 2, 1, 0, 2, 1, 2};                          
        }
        else if (shape.equals("Bar")) {
            //pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
            pieceCoordinates = new int[] {0, 1, 1, 1, 2, 1, 3, 1};
        }
        else if (shape.equals("T")) {
            pieceCoordinates = new int[] {1, 1, 0, 2, 1, 2, 2, 2};                  
        }
        else if (shape.equals("RevL")) {
            pieceCoordinates = new int[] {0, 2, 1, 2, 2, 2, 2, 1}; 
        }
        return pieceCoordinates;
    }
}


import java.awt.Color;
import java.util.Random;

public class TileSscce {
    private BoardSscce board;
    private int currX, currY;
    private Color color;

    public TileSscce(BoardSscce b, int x, int y) {

        board = b;

        //when Tile is instantiated, set its position
        setLocation(x, y);
    }

    public int getX() {
        return currX; 
    }

    public int getY() {
        return currY;
    }

    public boolean checkNewLocation(int newX, int newY) {
          boolean newLocationOK = board.isOpen(newX, newY);
          return newLocationOK;
        }   

    public boolean collision(int newX, int newY) {
        boolean collision = this.getY() == ((board.getHeight()/board.getTileSize()))-2 || board.getTileAt(newX, newY) != null;
        return collision;
    }

    public void setLocation(int newX, int newY) {
        //  board.setTileAt(null, currX, currY);
            currX = newX;
            currY = newY;
            board.setTileAt(this, currX, currY); 
    }



    public Color getColor() {
        return setColor(color);
    }

    public Color setColor(Color myColor) {  
        color = myColor;
        return color;
    }


}

谢谢!

编辑---------- 我已经尝试过实施 ValarDohaeris 和 Svend Hansen 的建议......现在当我按下时块向右移动,当我按下左时向上移动,当我按下右时向下移动.. .

在此处输入图像描述

它似乎与 Board 类中的这些方法有关,这些方法获取和设置图块位置......

// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
    System.out.println("getTileAt: " + row + ", " + col);
    if(isValidCoordinate(row, col))
        return grid[row][col];
    return null;
}

// sets the tile at (x, y) to tile
public void setTileAt(Tile tile, int row, int col) {
    System.out.println("setTileAt: " + row + ", " + col);
    if(isValidCoordinate(row, col))     
        grid[row][col] = tile;
}

在 Piece 类中......动作被定义为:

public void movePieceCheck(int keycode) {   
    if (keycode == KeyEvent.VK_DOWN) {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);                               
        }       
        clearCurrPosition();
        for (int i = 0; i < tile.length; i++) {
            board.checkEndGame(tile[i].getRow(), tile[i].getCol());
        }   
        board.checkBottomFull();
        if (isCollision()) board.createNewPiece();
        move();
    }
    if (keycode == KeyEvent.VK_RIGHT) {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
        }       
        clearCurrPosition();
        move();
    }
    if (keycode == KeyEvent.VK_LEFT) {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getRow(), tile[i].getCol()-1, i);
        }       
        clearCurrPosition();
        move();
    }
4

3 回答 3

3

嗯……很有趣的问题。因此,要找出问题可能出在哪里,我将尝试稍微分析您的代码...

您将堆栈跟踪粘贴为

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
    at Board.getTileAt(Board.java:177)
...

同时getTileAt()

// returns the tile at (x, y) or null if empty
public Tile getTileAt(int row, int col) {
    System.out.println("getTileAt: " + row + ", " + col);
    if(isValidCoordinate(row, col))//isValidCoordinate()? 
        return grid[row][col];
    return null;
}

public boolean isValidCoordinate(int x, int y) {
        return x >= 0 && y >= 0 && x < totalCols && y < totalRows; 
    }

...所以 isValidCoordinate 方法返回术语为

x >= 0 && y >= 0 && x < totalCols && y < totalRows

...该方法不允许避免数组越界问题;好像你放了错误的数组元素索引。

A.正如我所注意到的,您试图在 Java [][] 数组上放置一个经典的数学矩阵

public void clearRow(int rowToClear) {
         for(int row = rowToClear; row > 0; row--) {
             for(int col = 0; col < grid[row].length; col++) {//<-- ?
                grid[col][row] = grid[col][row-1];
             }
         }
    }

...在这里我必须说你应该知道在[][] 数组中 x,y是向后的,它是y,x因为:

  • y(或经典 i)- 子数组索引(垂直)
  • x(或经典 j)- 子数组的元素索引(水平)

所以你应该以这种方式使用数组索引grid[y][x] or grid[i][j]

作为一个有用的提示,我建议您分析您的代码以查找该字段中的逻辑错误...

B.根据您的应用截图为

在此处输入图像描述

...似乎x,y问题也发生在这里,因为您试图控制 y (垂直)坐标,但(实际上)您仅控制 x (水平)坐标:S 这仍然是因为row,col而不是经典Java (col,row或y,x) [] []数组索引位置。

C.再一次关于错误的方向......

...当我按左时向上,当我按右向下...

if (keycode == KeyEvent.VK_RIGHT) {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
        }       
        clearCurrPosition();
        move();
    }

在这里,我将尝试将事件分析为(您按右但向下移动)...

好的...根据您的一项任务,您需要按x坐标(水平)移动,但仔细观察...您tile[i].getCol()+1这样做了newY,当然,它垂直移动:S在您的情况下,它确实向下移动因为您使增量为y++ ...

public void calcNewPosition(int newX, int newY, int currTile) {             
        newPositionX[currTile] = newX;
        newPositionY[currTile] = newY;
    }

    public void clearCurrPosition() {   
        for (int i = 0; i < tile.length; i++) {
            currPositionX[i] = tile[i].getX();
            currPositionY[i] = tile[i].getY();  
            board.setTileAt(null, currPositionX[i], currPositionY[i]);
        }   
    }  



public void move()   {      
        if (movePieceValid()) {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(newPositionX[i], newPositionY[i]);//<-- !            
            }       
        } else {
            for (int i = 0; i < tile.length; i++) {
                tile[i].setLocation(currPositionX[i], currPositionY[i]);                
            }   
        }       
    }

...作为结论,我可能会建议以这种方式更改代码(向右移动) ...

if (keycode == KeyEvent.VK_RIGHT) {
        for (int i = 0; i < tile.length; i++) {
            calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
        }       
        clearCurrPosition();
        move();
    }

我希望我的建议能帮助你弄清楚要仔细观察什么。无论如何,如果您有其他信息,请评论我的回答


报告是否对您有帮助

于 2013-05-09T01:19:26.913 回答
3

你有

grid = new TileSscce[totalRows][totalCols];

所以当你想访问时grid[x][y],你应该检查

x >= 0 && y >= 0 && x < totalRows && y < totalCols

isValidCoordinate(x, y).

于 2013-05-03T16:23:37.553 回答
2

这是基于 x 对应于列,y 对应于行。
然而,网格由 [row][col] 索引。

TileSscce grid[][] = new TileSscce[totalRows][totalCols]; // 12 => totalRows, 10 => totalCols

public int getWidth() {
    return totalCols * tilesize;
}

public int getHeight() {
    return totalRows * tilesize;
}

以下更改(基于您的初始代码 - Sscce: - 无需稍后编辑)将消除异常并允许绘制到板底。

public void paintComponent(Graphics g) {
    for (int row = 0; row < grid.length; row++) {
        for (int col = 0; col < grid[row].length; col++) {
            if (grid[row][col] != null) {
                g.setColor(grid[row][col].getColor());
                g.fillRect(col * tilesize, row * tilesize, tilesize, tilesize); // changed, check below snippet from fillRect documentation
                g.setColor(Color.WHITE);
            }
        }
    }
}

public TileSscce getTileAt(int x, int y) {
    if (isValidCoordinate(x, y))
        return grid[y][x]; // changed to [y][x] as grid is indexed by [row][col]
    return null;
}

public void setTileAt(TileSscce tile, int x, int y) {
    if (isValidCoordinate(x, y))
        grid[y][x] = tile; // changed to [y][x] as grid is indexed by [row][col]
}

来自 fillRect 文档。

public abstract void fillRect(int x, int y, int width, int height)
    The left and right edges of the rectangle are at x and x + width - 1.
    The top and bottom edges are at y and y + height - 1.

这是对的。

public boolean isValidCoordinate(int x, int y) {
    return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}
于 2013-05-09T14:34:58.893 回答