memory game random color - java

Hey everybody I'm creating a memory game that uses a 4x4 2Darray.
I have the 4x4 filld with a pair of integers from 0-7 and they are randomly scattered. I want to assign a color to each pair, so when the mouse clicks over that square the assigned color will appear based on the integer and you will have to find the other integer based on it's corresponding matching color.
I've been running into some problems with this setColor method of mine. I'm going to include my whole code in case I messed up somewhere else and that was why. At the moment if I click every square once I use all 8 colors I assigned twice, but some of the colors don't match up to where the same integer is at on another tile. Also when I click the same tile multiple times it changes between 2-3 colors and I'm not sure what I'm doing wrong.
The parts I need advice on are the setColor method I have assigned and my logic behind it.
/*Sets the background of your memory board to black*/
public void init()
{
setSize(400,400);
setBackground(Color.BLACK);
buildBoard(4);
}
/*This is main in java applets
You may need to add (not
change) a couple things in this method
*/
public void paint(Graphics canvas)
{
if(firstRun) //for the first run we need to build our random board
{
print2DArray(board);
buildBoard(4);
firstRun = false;
}
else // once our board is built we will display the game
{
displayGame(canvas);
if (mouseClicked) // if the mouse has been clicked
{
displayHit(canvas);//find which box the user clicked
mouseClicked = false;
}
}
}
/*
DO NOT change this method
determines if the mouse has been pressed
sets x and y Mouse to the location of the mouse arrow
redraws the image
*/
public boolean mouseDown(Event e, int x, int y )
{
mouseClicked = true;
xMouse = x;
yMouse = y;
repaint();
return true;
}
/*DO NOT change this method
redraws the scene
*/
public void update ( Graphics g )
{
paint(g);
}
/*
pre: none
post: build an array that holds the memory values for a board of size x size
the board will hold two of each int from 0 to size randomly placed in the array
*/
public static void fillRect(Graphics g, int x, int y, int width, int length)
{
g.setColor(Color.BLACK);
width = 100;
length = 100;
x = (int)xMouse/100;
y = (int)yMouse/100;
}
public void buildBoard(int s)
{
int a = 4;
for (int row = 0; row < a; row++)
for (int column = 0; column < a; column++)
{
board[row][column] = count++ % 8;
}
for(int row = 0; row < 4; row++)
for(int column = 0; column < 4; column ++)
{
int x = (int)Math.floor(Math.random()*4);
int y = (int)Math.floor(Math.random()*4);
temp = board[row][column];
board[row][column] = board[x][y];
board[x][y] = temp;
}
}
public static void print2DArray(int[][] arr)
{
for (int row = 0; row < arr.length; row++)
{
for (int col = 0; col < arr[row].length; col++)
{
System.out.print(arr[row][col] + " ");
}
System.out.println();
}
}
public void displayGame(Graphics canvas)
{
canvas.setColor(Color.WHITE);
for(int i =0; i < 400; i+= WIDTH)
for(int j = 0; j < 400; j+= WIDTH)
canvas.drawRect(i, j, WIDTH, WIDTH);
}
/*
Pre: xMouse and yMouse have been initialized
Post: A circle is displayed in the correct box on the screen
Currently the circle is displayed at the mouse location
*/
public void displayHit(Graphics g)
{
/*int xGuess = (int)xMouse/100;
int yGuess = (int)yMouse/100;
board[xGuess][yGuess] = guess1;
int xGuess2 = (int)xMouse/100;
int yGuess2 = (int)yMouse/100;
board[xGuess2][yGuess2] = guess2;
if (guess1 == guess2)
{
setColor(g);
centerHit(xMouse, yMouse);
g.fillOval(xMouse, yMouse, 40, 40);
}
else
g.fillRect(guess1, guess2, width, length);
g.setColor(Color.BLACK);*/
setColor(g);
centerHit(xMouse, yMouse);
g.fillOval(xMouse, yMouse, 40, 40);
}
public void setColor(Graphics g)
{
centerClick(x1,y1);
//int x = xMouse;
//int y = yMouse;
colorIndex = board[row][column];
board[row][column] = board[x1][y1];
board[x1][y1] = colorIndex;
switch(colorIndex)
{
case 0: g.setColor(Color.RED);
break;
case 1: g.setColor(Color.GREEN);
break;
case 2: g.setColor(Color.BLUE);
break;
case 3: g.setColor(Color.ORANGE);
break;
case 4: g.setColor(Color.CYAN);
break;
case 5: g.setColor(Color.MAGENTA);
break;
case 6: g.setColor(Color.PINK);
break;
case 7: g.setColor(Color.YELLOW);
break;
}
}
public void centerHit(int centerX, int centerY)
{
{
if ((xMouse > 0) && (xMouse <=100))
xMouse = 33;
else if ((xMouse > 100) && (xMouse <=200))
xMouse = 133;
else if ((xMouse > 200) && (xMouse <=300))
xMouse = 233;
else if ((xMouse > 300) && (xMouse <=400))
xMouse = 333;
}
{
if ((yMouse > 0) && (yMouse <=100))
yMouse = 33;
else if ((yMouse > 100) && (yMouse <=200))
yMouse = 133;
else if ((yMouse > 200) && (yMouse <=300))
yMouse = 233;
else if ((yMouse > 300) && (yMouse <=400))
yMouse = 333;
}
}
public void centerClick(int centerX, int centerY)
{
{
if ((xMouse > 0) && (xMouse <=100))
x1 = 0;
else if ((xMouse > 100) && (xMouse <=200))
x1 = 1;
else if ((xMouse > 200) && (xMouse <=300))
x1 = 2;
else if ((xMouse > 300) && (xMouse <=400))
x1 = 3;
}
{
if ((yMouse > 0) && (yMouse <=100))
y1 = 0;
else if ((yMouse > 100) && (yMouse <=200))
y1 = 1;
else if ((yMouse > 200) && (yMouse <=300))
y1 = 2;
else if ((yMouse > 300) && (yMouse <=400))
y1 = 3;
}
}
}

