i am a high school student in an AP Computer Science course, and over the weekend we were assigned this project:
"Simulate the wandering of an intoxicated person in a square street grid. Draw a grid of 10 streets horizontally and 10 streets vertically. Represent the simulated drunkard by a dot, placed in the middle of the grid to start. For 100 times, have the simulated drunkard randomly pick a direction (east, west, north, south), move one block in the chosen direction, and draw the dot. After the iterations, display the distance that the drunkard has covered. (One might expect that on average the person might not get anywhere because the moves to different directions cancel one another out in the long run, but in fact it can be shown with probability 1 that the person eventually moves outside any finite region."
However, because graphics are not part of the curriculum, the grid is simulated by a grid created by a loop in a Grid class, and the dot representing the drunkard is an X, such as :
The default position for the X is at (5,5) which is shown above. However, I am having trouble with getting the X to move randomly.
My Drunkard class
public class Drunkard
{
int row;
int column;
public Drunkard()
{
row = 5;
column = 5;
}
public int getCol()
{
return column;
}
public int getRow()
{
return row;
}
public void moveRandomly()
{
double directionDeterminer = Math.random();
if (directionDeterminer >= 0 && directionDeterminer <= 0.25)
{
row++;
}
else if (directionDeterminer >= 0.25 && directionDeterminer <= 0.50)
{
row--;
}
else if ( directionDeterminer >= 0.50 && directionDeterminer <= 0.75)
{
column++;
}
else if ( directionDeterminer >= 0.75 && directionDeterminer <= 1.00)
{
column--;
}
}
}
and my grid class (Which contains the loop for creating the grid):
public class Grid
{
public static final int MAX_NUM_ROWS = 10;
public static final int MAX_NUM_COLUMNS = 10;
public Grid()
{
}
public void draw(Drunkard theDrunk)
{
Drunkard drunk = new Drunkard();
drunk.getRow();
int y = drunk.getCol();
String newRow = "- - - - - - - - - - ";
drunk.moveRandomly();
for (int row = 0; row < MAX_NUM_ROWS - 1; row++)
{
if (row == 4)
{
y = 8;
System.out.print( newRow.substring(0,y) + "X " + newRow.substring(10,20) );
System.out.print("\n");
}
for (int column = 0; column < MAX_NUM_COLUMNS ; column++)
{
System.out.print("- ");
}
System.out.print("\n");
}
}
}
The method moveRandomly() is supposed to either increment or decrement the rows or columns so that the position of the X changes either north, south, east or west. However, i am unsure on how to have the variables from moveRandomly() (row and column) have any effect on the grid created in the Grid class. Does anyone have an idea on how to make it so the variables have an effect on the grid? Keep in mind that I am a beginning programmer, so I have basic knowledge on loops and if statements, not arrrays or graphics. Any comments would be greatly appreciated.
It looks pretty good, i think you might just want something like this in draw:
for(int row = 0; row < MAX_NUM_ROWS - 1; row ++)
{
for(int column = 0; column < MAX_NUM_COLUMNS - 1; column ++)
{
if((row == theDrunk.getRow()) && (column == theDrunk.getCol()))
System.out.print("X");
else
System.out.print("-");
}
System.out.println();
}
This could also be done with substring given some modification
Related
I wrote algortihm tht checks just part of tic tac toe game board, let's say its 10x10 size.
There's no need to iterate throught whole board every time, just around player move index + game diffuculty in each direction.
Here is my impl:
private boolean checkHorizontalWin(String gameBoard, int gameSize, int gameDifficulty, int moveIdx) {
// CHECK HORIZONTAL WIN
int moveX = moveIdx / gameSize; // 15/10=1
int moveY = moveIdx % gameSize; // 15%10=5
int startX = clamp(moveX - gameDifficulty, 0, gameSize);
int startY = clamp(moveY - gameDifficulty, 0, gameSize);
int endX = clamp(moveX + gameDifficulty, 0, gameSize);
int endY = clamp(moveY + gameDifficulty, 0, gameSize);
for (int row = startY; row < endY; row++) {
char candidate = getPawnAtCoords(gameBoard, gameSize, row, 0);
int counter = 1;
for (int column = startX; column < endX; column++) {
char pawn = getPawnAtCoords(gameBoard, gameSize, row, column);
if ((pawn == candidate) && (pawn != '-')) {
counter++;
} else {
counter = 1;
candidate = pawn;
}
if (counter == gameDifficulty) {
return true;
}
}
}
return false;
}
private int clamp(int val, int min, int max) {
return Math.max(min, Math.min(max, val));
}
private char getPawnAtCoords(String board, int gameSize, int row, int column) {
int index = row * gameSize + column; // 1 * 10 + 5
return board.charAt(index);
}
Algorithm is not working as it's should when player move index is placed on board corner.
Anyone gat an idea?
The problem is that with candidate = getPawnAtCoords(gameBoard, gameSize, row, 0) you read a cell that might not be in the region you want to inspect: the column 0 might not be anywhere near. Yet, you count that cell. So for instance, with a 3-in-a-row game, when you scan the first row where a move was made in column 10, then that row might look like this:
X------XX-X----
^ last move
^ inner loop starts here, but count is already 1 before it starts
^ this X is counted erroneously
Your initialisation of candidate will count the left X and then will find two more X starting at index 7 (i.e. 10 - 3), and conclude there is a 3-in-a-row, but this is a false positive.
You can solve this in many ways. For instance, this will do the trick:
char candidate = '-';
int counter = 0;
Secondly, your encoding of an index (from row/column) is different from the decoding of an index (into row/column). In getPawnAtCoords the column is the smaller unit, and the row the bigger one (it is multiplied), yet in checkHorizontalWin you extract moveX as the bigger unit (as you divide), which is later used for the loop variable column.
You can fix this by changing the initialisation of moveX and moveY to:
int moveX = moveIdx % gameSize;
int moveY = moveIdx / gameSize;
Finally, this is an overly complex algorithm. You already know what the last move was, as you can read gameBoard[moveX] and it is that character you want to check with, nothing else. So the variable candidate could be set to it -- only once. Then you don't need that pawn == '-' check anymore and only need to reset the counter to 0 when you find a character that is different from candidate.
Moreover, for horizontal wins it is not necessary to look at any other row than the row of the last move.
Closely related to Java programming - nested for loops for minesweeper game, my Minesweeper program is designed to loop through cells, check each adjacent cell, perform a logic test to check if it's a Mine, and then jump to the next one. However, when I run it, it somehow becomes an infinite loop. I've tried changing variables, reversing signs (< becomes > and + becomes -), and googling other solutions, but I can't find anything.
Printouts are for debugging, gameboard is set to [10][10],
public static void assignNumbers(int[][] gameBoard)
{
for(int r = 0; r <= (gameBoard.length - 1); r++){ //row
for(int c = 0; c <= (gameBoard[0].length - 1); r++){ //column
System.out.print("New Cell ");
for(int vR = r+1; vR > r-2; vR --){ //vR is visiting Row
for(int vC = c+1; vC > c-2; vC --){ //vC is visiting Column
System.out.print("new item ");
if (isValid(vR, vC, gameBoard)){
System.out.print("isMine? ");
if (isMine(vR, vC, gameBoard)){
gameBoard[r][c] += 1;
System.out.print(" MINE ");
}
else {
System.out.print(" NO ");
}
}
}
}
System.out.println();
}
}
}
public static boolean isMine(int r, int c, int[][] gameBoard){
if(gameBoard[r][c] != 100){
return false;
}
else{
return true;
}
}
public static boolean isValid(int r, int c, int[][] gameBoard)
{
// Returns true if row number and column number
// is in range
return ((r >= 0) && (r < SIDE)) && ((c >= 0) && (c < SIDE)) && !isMine(r, c, gameBoard);
}
When I try to run it, I get an infinite printout saying :
"New Cell" followed by 9 "new items". This should only print out 100 times (once for each cell), however it doesn't stop after 100. I assume it's a logic error in one of the for loops, but I can't find it for the life of me. Any help is appreciated, and I'll do my best to answer any questions.
EDIT: punctuation
Try to replace r++ with c++
for(int c = 0; c <= (gameBoard[0].length - 1); c++){ //column
When I say efficient I mean code that isn't cpu intensive.
The Problem:
I have a field of blocks. Like in the following image:
Every single one of these blocks represents an instance of a self-made Block class. This block class has a List<Block> neighBours, where the neighbours of the block are stored. So every single block in the image knows which blocks are next to it.
What I want to do is to pick any block from this image, and compute how many "steps" away this block is. For example if I pick the block in the top left, I want to have a Map<Block, Integer> representing how many "steps" away each block is from the picked block. Like this:
Now before you say "Just store it's position X and Y in the block class and calculate the difference X + difference Y", that wouldn't work because the field can have gaps(represented by red color) between them like the following image:
And as you might notice, the block next to the gap that was first 4 steps away, is now 6 steps away. Thus the best way(I presume) to get how many steps away the other blocks are is by using a recursive algorith that makes use of the neighbour info. I couldn't make an efficient one myself and I was hoping someone might know something that works well.
Several problems I came across are the fact that because all blocks know their neighbours, the recursive algorithm would go indefinately back and forth between the first and second block. Or the fact that when using the algorithm on a 11x11 field, there were 3284 method calls, which seems waaay too high for an 11x11 field.
Question:
So the question I have is: What is an efficient way, using the knowledge of what neighbours each block has, to get how many steps away each block is.
Code:
This is the current code that I have incase anyone wants to see it.
public class Block
{
List<Block> neighBours;
public Block(List<Block> neighBours)
{
this.neighBours = neighBours;
}
public Map<Block, Integer> getStepsAway()
{
Map<Block, Integer> path = new HashMap<Block, Integer>();
getPaths(path, 0, 100);
return path;
}
public void getPaths(Map<Block, Integer> path, int pathNumber, int maxPathNumber)
{
if(pathNumber <= maxPathNumber)
{
for(Block block : neighBours)
{
Integer thePathNumber = path.get(block);
if(thePathNumber != null)
{
if(pathNumber < thePathNumber)
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
else
{
path.put(block, pathNumber);
block.getPaths(path, pathNumber + 1, maxPathNumber);
}
}
}
}
}
Recursive algorithms are doomed to fail on a large grid. Java is not designed for deep recursions and can only withstand a few thousands recursive calls before failing with a StackOverflowException. Only iterative solutions are a reasonible approach for large pathfinding problems in Java.
Of course you can always use a classic pathfinding algorithm such as A*, but you would have to apply it for each cell, which would be extremely expensive.
Indeed, your problem is a bit particular in the sense you want to calculate the minimum distance to all cells and not only just one. Therefore, you can do it in a more clever way.
One property of your problem is that given A and B, if the minimal path from A to B contains C then this path is also minimal from A to C and from C to B. That's what my intuition tells me, but it would need to be proven before implementing my suggestion.
The algorithm I propose is efficient, uses O(n) memory and has O(n^2) runtime complexity (cannot be faster since you need to set this many cells in the array):
start with your first point and set the distance of all its valid neighbours to 1. Doing so, you will record the border, which is all the cells at distance 1 from the first cell.
then, you iterate over the border and take all their neighbours which have not already been assigned a distance and assign them distance 2. All cells of distance 2 become your new border.
iterate until the border is empty
Below is a full working solution. The code may be improved in various ways using more convenience methods for initializing and printing matrices of objects and primitive integers, but you get the idea:
public class Solution {
public enum Cell { FREE, BLOCKED }
// assuming cells is a rectangular array with non-empty columns
public static int[][] distances(Cell[][] cells, ArrayCoordinate startingPoint) {
int[][] distances = new int[cells.length][cells[0].length];
// -1 will mean that the cell is unreachable from the startingPoint
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
distances[i][j] = -1;
}
}
distances[startingPoint.i][startingPoint.j] = 0;
Set<ArrayCoordinate> border = startingPoint.validNeighbours(cells);
for (int currentDistance = 1; !border.isEmpty(); currentDistance++) {
Set<ArrayCoordinate> newBorder = new HashSet<>();
for (ArrayCoordinate coord : border) {
distances[coord.i][coord.j] = currentDistance;
for (ArrayCoordinate neighbour : coord.validNeighbours(cells)) {
if (distances[neighbour.i][neighbour.j] < 0) {
newBorder.add(neighbour);
}
}
}
border = newBorder;
}
return distances;
}
private static class ArrayCoordinate {
public ArrayCoordinate(int i, int j) {
if (i < 0 || j < 0) throw new IllegalArgumentException("Array coordinates must be positive");
this.i = i;
this.j = j;
}
public final int i, j;
public Set<ArrayCoordinate> validNeighbours(Cell[][] cells) {
Set<ArrayCoordinate> neighbours = new HashSet<>();
// inlining for not doing extra work in a loop iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a loop
addIfValid(cells, neighbours, 1, 0);
addIfValid(cells, neighbours, -1, 0);
addIfValid(cells, neighbours, 0, 1);
addIfValid(cells, neighbours, 0, -1);
return neighbours;
}
private void addIfValid(Cell[][] cells, Set<ArrayCoordinate> neighbours, int dx, int dy) {
int x = i + dx, y = j + dy;
if (0 <= x && 0 <= y && x < cells.length && y < cells[0].length && cells[x][y] == Cell.FREE) {
neighbours.add(new ArrayCoordinate(i + dx, j + dy));
}
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArrayCoordinate point = (ArrayCoordinate) o;
if (i != point.i) return false;
if (j != point.j) return false;
return true;
}
#Override
public int hashCode() {
int result = i;
result = 31 * result + j;
return result;
}
}
public static void main(String[] args) {
int n = 11, m = 5;
Cell[][] cells = new Cell[n][m];
cells[1][1] = Cell.BLOCKED;
cells[1][2] = Cell.BLOCKED;
cells[2][1] = Cell.BLOCKED;
ArrayCoordinate startingPoint = new ArrayCoordinate(5, 2);
System.out.println("Initial matrix:");
for (int i = 0; i < cells.length; i++) {
for (int j = 0; j < cells[0].length; j++) {
if (cells[i][j] == null) {
cells[i][j] = Cell.FREE;
}
if (startingPoint.i == i && startingPoint.j == j) {
System.out.print("S ");
} else {
System.out.print(cells[i][j] == Cell.FREE ? ". " : "X ");
}
}
System.out.println();
}
int[][] distances = distances(cells, startingPoint);
System.out.println("\nDistances from starting point:");
for (int i = 0; i < distances.length; i++) {
for (int j = 0; j < distances[0].length; j++) {
System.out.print((distances[i][j] < 0 ? "X" : distances[i][j]) + " ");
}
System.out.println();
}
}
}
Output:
Initial matrix:
. . . . .
. X X . .
. X . . .
. . . . .
. . . . .
. . S . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Distances from starting point:
7 8 7 6 7
6 X X 5 6
5 X 3 4 5
4 3 2 3 4
3 2 1 2 3
2 1 0 1 2
3 2 1 2 3
4 3 2 3 4
5 4 3 4 5
6 5 4 5 6
7 6 5 6 7
Bonus
I almost cried when I saw all this boilerplate in my Java solution, so I wrote a shorter (perhaps slightly less efficient) version in Scala:
object ScalaSolution {
sealed abstract class Cell
object Free extends Cell
object Blocked extends Cell
// assuming cells is a rectangular array with non-empty columns
def distances(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// -1 will mean that the cell is unreachable from the startingPoint
val distances = Array.fill[Int](cells.length, cells(0).length)(-1)
distances(startingPoint._1)(startingPoint._2) = 0
var (currentDistance, border) = (1, validNeighbours(cells, startingPoint))
while (border.nonEmpty) {
border.foreach { case (i, j) => distances(i)(j) = currentDistance }
border = border.flatMap(validNeighbours(cells, _)).filter { case (i, j) => distances(i)(j) < 0 }
currentDistance += 1
}
distances
}
private def validNeighbours(cells: Array[Array[Cell]], startingPoint: (Int, Int)) = {
// inlining for not doing extra work in a for yield iterating over (-1, 1) x (-1, 1). If diagonals are allowed
// then switch for using a for yield
Set(neighbourIfValid(cells, startingPoint, ( 1, 0)),
neighbourIfValid(cells, startingPoint, (-1, 0)),
neighbourIfValid(cells, startingPoint, ( 0, 1)),
neighbourIfValid(cells, startingPoint, ( 0, -1)))
.flatten
}
private def neighbourIfValid(cells: Array[Array[Cell]], origin: (Int, Int), delta: (Int, Int)) = {
val (x, y) = (origin._1 + delta._1, origin._2 + delta._2)
if (0 <= x && 0 <= y && x < cells.length && y < cells(0).length && cells(x)(y) == Free) {
Some(x, y)
} else None
}
def main (args: Array[String]): Unit = {
val (n, m) = (11, 5)
val cells: Array[Array[Cell]] = Array.fill(n, m)(Free)
cells(1)(1) = Blocked
cells(1)(2) = Blocked
cells(2)(1) = Blocked
val startingPoint = (5, 2)
println("Initial matrix:")
printMatrix(cells)((i, j, value) => if ((i, j) == startingPoint) "S" else if (value == Free) "." else "X")
val distancesMatrix = distances(cells, startingPoint)
println("\nDistances from starting point:")
printMatrix(distancesMatrix)((i, j, value) => if (value < 0) "X" else value.toString)
}
private def printMatrix[T](matrix: Array[Array[T]])(formatter: (Int, Int, T) => String) = {
for (i <- 0 until matrix.length) {
for (j <- 0 until matrix(0).length) {
print(formatter(i, j, matrix(i)(j)) + " ")
}
println()
}
}
}
I believe there is a DP (dynamic programming) solution to this problem, looking at this, code below. I realize this is for finding all possible paths to a cell but it can give insight on your condition about 'blanks' or 'walls'
#include <iostream>
using namespace std;
// Returns count of possible paths to reach cell at row number m and column
// number n from the topmost leftmost cell (cell at 1, 1)
int numberOfPaths(int m, int n)
{
// Create a 2D table to store results of subproblems
int count[m][n];
// Count of paths to reach any cell in first column is 1
for (int i = 0; i < m; i++)
count[i][0] = 1;
// Count of paths to reach any cell in first column is 1
for (int j = 0; j < n; j++)
count[0][j] = 1;
// Calculate count of paths for other cells in bottom-up manner using
// the recursive solution
for (int i = 1; i < m; i++)
{
for (int j = 1; j < n; j++)
// By uncommenting the last part the code calculatest he total
// possible paths if the diagonal Movements are allowed
count[i][j] = count[i-1][j] + count[i][j-1]; //+ count[i-1][j-1];
}
return count[m-1][n-1];
}
I'm working on creating an inventory system for a game. The inventory system will use cells and 2D images to represent items, like Minecraft, Diablo, or WoW. I've hit a bit of a snag when trying to let the player place items in the bag (click and drag style).
So far, I've successfully created the inventory grid, which is really smoke and mirrors:
public class InventoryMenu {
boolean objectSelected = false;
Item selectedItem;
public final int COLUMNS = 5;
public final int ROWS = 7;
ArrayList<Item> inv = new ArrayList<Item>((ROWS + 1) * COLUMNS);
Sprite slot;
public void render(Graphics g) {
for (int i = 0; i < 40; i++) {
int col = i % COLUMNS;
int row = ROWS - i / COLUMNS;
slot.draw(g, (Camera.width - slot.getWidth() * COLUMNS) + slot.getWidth()* col, row * slot.getHeight());
if (inv.get(i) != null) {
inv.get(i).render(g);
}
}
if (selectedItem != null) {
selectedItem.render(g);
}
}
Basically, I have an arraylist that can hold items, and it just draws the "slot" image 40 times and if there's an item in that "slot" it draws the item image too. Cool? Cool. The problem comes if I want to allow the player to select an item in their inventory and move it to a different slot. I have no problem letting them pick it up (I use a pretty primitive brute force, but with any reasonably sized inventory, it works):
private Item grabItem(Point2D mouse) {
for (Item i : inv) {
if (i != null) {
if (i.getPhysicsShape().contains(mouse)) {
Item pick = i;
selectedItem = pick;
objectSelected = true;
i = null;
return pick;
}
}
}
return null;
}
That bit of code lets a player pick up an item, but placing it fails - it rarely gets the right slot, except if its the bottom row (0-4):
setDown(){
int slotLoc = calcSlot(InputHandler.mouseCoords);
placeItem(slotLoc);
}
private void placeItem(int loc) {
if(loc < 0 || loc > ROWS * (COLUMNS + 1))
return;
int col = loc % COLUMNS;
int row = ROWS - loc / COLUMNS;
selectedItem.pickUp((Camera.width - slot.getWidth() * COLUMNS) + slot.getWidth() * col, row * slot.getHeight());
inv.set(loc, selectedItem);
selectedItem = null;
objectSelected = false;
}
private int calcSlot(Point2D mouse){
int colPos = (int) (COLUMNS - (Camera.width - mouse.getX()) / slot.getWidth());
int rowPos = (int) (ROWS+1 - (mouse.getY()) / slot.getHeight());
if (colPos > COLUMNS || colPos < 0 || rowPos < 0 || rowPos > ROWS + 1) {
dropItem();
return -1;
} else {
return colPos + 4*rowPos;
}
}
I'm fairly confident that the problem is in calcSlot, but I can't seem to find where. Any help would be greatly appreciated, I'm sure it's something silly.
Images!!
So, I can pick up an item with no problem, and it automatically places it in the last slot. So far, everything is gold.
I can then click that image and lift it out of the grid, and it follows my mouse (mouse is hidden by PrntScrn, but its at the top left corner of the image:
When I try to place the item by clicking in the middle of slot 33, however, it derps and places it, inexplicably, in slot 27.
private int calcSlot(Point2D mouse){
int colPos = (int) (COLUMNS - (Camera.width - mouse.getX()) / slot.getWidth());
int rowPos = (int) (ROWS - ((mouse.getY())- slot.getHeight()) / slot.getHeight());
if (colPos > COLUMNS || colPos < 0 || rowPos < 0 || rowPos > ROWS + 1) {
dropItem();
return -1;
} else {
return COLUMNS*rowPos + colPos;
}
}
The difference % between 33 and 27 is "6"
So i suggest you look very carefully at the fact the numbers and rows run from bottom to top meaning its landed in the "sixth row up" so your linear calculation in the process for which is a row and which is the coord result is getting in the way somewhere in the calculation process (to hazard a guess).
Try placing it in 32 and see what happens for the cell it places.
but also you show the code for calcSlot twice here and in one version it has "ROWS+1"
I'm trying to make the game Tetris in java.
I've gotten it to the point where:
a new block is generated when it hits the floor or its y+1 is not null (meaning there's another block under it)
public void collisionCheck(int x, int y) {
if (activetile.getY() == this.height-2 || getTileAt(x, y+1) != null) {
activetile = new Tile(this, 0, 0);
}
}
A row clears when the bottom row is full of non-null values, or the Tetris pieces (for y = 4 (the floor), loop through x till x = 4 and check if all non-null)
public void checkBottomFull(int x, int y) {
while (getTileAt(x,y) != null) {
say("(" + x + ", " + y +")");
if (x == 3) {
say("row is full");
//replace full row with tiles from above
for (int i = 0; i < 4; i++) {
for (int j = 5; j > 0; j--) {
grid[j][i] = getTileAt(i,j-1);
grid[j-1][i] = null;
}
}
break;
}
x++;
}
}
Right now, I'm using keys to move the block:
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
if(keyCode == KeyEvent.VK_DOWN) {
activetile.setLocation(activetile.getX(), activetile.getY()+1);
System.out.println("coordinates: " + activetile.getX() + ", " + activetile.getY());
collisionCheck(activetile.getX(),activetile.getY());
checkBottomFull(0,4);
repaint();
}
}
There's two issues I'm having:
1) In the picture you'll notice I've dropped the block all the way to the floor... and the row cleared. After it's cleared, it will generate a block to the top left (x=0, y=1) which I have no control over.
2) On the floor there seems to be a red line... which I'm assuming is a row of blocks hidden by the JFrame... I'm not sure why that's there.
FYI: If you're wondering why grid[j][i] has the rows and columns flipped (aka, why it's not grid[i][j]) is because I instantiated it as grid = new Tile[height][width];
Any thoughts?
Thanks!
It is hard to say what is wrong without actually debugging your app.
But maybe try this one:
public void checkBottomFull(int x, int y) {
while (getTileAt(x,y) != null) {
say("(" + x + ", " + y +")");
if (x == 3) {
say("row is full");
//replace full row with tiles from above
for (int i = 0; i < 4; i++) {
for (int j = 4; j >= 0; j--) {
grid[j][i] = getTileAt(i,j-1);
grid[j-1][i] = null;
}
}
break;
}
x++;
}
}
You have 5 rows (indexed from 0 to 4) and 4 columns (indexed from 0 to 3).
What values of height and width do you pass to:
grid = new Tile[height][width];
Because from what I see you should do something like that:
grid = new Tile[5][4];
Bah,
Turns out in the key event, I needed to check if the bottom was full before checking if there is a collision.
I guess what was happening is, when I was checking collisionCheck(activetile.getX(),activetile.getY()); before checkBottomFull(0,4);, when the bottom was full, it would clear the row and set the current row equal to the row above it: grid[j][i] = getTileAt(i,j-1);, the problem was that collisionCheck was generating a new piece and the that newly generated piece was getting cleared and replaced by checkBottomFull.
Putting the collision check after the checkBottomFull ensures that the newly generated piece won't be replaced if bottom is full.