2013-05-03 95 views
1

我在俄羅斯方塊在Java的樂趣...我幾乎有一切工作......但後來發現,當我想要改變尺寸,使其成爲方形([10行] [10列]矩陣,而是[12行] [10列]矩陣),我開始獲得索引超出界限的例外...請參閱:Java Tetris - weird row clearing issue爪哇俄羅斯方塊 - 困惑網格[行] [col]和座標(x,y)

所以我試着修復所有的東西,以便行和列不被翻轉......但現在越來越多的事實上,網格需要[行] [col],但我正在移動瓷磚作爲(x,y)座標...

令人困惑的是,行= y和col = x ...這是顛倒的...所以當我傳入座標我不確定何時交換它們。

我知道這是一件簡單的事情,但它讓我感到困惑,並且每當我認爲自己的行爲正確時,我總是越界越界。

我不知道其確切的問題,所以我張貼我的程序的完整SSCCE ......我認爲這個問題是在董事會類...

這裏,此塊應仍然能夠上下移動...但如果它試圖走得更遠比這個... enter image description here

我得到:

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) 

SSCCE:

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和斯文·漢森的建議......現在該塊向右移動,當我按下去,起來,我按離開時,和下來的時候我按正確的...

enter image description here

這似乎與這些方法在董事會類get和set瓷磚的位置做...

// 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; 
} 

而在片類...運動被定義爲:

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(); 
    } 
+3

我不認爲這符合一個ShortSCC的定義.. – Marco 2013-05-03 16:16:00

+3

我以前也有類似的困惑,並發現它幫助只是重命名x和y爲i和j和思維只行/列數字(而不是有時行/列數字,有時作爲x/y座標)。當然,這並不能解決問題,但它可能會更容易找到並避免將來重新引入:) – 2013-05-03 16:32:46

+0

@Growler它是如何發展的?你成功解決座標問題了嗎? – user592704 2013-05-09 22:44:20

回答

3

你有

grid = new TileSscce[totalRows][totalCols]; 

所以,當您要訪問grid[x][y],你應該在isValidCoordinate(x, y)檢查

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

+0

現在允許被阻擋的屏幕向右移動(列),但仍然不允許移動到下面的可用行(10和11)。雖然現在它不會拋出異常,當我嘗試再次向下移動時......它根本不會移動,所有 – Growler 2013-05-03 16:31:28

+0

並不是我的x軸,因此您需要檢查總數列(因爲x軸跨越列),我的'y'在y軸上,所以你需要檢查'rows',因爲y訪問跨越所有行...我錯了嗎? – Growler 2013-05-03 16:51:11

1

行和列的概念在數組中實際上有些隨意。爲什麼不把陣列足夠大,只是映射陣列直接座標(X,Y)座標爲:

array[x][y] -> point(x,y) 

你可以做的另一件事是做一個get和set函數來訪問他們而言陣列x,y座標,所以你不必擔心它...

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(或經典ⅰ) - 子陣列索引(Vertica的L)
  • X(或經典j)的 - 子數組的元素索引(水平)

所以你應該使用數組索引的東西這樣grid[y][x] or grid[i][j]

作爲一個有用的技巧,我建議你分析你在這個領域中的邏輯錯誤代碼......

B.根據您的應用程序的截圖作爲

enter image description here

...好像在X,Y問題發生在這裏太,因爲你試圖控制Ÿ(垂直)座標,但(實際)可以控制X (水平)只有座標:S它仍然是因爲而不是經典的Java數組索引位置。

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(); 
    } 

在這裏,我會試着分析事件爲(你按正確的,但向下移動)...

OK ......根據你的任務之一你需要用x座標移動(水平),但仔細看......你讓tile[i].getCol()+1所以它是newY,當然,它垂直移動:在你的情況下,它真的移動下來,因爲你做增量爲Ÿ++。 ..

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(); 
    } 

我希望我的建議將幫助你找出更近的地方。無論如何,如果你有一些額外的信息,請這是基於x做評論我的回答


報告如果幫你

1

對應列和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; 
} 
+0

謝謝,交換網格[] []中的x和y使其向下移動,但是當我到達第9行並嘗試再次向下移動時,它會拋出一個'ArrayIndexOutOfBoundsException:10在Board.getTileAt,Tile.collision,at Piece.isCollision,在Piece.movePieceCheck上,在Board.keyPressed ...' – Growler 2013-05-09 15:02:13

+0

@Growler您之前的嘗試可能會導致此問題發生其他更改。我使用了你的初始代碼(在Sscce中:)而沒有在後面添加其他編輯。我所有的變化都是'g。fillRect()','getTileAt()'和'setTileAt()',如上面註釋中所示。在第10行的索引給出異常意味着,行/ y col/x swap仍然不完整。 – Sithsu 2013-05-09 15:27:21