to keep the colors from changing, change this code
colorIndex = board[row][column];
board[row][column] = board[x1][y1];
board[x1][y1] = colorIndex;
to
colorIndex = board[x1][y1];
the color matching issue is because youre building the board twice: first on the firstRun of the paint method where you print the array and then on the initmethod where the board gets overwritten so you see different values
to solve it you should build the board only once in the init method, and call print2DArray afterwards to check it, so
buildBoard(4);
print2DArray(board); //<-- add this line to verify colors
and you could omit the firstRun flag and all associated code.
comment or delete this code:
/*if(firstRun) //for the first run we need to build our random board
{
print2DArray(board);
buildBoard(4);
firstRun = false;
}
else // once our board is built we will display the game
{*/

Related

Snake Game: how not to make it possible for the fruit to spawn in the same position as the body

This is my first question and I apologize if it's not posed as it should be in advance.
So, I'm trying to make the fruits (I also call them apples in code) spawn on a position that is different from the snake body just like the title says. The problem is that I don't know how to check if the coordinates of the new fruit is not equal to each of the body parts of the snake.
public void newApple() {
tempX = random.nextInt(width/unitSize)*unitSize;
tempY = random.nextInt(height/unitSize)*unitSize;
for (int i = 0; i < bodyParts; i++) {
if (tempX != x[i] && tempY != y[i]){
appleX = tempX;
appleY = tempY;
}
else {
newApple();
}
}
}
This is what I've figured so far: I'm using 2 temp variables that will correspond to a random position in the frame and then I want to check if those are not equal to each position of the snake. The if condition inside the for loop just checks for x[0] and y[0] which are the coordinates of the head of my snake though.
This is what's inside the paintComponent() method to draw the apple.
//drawing apple
if (appleX != null && appleY != null) {
g.setColor(Color.red);
g.fillOval(appleX, appleY, unitSize, unitSize);
}
Down below is my entire 2 classes of the project if you may need it.
public class Main {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createGame();
}
});
}
public static void createGame() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(new MyPanel());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
public class MyPanel extends JPanel implements ActionListener {
final int width = 600;
final int height = 600;
final int unitSize = 25;
final int maxNumberOfUnits = (width*height)/(unitSize*unitSize);
int[] x = new int[maxNumberOfUnits];
int[] y = new int[maxNumberOfUnits];
int bodyParts = 2;
Integer appleX, appleY, tempX, tempY;
int score = 0;
char direction = 'R';
boolean running;
int delay = 175;
Timer timer = new Timer(delay, this);
Random random = new Random();
Font font1 = new Font("Ink Free", Font.BOLD, 40);
Font font2 = new Font("Ink Free", Font.BOLD, 75);
public Dimension getPreferredSize() {
return new Dimension(width, height);
}
MyPanel() {
setBackground(new Color(16, 16, 16));
setFocusable(true);
timer.start();
running = true;
newApple();
x[0] = 10*unitSize;
y[0] = 10*unitSize;
x[1] = 9*unitSize;
y[1] = 10*unitSize;
addKeyListener(new KeyAdapter() {
#Override
public void keyPressed(KeyEvent e) {
switch (e.getKeyCode()) {
case 37:
if (direction !='R') {
direction = 'L';
}
break;
case 38:
if (direction !='D') {
direction = 'U';
}
break;
case 39:
if (direction !='L') {
direction = 'R';
}
break;
case 40:
if (direction !='U') {
direction = 'D';
}
break;
}
}
});
}
public void moveSnake() {
for (int i = bodyParts; i > 0; i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}
switch (direction) {
case 'U':
y[0] -= unitSize;
break;
case 'D':
y[0] += unitSize;
break;
case 'L':
x[0] -= unitSize;
break;
case 'R':
x[0] += unitSize;
break;
}
}
public void newApple() {
tempX = random.nextInt(width/unitSize)*unitSize;
tempY = random.nextInt(height/unitSize)*unitSize;
for (int i = 0; i < bodyParts; i++) {
if (tempX != x[i] && tempY != y[i]){
appleX = tempX;
appleY = tempY;
}
else {
newApple();
}
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (running) {
/*
//drawing a matrix
for (int i = 1; i < height/unitSize; i++) {
g.drawLine(0, i*unitSize, width, i*unitSize);
}
for (int i = 1; i < width/unitSize; i++) {
g.drawLine(i*unitSize, 0, i*unitSize, height);
}
*/
//drawing apple
if (appleX != null && appleY != null) {
g.setColor(Color.red);
g.fillOval(appleX, appleY, unitSize, unitSize);
}
//drawing snake
g.setColor(Color.green);
for (int i = 0; i < bodyParts; i++) {
g.fillRect(x[i], y[i], unitSize, unitSize);
}
//drawing score
g.setColor(Color.red);
g.setFont(font1);
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Score: " + score, (width-metrics1.stringWidth("Score: " + score))/2, g.getFont().getSize());
}
else {
g.setColor(Color.red);
g.setFont(font1);
FontMetrics metrics1 = getFontMetrics(g.getFont());
g.drawString("Score: " + score, (width-metrics1.stringWidth("Score: " + score))/2, g.getFont().getSize());
g.setColor(Color.white);
g.setFont(font2);
FontMetrics metrics2 = getFontMetrics(g.getFont());
g.drawString("Game Over", (width-metrics2.stringWidth("Game Over"))/2, height/2);
}
}
public void checkApple() {
if (x[0]==appleX && y[0]==appleY) {
score++;
bodyParts++;
newApple();
}
}
public void checkCollisions() {
//body
for (int i = bodyParts; i > 0; i--) {
if (x[0] == x[i] && y[0] == y[i]) {
running = false;
}
}
if (x[0] < 0) {
running = false;
}
if (x[0] > width) {
running = false;
}
if (y[0] < 0) {
running = false;
}
if (y[0] > height) {
running = false;
}
if (!running) {
timer.stop();
}
}
#Override
public void actionPerformed(ActionEvent e) {
if (running) {
checkApple();
moveSnake();
checkCollisions();
}
repaint();
}
}
You don't need a recursive call. Method newApple() should not call itself. You need a loop.
Generate values for tempX and tempY.
For each part of the snake check whether tempX equals the snake body part x[i] and also tempY equals y[i].
If at least one part of the snake body equals the coordinates tempX and tempY, go back to step 1, above.
If none of the snake body parts equals the coordinates, assign the generated coordinates to the "apple".
This is method newApple()
public void newApple() {
boolean ok = false;
while (!ok) {
ok = true;
tempX = random.nextInt(width/unitSize)*unitSize;
tempY = random.nextInt(height/unitSize)*unitSize;
for (int i = 0; i < bodyParts; i++) {
if (tempX == x[i] && tempY == y[i]) {
ok = false;
break;
}
}
if (ok) {
appleX = tempX;
appleY = tempY;
}
}
}
I think you should have an array of all the location of body parts of snakes as any body part could do collision (As if the snake collide then it's game over).
You can use the same Array for fruit respawn just ensuring that it is not in the array.
You should verify whether tempX and tempY match the values in the x and y arrays and call newApple() if they do and break out of the loop.
This means, that if you reach the end of the loop, no matches were found. You can then safely set the apple's x and y coordinates:
public void newApple() {
tempX = random.nextInt(width/unitSize)*unitSize;
tempY = random.nextInt(height/unitSize)*unitSize;
for (int i = 0; i < bodyParts; i++) {
if (tempX == x[i] && tempY == y[i]){
newApple();
break;
}
if ( i == bodyParts - 1 ) {
appleX = tempX;
appleY = tempY;
}
}
}
If I were in your shoes, I would try to avoid recursion and create a separate function to calculate if a coordinate collides with the snake's body.
A basic idea would be like this:
newApple()
- randomize a new coordinate x,y
- while overlapsWithSnake(x,y)
- randomize a new coordinate x,y
overlapsWithSnake(x,y)
- iterate through all snake coordinates
- if coordinate is the same, return true
- return false
Now, I need to point out that the algorithm does not consider when there is no more free space in the screen (the end of the game).
Additionally, this algorithm takes more and more time to find an available coordinate as the snake's body grows. What you could do to improve that is the following:
newApple()
- assign the result of getAvailableSpaces() to a list
- if the list is empty, then is game over
- else, randomize a number between 0 and list size - 1 as p
- select the coordinate at position p of the list
getAvailableSpaces()
- create logic to return a list of all free coordinates
The problem is that you only check if the apple is in the first body parts index.
You need to complete the for loop before checking if the apple can be placed.
boolean applePlacementOk = true;
while(true){
applePlacementOk = true;
tempX = random.nextInt(width/unitSize)*unitSize;
tempY = random.nextInt(height/unitSize)*unitSize;
for (int i = 0; i < bodyParts; i++) {
if (tempX == x[i] && tempY == y[i]){
applePlacementOk = false;
break;
}
}
if(applePlacementOk){
break;
}
}
appleX = tempX;
appleY = tempY;
Edit: Sorry about SO. This should work better
Edit2: I notice it's essentially the same answer as Abra, now.

How to convert the mouse position in pixels into the row and column on the grid?

I am basically making a battleship guessing game where you have to the position of a ship by the click of your mouse. When a position of the ship is guessed correctly it deletes that ship cell from the array and when every cell is guessed correctly, the game is over.
What I am now struggling on is to
keep the ship cells within the canvas
convert the mouse position in pixels into the row and column on the grid
if the guess is correct, add the guess to the hit array and if missed adding it to the miss array.
when a guess is made, in addition to colouring the cell, print either “Hit!” or “Miss!” on the cell
sinking the ship when all cells have been hit
In your code you've mixed rows and columns. The x coordinate goes from the left to the right, this are the columns. The y axis goes from the top to the bottom and corresponds to the rows.
Don't store column, row, hit and miss in arrays. But use 2-dimensional arrays to store the position of the ship and the positions of mouse clicks:
boolean [][] ship;
boolean [][] click;
keep the ship cells within the canvas
If the direction is horizontal, then the x start position of the ship has to be less than NUM_COLS - shipLength:
randomX = (int)random(NUM_COLS - shipLength);
randomY = (int)random(NUM_ROWS);
If the direction is horizontal, then the y start position of the ship has to be less than NUM_ROWS - shipLength:
randomX = (int)random(NUM_COLS);
randomY = (int)random(NUM_ROWS - shipLength);
Call randomShip in setup rather than draw:
void setup() {
size(600, 500);
randomShip();
println(store);
}
void draw() {
// randomShip(); <---- delete
drawCells (row, column, shipLength, (255) );
}
Generate the random position and size of the ship in randomShip;
void randomShip () {
ship = new boolean[NUM_COLS][NUM_ROWS];
click = new boolean[NUM_COLS][NUM_ROWS];
shipLength = (int)random (3, 8);
int store = (int)random(vert, horz);
if (store >= 0) {
int randomX = (int)random(NUM_COLS - shipLength);
int randomY = (int)random(NUM_ROWS);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX + i][randomY] = true;
}
} else {
int randomX = (int)random(NUM_COLS);
int randomY = (int)random(NUM_ROWS - shipLength);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX][randomY+1] = true;
}
}
println(shipLength);
}
convert the mouse position in pixels into the row and column on the grid
if the guess is correct, add the guess to the hit array and if missed adding it to the miss array.
The cell which was clicked can be get by the dividing the mouse coordinates mouseX and mouseY by CELLSIZE
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
Store mark the clicked cells and count the hits and miss in mouseClicked:
void mouseClicked () {
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
if (!click[cell_x][cell_y]) {
click[cell_x][cell_y] = true;
if ( ship[cell_x][cell_y] ) {
hitCount ++;
} else {
missCount ++;
}
}
}
when a guess is made, in addition to colouring the cell, print either “Hit!” or “Miss!” on the cell
Evaluate the ship position (ship[][]) and clicked positions (click[][]) in drawCells. Draw the cells and the text dependent on the states in 2 nested loops:
void drawCells(int colour) {
for (int i = 0; i < NUM_COLS; i++) {
for (int j = 0; j < NUM_ROWS; j++) {
float x = i * CELLSIZE;
float y = j * CELLSIZE;
if (ship[i][j]) {
fill (colour);
rect(x, y, CELLSIZE, CELLSIZE);
}
if (click[i][j]) {
fill(255, 0, 0);
textSize(15);
text(ship[i][j] ? "hit" : "miss", x+10, y+30);
}
}
}
}
sinking the ship when all cells have been hit
Handle the end of the game in draw:
e.g.
void draw() {
drawCells(255);
if (hitCount == shipLength ) {
// [...]
}
}
Full code listing:
final int CELLSIZE = 50;
final int NUM_ROWS = 10;
final int NUM_COLS = 12;
int horz = (int)random(50);
int vert = (int)random(-50);
int store;
int shipLength;
boolean [][] ship;
boolean [][] click;
int hitCount = 0;
int missCount = 0;
void setup() {
size(600, 500);
randomShip();
println(store);
}
void draw() {
drawCells(255);
if (hitCount == shipLength ) {
// [...]
}
}
void drawCells(int colour) {
for (int i = 0; i < NUM_COLS; i++) {
for (int j = 0; j < NUM_ROWS; j++) {
float x = i * CELLSIZE;
float y = j * CELLSIZE;
if (ship[i][j]) {
fill (colour);
rect(x, y, CELLSIZE, CELLSIZE);
}
if (click[i][j]) {
fill(255, 0, 0);
textSize(15);
text(ship[i][j] ? "hit" : "miss", x+10, y+30);
}
}
}
}
void randomShip () {
ship = new boolean[NUM_COLS][NUM_ROWS];
click = new boolean[NUM_COLS][NUM_ROWS];
hitCount = 0;
missCount = 0;
shipLength = (int)random (3, 8);
int store = (int)random(vert, horz);
if (store >= 0) {
int randomX = (int)random(NUM_COLS - shipLength);
int randomY = (int)random(NUM_ROWS);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX + i][randomY] = true;
}
} else {
int randomX = (int)random(NUM_COLS);
int randomY = (int)random(NUM_ROWS - shipLength);
for (int i = 0; i < shipLength; i++ ) {
ship[randomX][randomY+1] = true;
}
}
println(shipLength);
}
void mouseClicked () {
int cell_x = mouseX / CELLSIZE;
int cell_y = mouseY / CELLSIZE;
if (!click[cell_x][cell_y]) {
click[cell_x][cell_y] = true;
if ( ship[cell_x][cell_y] ) {
hitCount ++;
} else {
missCount ++;
}
}
}

