I am making Tetris in Java. I am having difficulty having my blocks shift down, once a row has been removed (because it filled up). My code is throwing an arrayIndexOutOfBounds error. The rest of the code works, where it finds which row is full and sets that row to 0. But in the if statement near the bottom, that's where it doesn't work. Thanks ! :)
// Removes any rows that are filled
public static int removeRows()
{
// Variables
int numOfRows = tetrisGrid.getNumOfRows();
int numOfCols = tetrisGrid.getNumOfCols();
int numRowsRemoved = 0;
int [][] grid = tetrisGrid.getGrid();
// Finds the number of rows that are filled
for (int row = 0; row < numOfRows; row++)
{
for (int col = 0; col < numOfCols; col++)
{
int blockValue = tetrisGrid.getBlockValue(row, col);
if (blockValue == 0)
{
break;
}
if (col == numOfCols - 1)
{
numRowsRemoved++;
// Sets the rows filled to zero
for (int change = 0; change < numOfCols; change++)
{
grid [row][change] = 0;
}
// Shifts everything down until it hits blocks below
for (int shiftRow = 0; shiftRow < 2; shiftRow++)
{
for (int shiftCol = 0; shiftCol < numOfCols; shiftCol++)
{
if (blockValue == 1)
{
grid [row][col] = 0;
row++;
col++;
grid [row][col] = 1;
row--;
col--;
}
else if (blockValue == 0)
break;
}
}
// TAKE OUT -------------------------
System.out.println ("--------");
tetrisGrid.printGrid();
System.out.println ("--------");
// -------------------------
}
}
}
tetrisGrid.setGrid(grid);
return numRowsRemoved;
}
Related
I am starting with Java and I was wondering how could you reverse a diagonal search like the one shown in the picture but from bottom left to right or from right top to bottom left.
The code for the diagonal search shown in the picture is :
// top-left to bottom-right - green diagonals
for (int rowStart = 0; rowStart < rowMax - 4; rowStart++) {
int count = 0;
int row, col;
for (row = rowStart, col = 0; row < rowMax && col < colMax; row++, col++) {
if (gridTable[row][col] == player) {
count++;
if (count >= 4) return 1;
} else {
count = 0;
}
}
}
// top-left to bottom-right - red diagonals
for (colStart = 1; colStart < colMax - 4; colStart++) {
count = 0;
int row, col;
for (row = 0, col = colStart; row < rowMax && col < colMax; row++, col++) {
if (gridTable[row][col] == player) {
count++;
if (count >= 4) return 1;
} else {
count = 0;
}
}
}
public class matrix {
public static void main (String[] args) {
int[][] matrix = Array();
}
}
You need a count for each row for all columns and vice versa.
As you count upto 1 a boolean suffices: having found a non-zero element.
Instead of for row/for col and for col/for row which is a non space consuming fine algorith you could have done:
public static boolean isGPM(int [][] matrix) {
boolean[] rowNonZero = new boolean[matrix.length];
boolean[] colNonZero = new boolean[matrix[0].length];
for (int row = 0; row < matrix.length; row++) {
for (int col = 0; col < matrix[0].length; col++) {
if (matrix[row][col] != 0) {
if (rowNonZero[row] || colNonZero[col]) {
return false;
}
rowNonZero[row] = true;
colNonZero[col] = true;
}
}
}
return true;
}
Above an array for rowNonZero is not needed as you see.
Your version would be:
public static boolean isGPM(int [][] matrix) {
for (int row = 0; row < matrix.length; row++) {
boolean nonZero = false;
for (int col = 0; col < matrix[0].length; col++) {
if (matrix[row][col] != 0) {
if (nonZero) {
return false;
}
nonZero = true;
}
}
}
for (int col = 0; col < matrix[0].length; col++) {
boolean nonZero = false;
for (int row = 0; row < matrix.length; row++) {
if (matrix[row][col] != 0) {
if (nonZero) {
return false;
}
nonZero = true;
}
}
}
return true;
}
Since my reputation is too low to comment I'll post an answer. In isGPM function in your loops when you check if count/sum is not equal to 1, in your first iteration it is always going to be 0 and return false, unless there is a number that is different from 0 on the first position in array.
The way I'd dodge this is to do it like this:
int count = 0;
for(int row = 0; row < matrix.length; row++) {
for(int col = 0; col < matrix[0].length; col++)
if (matrix[row][col] != 0) {
count++;
}
}
if (count != 1)
return false;
You just move out the variable declaration of count from for loop and after the loop is finished you do the check. You can do the same thing for your other loop in the function.
The following pice of code is my code for my Game of Life. For some reason it works very strangely. The first few steps of the game are wrong, and then the whole output turns to zeroes. I don't know which method is causing the problem, but I assume it is the count neighbors method.
The board is a 2D array called GOLBoard, and the x and y coordinates are cellRow and cellCol. Alive cells are 1, and dead cells are 0s. The way I avoid out of bounds problems are by making the board 12x12, but I use only 1 to 11 for rows and columns.
<code> #Override
public int countNeighbours(int cellRow, int cellCol) {
int neighbours = 0;
for (int i = cellRow-1; i < cellRow + 2; i++) {
for (int j = cellCol - 1; j < cellCol + 2; j++) {
if (GOLBoard[i][j] == 1) {
neighbours += 1;
}
}
}
if (GOLBoard[cellRow][cellCol] == 1) {
return(neighbours-1);
} else {
return(neighbours);
}
}
#Override
public int applyRules(int cellRow, int cellCol) {
int alive = 0;
if (GOLBoard[cellRow][cellCol] == 1) {
if (countNeighbours(cellRow, cellCol) == 2 || countNeighbours(cellRow, cellCol) == 3) {
alive = 1;
} else if (countNeighbours(cellRow, cellCol) < 2 || countNeighbours(cellRow, cellCol) > 3) {
alive = 0;
}
}
if (GOLBoard[cellRow][cellCol] == 0) {
if (countNeighbours(cellRow, cellCol) == 3) {
alive = 1;
}
}
return (alive);
}
#Override
public void takeStep() {
for (int row = 1; row < 11; row++) {
for (int col = 1; col < 11; col++) {
GOLBoard[row][col] = applyRules(row, col);
}
}
}
#Override
public String toString() {
for (int row = 1; row < 11; row++) {
for (int col = 1; col < 11; col++) {
System.out.print("[" + GOLBoard[row][col] + "]");
}
System.out.println("");
}
return("");
}
} <code>
If I am recalling the rules of GOL correctly, the evolution of the board should proceed in a series of "generations", wherein the state of each cell on a "new" board is determined solely by the conditions of the corresponding cell on the "old" board. Your program is trying to continuously evolve a single board, so that changes to previously computed cells are affecting the outcome of cells yet to be computed. Your takeStep routine should be doing something more like this:
newBoard = new int[12][12];
for (int row = 1; row < 11; row++) {
for (int col = 1; col < 11; col++) {
newBoard[row][col] = applyRules(row, col);
}
}
GOLBoard = newBoard;
As far as I can tell, your countNeighbours is OK.
I've been working on this for hours! I feel like the solution might be really easy but I just can't see it out for the life of me.
I want to know how to make the do-while loop in the userInput() part actually stop when the user input for var1 or var 2 is outside of the range. Less than 0 or greater than 10. Here's the original question:
modify PlayLife so the user can enter a series of
row, col coordinates between 1 and 10 to make cells alive. Entering a value
less than 1 or greater than 10 will be the signal the user is done.
import java.util.Scanner;
public class PlayLife
{
public static void main(String[] args)
{int answer;
World myWorld = new World(10, 10);
System.out.println("Enter a row and column number between 1 and 10 to make a cell live:");
myWorld.userInput();
System.out.println(myWorld);
System.out.println();`
World
import java.util.Scanner;
import java.util.Random;
public class World
{
private Cell[][] board; //a 2 dimensional array of Cells called board
private int rows;
private int cols;
int var1 = 0, var2 = 0 , test;
int row, col;
public World(int numOfRows, int numOfCols)
{
int row, col;
rows = numOfRows;
cols = numOfCols;
board = new Cell[rows][cols];
//the following nested loop creates the rows X cols array of "dead" Cells
for(row = 0; row < rows; row++)
for(col = 0; col < cols; col++)
board[row][col] = new Cell(false);
}
public boolean getStatus(int row, int col)
{
return board[row][col].getStatus();
}
public void setStatus(int row, int col, boolean status)
{
board[row][col].setStatus(status);
}
public void makeAlive(int row, int col)
{
board[row][col].setStatus(true);
}
public void makeDead(int row, int col)
{
board[row][col].setStatus(false);
}
public void userInput()
{
Scanner keyboard = new Scanner(System.in);
for(col = 0; col < cols; col++)
for(row = 0; row < rows; row++)
do
{
var1 = keyboard.nextInt();
var2 = keyboard.nextInt();
}
while(var1 < 0 || var1 >= 10 || var2 < 0 || var2 >= 10);
board[var1][var2].setStatus(true);
}
public void randomFill()
{
int row, col;
Random pick = new Random();
for(row = 0 ; row < rows; row++)
for(col = 0; col < cols; col++)
if(pick.nextInt(4)==0) //make 25% of the cells alive
board[row][col].setStatus(true);
}
public String toString()
{
String boardPic = ""; //start with an empty string
int row, col;
for(row = 0; row < rows; row++)
{
for(col = 0; col < cols; col++)
if(board[row][col].getStatus())
boardPic = boardPic + "X"; //if the cell is alive, add an X to it
else
boardPic = boardPic + "."; //otherwise adda dot
boardPic = boardPic + "\n"; //after finishing all columns in a row, add a newline character
}
return boardPic;
}
// counts all live cells in a 3 X 3 array then subtracts 1 if the center cell is alive
private int countNeighbors(int curRow, int curCol)
{
int row, col, neighbors = 0;
for(row = curRow - 1; row <= curRow + 1; row++)
for(col = curCol - 1; col <= curCol + 1; col++)
if(board[row][col].getStatus())
neighbors++;
//Is the center cell alive?
if(board[curRow][curCol].getStatus())
neighbors--;
return neighbors;
}
//The outside edge is already dead, so this only processes row 1-8 and column 1-8
//if a cell has three neighbors, it will be alive regardless of its current status
//if a cell has two neighbors, it will be the same in the next gen as the last.
public void nextGen()
{
World nextOne = new World(rows, cols); //makes a new "scratch" array
int row, col, neighbors;
for(row = 1; row < rows - 1; row++)
for(col = 1; col < cols - 1; col++)
{
neighbors = countNeighbors(row, col);
if(neighbors == 3)
nextOne.makeAlive(row, col);
else if (neighbors == 2)
nextOne.setStatus(row, col, this.getStatus(row, col)); //"this" refers to the object performing the method
}
//copy new world just created to exixting world
for(row = 0; row < rows; row++)
for(col = 0; col < cols; col++)
board[row][col].setStatus(nextOne.board[row][col].getStatus());
}
}
and here's the other one. There's nothing wrong with this one I'm just posting it just in case you'd like to see it
public class Cell
{
private boolean status; //true = alive, false = dead
public Cell(boolean aliveOrDead) //one parameter constructor
{
status = aliveOrDead;
}
public void setStatus(boolean aliveOrDead) //mutator to set the status of the cell via the parameter
{
status = aliveOrDead;
}
public boolean getStatus() //acessor to get the current status
{
return status;
}
}
Seth is right. The expression you use inside your while is not correct for what you are trying to achieve. If you replace it with the code Seth gave you you should be fine.
Right now your code executes only for the values for which you DONT want it to execute.
So something like this
do
{
var1 = keyboard.nextInt();
var2 = keyboard.nextInt();
}
while((var1 > 0 && var1 < 10) && (var2 > 0 && var2 < 10));
This question already has answers here:
Connect 4 check for a win algorithm
(6 answers)
Closed 6 years ago.
I am developing a Connect 4 game with 7x7 fields, horizontal and vertical checks but I dont get diagonal checks works
I can win as long as one of the tokens is not in the last column.
This are all checks:
private static int getWinningInDiagonals() {
// Top-Left -> Bottom-Right
for (int column = 0; column < 7; column++) {
int count = 0;
for (int row = 0; row < 7; row++) {
if (field[row][column] != 0 && field[row+1][column + row - 1] == field[row][column])
count++;
else
count = 1;
if (count >= 4) {
return field[row][column];
}
}
}
// Top-Right -> Bottom-Left
for (int column = 0; column < 7; column++) {
int count = 0;
for (int row = 0; row < 7; row++) {
if (field[row][column] != 0 && field[row+1][column - row + 1] == field[row][column])
count++;
else
count = 1;
if (count >= 4) {
return field[row][column];
}
}
}
return 0;
}
For one you want to move down and right at the same time every time, you also only need to go to 3, 3 as a diagonal cannot occur any farther than that without it leaving the bounds of the array.
This should work for your top left to bottom rights if I'm right in assuming that your top left is your 0,0.
Doing top right to bottom left is a matter of changing the column and row loops and changing how the offset works.
// Top-Left -> Bottom-Right
for (int column = 0; column < 4; column++) {
for (int row = 0; row < 4; row++) {
player = 0;
if (field[row][column] != 0){
player=field[row][column];
offset = 1;
}
while (player != 0){
if (field[row + offset][column + offset] == player){
offset += 1;
}else{
player = 0;
}
}
if(offset >= 4){
return field[row][column];
}
}
}