Error building a Checkers Game

Error message:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at neegjar.Play.canJump(Play.java:113)
at neegjar.Play.getLegalMoves(Play.java:278)
at neegjar.Board.printLegalMoves(Board.java:198)
at neegjar.main.main(main.java:17)
Java Result: 1
I am trying to build a checkers Game in java (in the console for now). I have 6 classes:
Board: displays and keeps track of the board. It is a 2d array of Square objects called mySquare.
CheckerMove: contains variables fromX, fromY, toX, toY and boolean isAJump. In Play, I create an Array of CheckerMove objects to find out what moves are valid.
Piece: A single checker piece. Each player has an array of 12 Piece objects to use. Contains variables xCoord, yCoord, isKing, isAlive and team.
Play: Basically the backbone of the project. Handles what is considered a valid move, what is a "jump", etc. It is included below.
Square: A square object is a single tile on the checkers board. It contains variables squareColor, hasAPiece, and hasARedPiece( player one).
main (contains main method)
When I try to run the main method which creates the board, places the pieces, and prints the legal moves, everything works until it tries to print the legal moves (it displays the error message above).
Why is it doing this? I have no idea. I would appreciate any help, and thank you for taking the time to read this!
Here is Play:
package neegjar;
import java.util.ArrayList;
public class Play extends Board
{
public int currentPlayer;
public boolean gameOver;
public int turnNumber;
public Play()
{
currentPlayer = 1;
gameOver = false;
turnNumber = 0;
}
public void takeTurn()
{
System.out.println("It is player "+ this.currentPlayer + "'s turn");
//for Player 1
have user select a piece
System.out.println("Select a piece by typing and x coordinate, followed by a y coordinate (seperated by commas");
System.out.println("For an example input, type h");
}
//can the piece jump from x1,y1 TO x2,y2?
public boolean canJump(int player, int x1, int y1, int x2, int y2)
{
boolean CURRENT_KING = false; //by default
int CURRENT_PIECE = -1;
if(player == 1)
{
if((x2 != x1+2) && (x2 != x1-2) && (y2 != y1+2) && (y2 != y1-2)) return false;
for(int i=0; i<12; i++)
{
if((player1Pieces[i].getX() == x1)&&(player1Pieces[i].getY() == y1))
{
CURRENT_PIECE = i;
break; //get out of foor loop
}
}
if(player1Pieces[CURRENT_PIECE].isAKing() == true)
{
CURRENT_KING = true;
}
//top left spot
if((x2 == x1-2)&&(y2 == y1-2))
{
//first check to see if there is an enemy black piece on the adjacent square
if((mySquare[y1-1][x1-1].getHasAPiece()==true)&&(mySquare[y1-1][x1-1].getHasARedPiece()==false))
if((mySquare[y1-2][x1-2].getHasAPiece()==true)||(y1-2 < 0)||(x1-2 < 0)) //check for a blocker
{
return false;
}
else
return true;
}
//top right spot
if((x2 == x1+2)&&(y2 == y1-2))
{
//first check to see if there is an enemy black piece on the adjacent square
if((mySquare[y1-1][x1+1].getHasAPiece()==true)&&(mySquare[y1-1][x1+1].getHasARedPiece()==false))
if((mySquare[y1-2][x1+2].getHasAPiece()==true)||(y1-2 < 0)||(x1+2 > 7)) //check for a blocker
{
return false;
}
else
return true;
}
//Next 2 are for Kings only!
if(CURRENT_KING = true)
{
//bottom left
if((x2 == x1-2)&&(y2 == y1+2))
{
if((mySquare[y1+1][x1-1].getHasAPiece()==true)&&(mySquare[y1+1][x1-1].getHasARedPiece()==false))
if((mySquare[y1+2][x1-2].getHasAPiece()==true)||(y1+2 > 7)||(x1-2 < 0)) //check for a blocker or out of bounds
{
return false;
}
else
return true;
}
//bottom right
if((x2 == x1+2)&&(y2 == y1+2))
{
if((mySquare[y1+1][x1+1].getHasAPiece()==true)&&(mySquare[y1+1][x1+1].getHasARedPiece()==false))
if((mySquare[y1+2][x1+2].getHasAPiece()==true)||(y1+2 > 7)||(x1+2 >7)) //check for a blocker
{
return false;
}
else
return true;
}
}//end if King
}//end p1
if(player == 2)
{
if((x2 != x1+2) && (x2 != x1-2) && (y2 != y1+2) && (y2 != y1-2)) return false;
for(int i=0; i<12; i++)
{
if((player2Pieces[i].getX() == x1)&&(player2Pieces[i].getY() == y1))
{
CURRENT_PIECE = i;
break; //get out of foor loop
}
}
if(player2Pieces[CURRENT_PIECE].isAKing() == true)
{
CURRENT_KING = true;
}
//bottom left
if((x2 == x1-2)&&(y2 == y1+2))
{
if((mySquare[y1+1][x1-1].getHasAPiece()==true)&&(mySquare[y1+1][x1-1].getHasARedPiece()==false))
if((mySquare[y1+2][x1-2].getHasAPiece()==true)||(y1+2 > 7)||(x1-2 < 0)) //check for a blocker or out of bounds
{
return false;
}
else
return true;
}
//bottom right
if((x2 == x1+2)&&(y2 == y1+2))
{
if((mySquare[y1+1][x1+1].getHasAPiece()==true)&&(mySquare[y1+1][x1+1].getHasARedPiece()==false))
if((mySquare[y1+2][x1+2].getHasAPiece()==true)||(y1+2 > 7)||(x1+2 >7)) //check for a blocker
{
return false;
}
else
return true;
}
//Next 2 are for Kings only!
if(CURRENT_KING = true)
{
//top left spot
if((x2 == x1-2)&&(y2 == y1-2))
{
//first check to see if there is an enemy black piece on the adjacent square
if((mySquare[y1-1][x1-1].getHasAPiece()==true)&&(mySquare[y1-1][x1-1].getHasARedPiece()==false))
if((mySquare[y1-2][x1-2].getHasAPiece()==true)||(y1-2 < 0)||(x1-2 < 0)) //check for a blocker
{
return false;
}
else
return true;
}
//top right spot
if((x2 == x1+2)&&(y2 == y1-2))
{
//first check to see if there is an enemy black piece on the adjacent square
if((mySquare[y1-1][x1+1].getHasAPiece()==true)&&(mySquare[y1-1][x1+1].getHasARedPiece()==false))
if((mySquare[y1-2][x1+2].getHasAPiece()==true)||(y1-2 < 0)||(x1+2 > 7)) //check for a blocker
{
return false;
}
else
return true;
}
}//end if king
} //end p2
//default, or if nothing is found
return false;
} // end canJump()
/**
* This is called by the getLegalMoves() method to determine whether
* the player can legally move from (r1,c1) to (r2,c2). It is
* assumed that (r1,r2) contains one of the player's pieces and
* that (r2,c2) is a neighboring square.
*/
public boolean canMove(int player, int x1, int y1, int x2, int y2)
{
if (y2 < 0 || y2 >= 8 || x2 < 0 || x2 >= 8) //check to see if move is on the board
return false;
if (mySquare[y2][x2].getHasAPiece() == true)
return false; // (r2,c2) already contains a piece.
if (player == 1)
{
if (mySquare[y1][x1].getHasARedPiece() == true && y2 < y1)
return false; //red can only move up if not a king
return true;
}
else //player == 2
{
if (mySquare[y1][x1].getHasAPiece() == true && mySquare[y1][x1].getHasARedPiece()==false && y2 > y1)
return false; // black can only move down if not a king
return true;
}
} // end canMove()
public CheckerMove[] getLegalMoves(int whichPlayer)
{
int pX =0;
int pY = 0;
int CURRENT_PIECE = -1; //used to signify desired piece
boolean CURRENT_KING = false; //default not a king
ArrayList<CheckerMove> legalMoves = new ArrayList<CheckerMove>(); //ADJUSTABLE arraylist of legalMoves
if((whichPlayer != 1)&&(whichPlayer != 2)) return null; //not a valid player
//player One /********************************************************/
if(whichPlayer == 1)
{
//loop through array to find piece
for(int i=0; i<12; i++)
{
if(player1Pieces[i].getIsAlive() == false) break;
if(player1Pieces[i].isAKing() == true)
CURRENT_KING = true;
pX = player1Pieces[i].getX();
pY = player1Pieces[i].getY();
//check for Jumps 1st
if (canJump(1, pX, pY, pX+2, pY+2))
legalMoves.add(new CheckerMove(pX, pY, pX+2, pY+2, true));
if (canJump(1, pX, pY, pX-2, pY+2))
legalMoves.add(new CheckerMove(pX, pY, pX-2, pY+2, true));
if (canJump(1, pX, pY, pX+2, pY-2))
legalMoves.add(new CheckerMove(pX, pY, pX+2, pY-2, true));
if (canJump(1, pX, pY, pX-2, pY-2))
legalMoves.add(new CheckerMove(pX, pY, pX-2, pY-2, true));
}//end for
if (legalMoves.size() == 0) //if there are no jumps
{
//loop through pieces array to find valid moves for each piece
for(int ctr = 0; ctr < 12; ctr++)
{
if(player1Pieces[ctr].isAlive == true)
{
int currX = player1Pieces[ctr].getX();
int currY = player1Pieces[ctr].getY();
if(canMove(1,currX,currY,currX-1,currY-1))
legalMoves.add(new CheckerMove(currX,currY,currX-1,currY-1,false));
if(canMove(1,currX,currY,currX+1,currY-1))
legalMoves.add(new CheckerMove(currX,currY,currX+1,currY-1,false));
if(canMove(1,currX,currY,currX-1,currY+1))
legalMoves.add(new CheckerMove(currX,currY,currX-1,currY+1,false));
if(canMove(1,currX,currY,currX+1,currY+1))
legalMoves.add(new CheckerMove(currX,currY,currX+1,currY+1,false));
}
}
}//if no legal moves exist
}//end player One /**********************************************/
//player Two
if(whichPlayer == 2)
{
//loop through array to find piece
for(int i=0; i<12; i++)
{
if(player2Pieces[i].getIsAlive() == false) break;
if(player2Pieces[i].isAKing() == true)
CURRENT_KING = true;
pX = player2Pieces[i].getX();
pY = player2Pieces[i].getY();
//check for Jumps 1st
if (canJump(2, pX, pY, pX+2, pY+2))
legalMoves.add(new CheckerMove(pX, pY, pX+2, pY+2, true));
if (canJump(2, pX, pY, pX-2, pY+2))
legalMoves.add(new CheckerMove(pX, pY, pX-2, pY+2, true));
if (canJump(2, pX, pY, pX+2, pY-2))
legalMoves.add(new CheckerMove(pX, pY, pX+2, pY-2, true));
if (canJump(2, pX, pY, pX-2, pY-2))
legalMoves.add(new CheckerMove(pX, pY, pX-2, pY-2, true));
}//end for
if (legalMoves.size() == 0) //if there are no jumps
{
//loop through pieces array to find valid moves for each piece
for(int ctr = 0; ctr < 12; ctr++)
{
if(player2Pieces[ctr].isAlive == true)
{
int currX = player2Pieces[ctr].getX();
int currY = player2Pieces[ctr].getY();
if(canMove(2,currX,currY,currX-1,currY-1))
legalMoves.add(new CheckerMove(currX,currY,currX-1,currY-1,false));
if(canMove(2,currX,currY,currX+1,currY-1))
legalMoves.add(new CheckerMove(currX,currY,currX+1,currY-1,false));
if(canMove(2,currX,currY,currX-1,currY+1))
legalMoves.add(new CheckerMove(currX,currY,currX-1,currY+1,false));
if(canMove(2,currX,currY,currX+1,currY+1))
legalMoves.add(new CheckerMove(currX,currY,currX+1,currY+1,false));
}
}
}
}//end p2
if (legalMoves.size() == 0)
return null; //no legal moves found
else //there are legal moves, so copy array list to an array and return
{
CheckerMove[] validMoves = new CheckerMove[legalMoves.size()];
for (int lastCtr = 0; lastCtr < legalMoves.size(); lastCtr++)
{
validMoves[lastCtr] = legalMoves.get(lastCtr);
}
return validMoves;
}
}//end getLegalMoves
}//end class
Here is Board:
package neegjar;
public class Board
{
public Square mySquare[][] = new Square[8][8];
public boolean gameover;
//initialize an Array of 12 Pieces (for the checkers) for EACH player
public Piece player1Pieces[] = new Piece[12];; //declaration
public Piece player2Pieces[] = new Piece[12]; //declaration
public Board()
{
//CREATE THE BOARd
//mySquare = new Square[8][8];
//initialize mySquare
for(int i = 0; i < 8; i++) //not sure if I need this
{
for(int j = 0; j < 8; j++)
{
mySquare[i][j] = new Square();
}
}
//initialize player1 and 2 Pieces arrays
initPieces(1);
initPieces(2);
//alternating colors
/*
for (int row = 0; row < 8; row++)
{
for (int col = 0; col < 8; col++)
{
if ((row == 0) || (row % 2 == 0) && ((col == 0) || (col % 2 == 0)))
{
mySquare[row][col].squareColor = "white";
}
else
{
// do nothing, the square will be black by default
}
}
}//end for loop
*/
//
}//end constructor
public void placePieces()
{
//set location of the pieces' initial location
//player 1
player1Pieces[0].move(0,5);
mySquare[5][0].setHasAPiece(true);
mySquare[5][0].setHasARedPiece(true);
player1Pieces[1].move(2,5);
mySquare[5][2].setHasAPiece(true);
mySquare[5][2].setHasARedPiece(true);
player1Pieces[2].move(4,5);
mySquare[5][4].setHasAPiece(true);
mySquare[5][4].setHasARedPiece(true);
player1Pieces[3].move(6,5);
mySquare[5][6].setHasAPiece(true);
mySquare[5][6].setHasARedPiece(true);
player1Pieces[4].move(1,6);
mySquare[6][1].setHasAPiece(true);
mySquare[6][1].setHasARedPiece(true);
player1Pieces[5].move(3,6);
mySquare[6][3].setHasAPiece(true);
mySquare[6][3].setHasARedPiece(true);
player1Pieces[6].move(5,6);
mySquare[6][5].setHasAPiece(true);
mySquare[6][5].setHasARedPiece(true);
player1Pieces[7].move(7,6);
mySquare[6][7].setHasAPiece(true);
mySquare[6][7].setHasARedPiece(true);
player1Pieces[8].move(0,7);
mySquare[7][0].setHasAPiece(true);
mySquare[7][0].setHasARedPiece(true);
player1Pieces[9].move(2,7);
mySquare[7][2].setHasAPiece(true);
mySquare[7][2].setHasARedPiece(true);
player1Pieces[10].move(4,7);
mySquare[7][4].setHasAPiece(true);
mySquare[7][4].setHasARedPiece(true);
player1Pieces[11].move(6,7);
mySquare[7][6].setHasAPiece(true);
mySquare[7][6].setHasARedPiece(true);
//player 2
player2Pieces[0].move(1,0);
mySquare[0][1].setHasAPiece(true);
player2Pieces[1].move(3,0);
mySquare[0][3].setHasAPiece(true);
player2Pieces[2].move(5,0);
mySquare[0][5].setHasAPiece(true);
player2Pieces[3].move(7,0);
mySquare[0][7].setHasAPiece(true);
player2Pieces[4].move(0,1);
mySquare[1][0].setHasAPiece(true);
player2Pieces[5].move(2,1);
mySquare[1][2].setHasAPiece(true);
player2Pieces[6].move(4,1);
mySquare[1][4].setHasAPiece(true);
player2Pieces[7].move(6,1);
mySquare[1][6].setHasAPiece(true);
player2Pieces[8].move(1,2);
mySquare[2][1].setHasAPiece(true);
player2Pieces[9].move(3,2);
mySquare[2][3].setHasAPiece(true);
player2Pieces[10].move(5,2);
mySquare[2][5].setHasAPiece(true);
player2Pieces[11].move(7,2);
mySquare[2][7].setHasAPiece(true);
}
public void alternateSquares() //assign every other to white
{
for(int row = 0; row < 8; row+=2)
{
for(int col = 0; col < 8; col+=2)
{
mySquare[row][col].setSquareColor("white");
}
}
for(int row = 1; row < 8; row+=2)
{
for(int col = 1; col < 8; col+=2)
{
mySquare[row][col].setSquareColor("white");
}
}
}
public void initPieces(int whichPlayer)
{
for(int p = 0; p <12; p++)
{
if(whichPlayer == 1)
player1Pieces[p] = new Piece();
else
player2Pieces[p] = new Piece();
}
}
public void printBoard()
{
System.out.print(" 0 1 2 3 4 5 6 7 \n");
System.out.print("---------------------------------------------------\n");
for(int row=0; row<8; row++)
{
System.out.print(row);
for(int col = 0; col < 8; col++)
{
System.out.print(" | ");
if(mySquare[row][col].getHasAPiece() == false)
System.out.print(" ");
else if(mySquare[row][col].getHasARedPiece()==true)
System.out.print(" R ");
else if(mySquare[row][col].getHasARedPiece()==false)
System.out.print(" * ");
}
System.out.print(" |\n");
System.out.print("---------------------------------------------------\n");
}
}
public void printPieces()
{
for(int i=0; i<12; i++)
{
System.out.print(player1Pieces[i].getX() + ", ");
System.out.print(player1Pieces[i].getY());
System.out.println();
}
}
public void printLegalMoves()
{
Play p1 = new Play();
CheckerMove[] temp = p1.getLegalMoves(1);
for(int i=0; i<temp.length; i++)
{
System.out.println("From: "+temp[i].fromX+", "+temp[i].fromY);
System.out.println("To: "+temp[i].toX+", "+temp[i].toY);
}
}
}//end class
main:
package neegjar;
import java.util.ArrayList;
public class main
{
public static void main(String[] args)
{
Board newBoard = new Board();
//newBoard.alternateSquares();
//newBoard.alternateSquares();
//System.out.println(newBoard.player1Pieces[0].getX());
newBoard.placePieces();
//newBoard.printBoard();
newBoard.printLegalMoves();
//newBoard.printPieces();
}
}//end class
This is a very basic debugging question.
Your method canJump() has several places where it indexes an array with a number from which it subtracts 1 or 2; in one of these places, the result is -1, and there is no -1 index into your array (or any java array).
The error message tells you on exactly which line this occurs; I can't tell from your source, because the line numbers don't match what you have posted. It will be accurate on your source, however.
Learn to look at your java error messages. They are excellent sources of information about what the problem is (which is not universal of language runtimes). Its combination of a virtual machine and a strongly-typed language allows it to point you to the source of the problem much more exactly than some other languages.
And learn to use a debugger. You can step to the code where the problem is and see what values your variables have in the middle of execution. It is invaluable for discovering and fixing problems on your own.

Java Tetris - Confused on grid[row][col] and coordinates (x, y)

I'm making Tetris in java for fun... I pretty much had everything working... but later found out that when I wanted to change the dimensions so it was square ([10 row][10 col] matrix, but instead a [12 row][10 col] matrix), that I started getting Index Out of Bound exceptions... see here: Java Tetris - weird row clearing issue
So I tried fixing everything so that the rows and columns weren't flip flopped... But am now getting hung up on the fact that the grid takes [row][col], but I’m moving around the tiles as (x, y) coordinates…
What’s confusing me is that row = y and col = x… which is reversed… so when I pass in coordinates I’m not sure when to swap them.
I know it’s a simple thing, but it’s confusing the hell out of me and I keep getting out of bounds exceptions whenever I think I have it right.
I'm not sure where the exact issue is, so I'm posting a full Sscce of my program... I think the issue is in the Board class...
Here, the block should still be able to move down... but if it tries to go down further than this...
I get:
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;
}
}
Thanks!
EDIT----------
I've tried implementing both ValarDohaeris and Svend Hansen's suggestions... Now the block is moving right when I press down, up when I press left, and down when I press right...
It seems to have to do with these methods in Board class which get and set tile locations...
// 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;
}
And in Piece class... movements are defined as:
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();
}
You have
grid = new TileSscce[totalRows][totalCols];
So when you want to access grid[x][y], you should check
x >= 0 && y >= 0 && x < totalRows && y < totalCols
in isValidCoordinate(x, y).
Emm... Quite interesting question. So to find out where the problem(s) may be I'll try to analyze your code a little bit...
You paste stack trace as
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 10
at Board.getTileAt(Board.java:177)
...
and at the same time the 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;
}
... so the isValidCoordinate method return terms as
x >= 0 && y >= 0 && x < totalCols && y < totalRows
...the method doesn't allow to avoid array out-of-bounds problems; Seems like you put wrong array element indexes.
A. As I can notice, you trying to put a classic math matrix on Java [][] arrays as
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];
}
}
}
... and here I must say that you should know that in [][] arrays x,y are backwards and it is y,x because :
y (or classic i) - sub-array index (vertical)
x (or classic j) - sub-array's element index (horizontal)
so you should use array index something this way grid[y][x] or grid[i][j]
As a useful tip, I recommend you to analyze your code for logic errors in this field...
B. According to your app screenshot as
... it seems like the x,y problem takes place here too because you trying to control y (vertical) coordinates but (in real) you control x (horizontal) coordinates only :S It is still because of the row,col instead of a classic Java (col,row or y,x) [][] array index positions.
C. And again concerning to the wrong directions...
...up when I press left, and down when I press right...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow(), tile[i].getCol()+1, i);
}
clearCurrPosition();
move();
}
Here I'll try to analyze the event as (you press right but move down)...
OK... according to one of your tasks you need to move by x coordinate (horizontally) but look closer... you make tile[i].getCol()+1 so it is newY and, of course, it moves vertically :S In your case it really moves down because you make increment as 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]);
}
}
}
...as a conclusion, I may recommend to change code (move right) something this way...
if (keycode == KeyEvent.VK_RIGHT) {
for (int i = 0; i < tile.length; i++) {
calcNewPosition(tile[i].getRow()+1, tile[i].getCol(), i);
}
clearCurrPosition();
move();
}
I hope my tips will help you to figure out what to look closer. Anyway, if you have some additional information please do comment my answer
Report if that helped you
This is based on x corresponds to columns and y corresponds to rows.
However grid is indexed by [row][col].
TileSscce grid[][] = new TileSscce[totalRows][totalCols]; // 12 => totalRows, 10 => totalCols
public int getWidth() {
return totalCols * tilesize;
}
public int getHeight() {
return totalRows * tilesize;
}
Following changes (based on your initial code - Sscce: - without later edits) will get rid of the exception and allow drawing till bottom of the board.
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]
}
From fillRect documentation.
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.
This is correct.
public boolean isValidCoordinate(int x, int y) {
return x >= 0 && y >= 0 && x < totalCols && y < totalRows;
}

Detect mouseclick on object Slick2d

I've made this code that successfully creates a 16x12 grid by 50x50 squares on a 800x600px board.
As you can see, the player moves to the coordinates of the players mouseclick.
Each square of the grid has an object of Felt (field) on it, which can be laast (locked). If a fields lock attribute is set to 1, the player should not be moved to that position.
How do i detect the field a player tries to move on to achieve this?
public class SimpleGame extends BasicGame{
private Image plane;
private float planeX;
private float planeY;
public SimpleGame()
{
super("SpilTest");
}
#Override
public void init(GameContainer gc) throws SlickException {
plane = new Image("figur.png");
}
#Override
public void update(GameContainer gc, int delta) throws SlickException {
Input input = gc.getInput();
if (input.isMousePressed(input.MOUSE_LEFT_BUTTON)) {
this.planeX = input.getMouseX() - 30;
this.planeY = input.getMouseY() - 50;
}
}
public void render(GameContainer gc, Graphics g) throws SlickException {
Felt board[][] = nytGrid();
int distancex = 0;
int distancey = 0;
int counter = 0;
for (int i=0; i < board.length ; i++) {
for (int j=0; j < board[i].length ; j++) {
if (board[i][j].getLaast() == 1) {
g.setColor(Color.red);
g.fillRect(distancex, distancey, 50, 50);
}
distancex += 50;
counter++;
if (counter == 16) {
distancey += 50;
distancex = 0;
counter = 0;
}
}
}
g.drawImage(plane, planeX, planeY);
}
public static void main(String[] args) throws SlickException {
AppGameContainer app = new AppGameContainer(new SimpleGame());
app.setDisplayMode(800, 600, false);
app.setTargetFrameRate(60);
app.start();
}
public Felt[][] nytGrid() {
Felt [][] board = new Felt[16][12];
for (int i=0; i < board.length ; i++) {
for (int j=0; j < board[i].length ; j++) {
int x = i;
int y = j;
board[i][j] = new Felt(x, y);
if (i == 5 && j == 5) {
board[i][j].setLaast(1);
}
}
}
return board;
}
}
First off, you should probably initialize the board in the init() method instead of render, so it doesn't have to do it every frame, and move the declaration for the grid next to the plane, planeX and planeY declarations in the class.
Now to disable movement into a locked square, first add a method to check if a square at certain coordinates is locked, so something along the lines of:
private boolean isLocked(int x, int y) {
int square = board[x/50][y/50];
if (square == 1) return true;
else return false;
}
Next modify the part of your update() method where you update the plane coordinates, so vaguely something like:
if (input.isMousePressed(input.MOUSE_LEFT_BUTTON)) {
int destX = input.getMouseX() - 30;
int destY = input.getMouseY() - 50;
if (!isLocked(destX, destY)) {
this.planeX = destX;
this.planeY = destY;
}
}
It's easy!
int mx = Mouse.getX();
int my = Mouse.getY();
But, it gives you the world cordinates, and you have to translate it to pixels:
int mx = Mouse.getX();
int my = Mouse.getY() * -1 + (Window.WIDTH / 2) + 71;

Categories

Resources