how to replace a 2D array for a new 2D array in a console in Java? - java

My code has some logic issues with the problem mentioned above.
What I'm trying to do is to print a 2D array in the console, and then, after asking for the user's input, the array will change and will replace the old one for this new one in the console.
Here is an example of what I'm trying to do.
Don't pay attention to the numbers on the array, what I am asking only has to do with the elements that are printed in the console.
The console will look like this
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
After the user gives the column, the console will look like this.
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---2---
The code that I attached at the end does all of this, but the problem starts after the user gives the second input. After the user gives his second input (his second column) the console will look like this:
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---1---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---2---
B
2 2 2 3 3 1
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
0 0 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---3---
What it's doing is that it keeps printing and printing new boards instead of "updating" the same board.
What I am trying to achieve is the following: (What I am showing is what I want the console to look like)
(User gives the first input)
Console:
The number that is going to be shoot is ---2---
A
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
2 2 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(User gives second input)
Console:
What column do you want to shoot (A, B, C, D, E, F)
The number that is going to be shoot is ---3---
A
2 2 2 3 3 1
3 3 2 1 1 3
2 2 3 1 1 3
2 3 3 1 3 3
2 2 3 3 1 3
1 3 1 2 2 3
0 0 1 1 3 2
0 0 0 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
(The only 2 changes here are the number that is going to be shoot and the numbers in the array)
In a few words all I want to do is to "update" the board with the result instead of printing and printing new boards over and over again.
The code below is the code I have so far. I included a pseudo code so that you can see what each method does (The whole game structure is on the game() method). I would prefer to not change the code for any of the methods rather than the gameOver method since it is the one that is in "charge" of clearing the consoles and all that stuff. (If you find an answer and involves changing another method that's ok)
Again, the only thing that i'm confused about is on how to replace the existing board instead of printing new boards, not with the content of the arrays.
Here's the code
import java.util.Scanner;
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Collections;
public class Project {
public static final int[][] NEIGHBOURS = // adjacent cells
{{0, 1}, // horizontal -
{1, 0}, // vertical |
{1, 1}, // diagonal \
{1, -1}}; // diagonal /
private List<Island> islands = new ArrayList<>(); // collection of Islands
private int[][] grid; // matrix
public Project(int[][] grid) {
this.grid = grid;
}
public static int[][]board = { {0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0} };
public static int[][]numberBoard = createBoard(6, /*Number of colums*/ 5, /*Number of rows*/ 3 /*Bubble types in the board (1, 2 or 3)*/);
//creates random board
public static void main( String[] args) {
game();
}
public static void game() {
String input; //the Input
int randomNumber;
int[] location;
board = combine(board, numberBoard); //Empty Board to Randomized Board
while(gameOver(board).equals("GAME CONTINUES")) {
gameOver(board); //Scans the array to see if the game is still going or not
//The code below up to "shiftRow" shouldn't really matter with the question because all it's doing is to make changes to the array
//but does not print anything to the console so I seperated them.
randomNumber = createRandomNumber(3); //creates a randomNumber
input = shoot(randomNumber); //Input
board = putNumber(board, input, randomNumber); //Places Input
location = numberLocation(board, input, randomNumber); //Gets location of the placed number
board = destroyAdjacentNumbers(board, location[0], location[1], randomNumber); //Deletes any number that is both, a neighbor and
//has the same value as the number placed
Project destroyIslands = new Project(board); //destroys the islands (Chunks of numbers that are completely surrounded by zeros)
destroyIslands.deleteIslandBoard2();
shiftRow(board); //Shifts the row down
destroyIslands.printGrid(); //prints the grid
}
if(gameOver(board).equals("CONGRATULATIONS, YOU WON THE GAME!")) {
clearConsole();
System.out.println("CONGRATULATIONS, YOU WON THE GAME!");
} else if(gameOver(board).equals("YOU LOST THE GAME!")) {
clearConsole();
System.out.println("YOU LOST THE GAME!");
}
}
public static int[][] createBoard(int cols, int rows, int numBubbleTypes) {
int[][] board = new int[rows][cols];
for( int row = 0; row < rows; row++ ) {
for( int col = 0; col < cols; col++ ) {
board[row][col] = (int)(Math.random() * (double)numBubbleTypes) + 1;
}
}
return board;
}
public static int createRandomNumber(int type) {
double randomNumber = Math.random();
randomNumber = randomNumber * type;
int roundedNumber = (int) Math.floor(randomNumber);
int result = roundedNumber + 1;
return result;
}
public static void printGrid(int[][] grid) {
for( int row = 0; row < grid.length; row++ ) {
for( int col = 0; col < grid[row].length; col++ ) {
System.out.print( grid[row][col] + " " );
}
System.out.println("");
}
}
public static int[][] shiftRow( int[][] grid ) {
/*
* Pseudocode:
* Shift down first row to second row, then third row goes up two rows
*
* Shift each row down one (except the last row), then shift bottom row to the top
*
* Store the row after the current row in a temporary box, then overwrite the next row
* with the first, then repeat (excluding the last row).
*/
int[] tempList = new int[ grid[0].length ]; //0, 0, 0
for( int col = 0; col < grid[0].length; col++ ) {
tempList[col] = grid[0][col];
}
for( int row = 0; row < grid.length - 1; row++ ) {
int[] currentList = new int[ grid[row].length ];
for( int col = 0; col < grid[row].length; col++ ) {
currentList[col] = tempList[col];
tempList[col] = grid[row+1][col];
grid[row+1][col] = currentList[col];
}
}
int[][]newRow = createBoard(6, 1, 3);
for( int col = 0; col < grid[0].length; col++ ) {
grid[0][col] = newRow[0][col];
}
return grid;
}
public static void fillBoard(int[]array) {
}
public static String shoot(int number) {
System.out.println("What column do you want to shoot (A, B, C, D, E, F)");
System.out.println("The number that is going to be shoot is ---" + number + "--- ");
Scanner scanShoot = new Scanner(System.in);
String input = scanShoot.nextLine();
return input;
}
private static void clearConsole() {
System.out.print('\u000C'); //Clear terminal
}
public static int[][] combine(int[][]board, int[][] numberBoard) {
for(int i = 0; i < numberBoard.length; i++) {
for(int j = 0; j < numberBoard[i].length; j++) {
board[i][j] = numberBoard[i][j];
}
}
return board;
}
public static int[][] putNumber(int[][] board, String columnInput, int randomNumber) {
if(columnInput.equals("A") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][0] == 0) {
board[row][0] = randomNumber;
break;
}
}
}
if(columnInput.equals("B") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][1] == 0) {
board[row][1] = randomNumber;
break;
}
}
}
if(columnInput.equals("C") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][2] == 0) {
board[row][2] = randomNumber;
break;
}
}
}
if(columnInput.equals("D") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][3] == 0) {
board[row][3] = randomNumber;
break;
}
}
}
if(columnInput.equals("E") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][4] == 0) {
board[row][4] = randomNumber;
break;
}
}
}
if(columnInput.equals("F") ) {
for(int row = 0; row < board.length; row++) {
if(board[row][5] == 0) {
board[row][5] = randomNumber;
break;
}
}
}
return board;
}
public static int [] numberLocation(int [][] board, String column, int randomNumber) {
int columnIndex = column.charAt (0) - 'A';
int saveRow = -1;
for (int row = 0; row < board.length; row++) {
if (columnIndex >= 0 && columnIndex < board[row].length && board [row][columnIndex] == 0) {
board [row][columnIndex] = randomNumber;
saveRow = row;
break;
}
}
return new int [] { saveRow, columnIndex };
}
public static void destroyNumbers(int num, int[][] grid) {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] == num) {
grid[i][j] = 0;
}
}
}
}
public static int[][] destroyAdjacentNumbers(int[][] array, int row, int col, int num) {
if (row < 0 || row >= array.length || col < 0 || col >= array[row].length) {
return array;
}
if (array[row][col] == num) {
array[row][col] = 0;
}
if (row > 0 && array[row - 1][col] == num) {
array[row - 1][col] = 0;
destroyAdjacentNumbers(array, row - 1, col, num);
}
if (row < array.length - 1 && array[row + 1][col] == num) {
array[row + 1][col] = 0;
destroyAdjacentNumbers(array, row + 1, col, num);
}
if (col > 0 && array[row][col - 1] == num) {
array[row][col - 1] = 0;
destroyAdjacentNumbers(array, row, col - 1, num);
}
if (col < array[row].length - 1 && array[row][col + 1] == num) {
array[row][col + 1] = 0;
destroyAdjacentNumbers(array, row, col + 1, num);
}
return array;
}
public static void numberShot(int number) {
System.out.println("The number that is going to be shot is " + " --- " + number + " --- " );
}
public static String gameOver(int[][] array) {
boolean hasEmpty = false;
boolean hasNonEmpty = false;
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++) {
if (array[i][j] == 0) {
hasEmpty = true;
} else {
hasNonEmpty = true;
}
}
}
if (hasEmpty && hasNonEmpty) {
return "GAME CONTINUES";
} else if (hasEmpty) {
clearConsole();
return "CONGRATULATIONS, YOU WON THE GAME!";
} else {
clearConsole();
return "YOU LOST THE GAME!";
}
}
public static int[][] deleteIslandBoard(int[][] array) {
// Create a boolean array to track which cells have been visited
boolean[][] visited = new boolean[array.length][array[0].length];
// Iterate
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[0].length; j++) {
// If the cell is not visited and is part of an island
if (!visited[i][j] && array[i][j] != 0) {
// Delete the island by setting all cells to 0
deleteIsland(array, i, j, visited);
}
}
}
// Return the modified array
return array;
}
public static void deleteIsland(int[][] array, int i, int j, boolean[][] visited) {
// Check if the current cell is out of board or if it has already been visited
if (i < 0 || i >= array.length || j < 0 || j >= array[0].length || visited[i][j]) {
return;
}
// Mark the current cell as visited
visited[i][j] = true; // If the current cell is part of the island, set it to 0
if (array[i][j] != 0) {
array[i][j] = 0;
// Recursively delete the neighboring cells that are part of the island
deleteIsland(array, i - 1, j, visited);
deleteIsland(array, i + 1, j, visited);
deleteIsland(array, i, j - 1, visited);
deleteIsland(array, i, j + 1, visited);
}
}
public class Island implements Comparable<Island> {
private List<int[]> cells = new ArrayList<>();
public void addCell(int[] cell) {
cells.add(cell);
}
public void destroy() {
cells.forEach(cell -> grid[cell[0]][cell[1]] = 0);
}
#Override
public int compareTo(Island other) {
return Integer.compare(cells.size(), other.cells.size());
}
}
public void deleteIslandBoard2() {
exploreIslands();
deleteSmallerIslands();
}
public void exploreIslands() {
boolean[][] visited = new boolean[grid.length][grid[0].length];
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (!visited[i][j] && grid[i][j] != 0) { // if a New Island was found
exploreIsland(new int[]{i, j}, visited); // explore the Island, i.e. index all its cell and mark them as visited
}
}
}
}
/**
* Depth first search implementation
*/
public void exploreIsland(int[] cell, boolean[][] visited) {
Island island = new Island();
islands.add(island); // updating the list of Islands
Deque<int[]> stack = new ArrayDeque<>();
stack.push(cell);
while (!stack.isEmpty()) {
int[] next = stack.poll();
island.addCell(next);
for (int[] shift : NEIGHBOURS) {
int row = next[0] + shift[0];
int col = next[1] + shift[1];
if (isValid(row, col) && !visited[row][col]) { // if cell exist, non-zero and not visited yet
stack.push(new int[]{row, col});
visited[row][col] = true;
}
}
}
}
public boolean isValid(int row, int col) {
return row >= 0 && row < grid.length
&& col >= 0 && col < grid[0].length
&& grid[row][col] != 0;
}
public void deleteSmallerIslands() {
if (islands.isEmpty()) return; // otherwise Collections.max() would throw NoSuchElementException
Island largest = Collections.max(islands);
for (Island next : islands) {
if (next != largest) next.destroy();
}
}
public void printGrid() {
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
System.out.print(grid[i][j] + " ");
}
System.out.println();
}
}
}
Most of this code shouldn't matter, just the methods that print stuff!!!!!!!!!!!!!!!

Related

Trying to implement Conway's Game of Life in Java but having trouble with counting the "living" cells around a cell

I'm a beginner in coding. I have this problem that I know already, but I can't seem to find the solution
Given a preset 5x5 2D array representing the board (. means dead cell and 0 means living cell.
)
. . . . .
. . . . .
. . 0 . .
. . . . .
. . . . .
I have a method countLivingNeighbors that counts the "living" cells around a cell.
When I visualize the number of living neighbors of each cell in a the same grid pattern, the expected output and the actual output are:
EXPECTED: ACTUAL:
0 0 0 0 0 0 0 0 0 0
0 1 1 1 0 0 1 1 1 0
0 1 0 1 0 0 1 0 0 0
0 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
I know the problem is that the method countLivingNeighbors doesn't count a "living" cell if its position is on the left, above-right, above, or above-left of the current cell. But I'm pretty sure the logic of my code is alright, I think.
For reference, here's the code for the method:
// 'true' means living, 'false' means dead
static int countLivingNeighbors(boolean[][] board, int posX, int posY) {
int counter = 0;
// Iterate around the cell
for (int j = -1; j <= 1; j++) {
if (posY + j < 0 || posY + j >= board.length) continue;
for (int i = -1; i <= 1; i++) {
if (posX + i < 0 || posX + i >= board[0].length) continue;
if (board[posY + j][posX + i]) ++counter;
}
}
// It counts the current cell as well, so let's remove that.
if (board[posY][posX]) --counter;
return counter;
I don't think I have problems with the code except for this which stomps me for quite a while now. Any help is much appreciated.
Here's the current version of the entire code.
package GameOfLife;
import java.util.Random;
public class Main {
public static void main(String[] args){
int boardWidth = 5, boardHeight = 5;
boolean[][] board = {{false, false, false, false, false},
{false, false, false, false, false},
{false, false, true , false, false},
{false, false, false, false, false},
{false, false, false, false, false}};
renderBoard(board);
System.out.println();
board = getNextBoardState(board);
renderBoard(board);
}
static boolean[][] createRandomBoard(int width, int height) {
boolean[][] board = new boolean[height][width];
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
switch (new Random().nextInt(2)) {
case 0 -> board[i][j] = false;
case 1 -> board[i][j] = true;
}
}
}
return board;
}
static void renderBoard(boolean[][] board) {
for (boolean[] cellRows : board) {
for (boolean cells : cellRows) {
if (cells) System.out.print(" 0 ");
else System.out.print(" . ");
} System.out.println();
}
}
static boolean[][] getNextBoardState(boolean[][] board) {
boolean[][] nextBoard;
nextBoard = board;
for (int y = 0; y < board.length; y++) {
for (int x = 0; x < board[0].length; x++) {
int livingNeighbors = countLivingNeighbors(board, x, y);
System.out.print(" " + livingNeighbors + " ");
nextBoard[y][x] = setNextCellState(livingNeighbors, board[y][x]);
} System.out.println();
} System.out.println();
return nextBoard;
}
static int countLivingNeighbors(boolean[][] board, int posX, int posY) {
int counter = 0;
for (int j = -1; j < 2; j++) {
if (posY + j < 0 || posY + j >= board.length) continue;
for (int i = -1; i < 2; i++) {
if (posX + i < 0 || posX + i >= board[0].length) continue;
if (board[posY + j][posX + i]) ++counter;
}
}
if (board[posY][posX]) --counter;
return counter;
}
static boolean setNextCellState(int livingNeighbors, boolean cellState) {
if (cellState) {
if (livingNeighbors <= 1 || livingNeighbors > 3) return false;
} else {
if (livingNeighbors == 3) return true;
}
return cellState;
}
}
In the getNextBoardState method you are assigning nextBoard = board.
static boolean[][] getNextBoardState(boolean[][] board) {
boolean[][] nextBoard;
nextBoard = board;
It's natural to think that this should copy all of the values in the board array into a new array called nextBoard. But in fact, it creates a new pointer called nextBoard, which points to the same array as board. This means that when you change a value in nextBoard, you are in fact changing the same value pointed to by board.
To get around this, make a method that copies values from the board into a new board. Here's a very simple example (which has some pitfalls of its own):
private static boolean[][] copyBoard(boolean[][] board) {
boolean[][] newBoard = new boolean[board.length][board[0].length];
for (int i = 0; i < board.length; i++) {
for (int j = 0; j < board[i].length; j++) {
newBoard[i][j] = board[i][j];
}
}
return newBoard;
}
Then in getNextBoardState, replace
boolean[][] nextBoard;
nextBoard = board;
with
boolean[][] nextBoard = copyBoard(board);
You should get the result you expect:
0 0 0 0 0
0 1 1 1 0
0 1 0 1 0
0 1 1 1 0
0 0 0 0 0
Note: the copyBoard method assumes that board always has at least one inner array (board[0]) and that all of board's inner arrays have the same length as the array at board[0].

Finding the number of areas of true values in a 2D array

I have a question about my homework in scratching my head-on.
So I need to build a program that counts the number of areas of true value (near to each other) in the 2D array.
{0,1,0,0}
{1,0,0,1}
{1,1,0,1}
{1,0,0,1}
So the program needs to return 3 because there 3 places with trues.
If there are no true then to return 0.
The program needs to recursive and without loops.
Thanks in advance to the ones that will help me solve this one. I didn't even have any idea how to start it.
Ok, you do a dfs to record the cells you went and you can have a boolean[][] to record the cells you went. Then you just loop through the grid to see where you have not gone. If you did not go there yet, go there and also perform a dfs on nearby cells, but anyway, a code would be more clear.
public static int[][] grid;
public static boolean[][] went;
public static int r, c;
public static void dfs(int x, int y) {
if (x < 0 || x >= r || y < 0 || y >= c) {//out of the grid
return;
}
if (went[x][y]) {//I went here
return;
}
went[x][y] = true;
if (grid[x][y] == 0) {//It's false here so don't go
return;
}
dfs(x - 1, y);
dfs(x + 1, y);
dfs(x, y - 1);
dfs(x, y + 1);
}
public static void main(String[] args) throws IOException {
BufferedReader input =
new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(input.readLine());
//input reading
r = Integer.parseInt(st.nextToken());
c = Integer.parseInt(st.nextToken());
grid = new int[r][c];
went = new boolean[r][c];
for (int i = 0; i < r; i++) {
st = new StringTokenizer(input.readLine());
for (int j = 0; j < c; j++) {
grid[i][j] = Integer.parseInt(st.nextToken());
}
}
//end of input reading
int cnt = 0;//number of areas
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
// If I have not went have and the value
// must be true so I would perform a dfs
// (since I only care about the value of 1s)
if (!went[i][j] && grid[i][j] == 1) {
cnt++;//add to our counter
dfs(i, j);//have not went here
}
}
}
System.out.println(cnt);
}
This solution uses the only recursion. No loops.
public static void main(String... args) {
System.out.println(countTrueAreas(new int[][] {
{ 0, 1, 0, 0 },
{ 1, 0, 0, 1 },
{ 1, 1, 0, 1 },
{ 1, 0, 0, 1 } })); // 3
}
public static int countTrueAreas(int[][] grid) {
return countTrueAreas(grid, 0, 0, 10) - 10;
}
private static int countTrueAreas(int[][] grid, int row, int col, int num) {
if (row == grid.length)
return num;
if (col == grid[row].length) {
if (++row == grid.length)
return num;
col = 0;
}
if (grid[row][col] == 1)
dfs(grid, row, col, num++);
return countTrueAreas(grid, row, col + 1, num);
}
private static void dfs(int[][] grid, int row, int col, int num) {
if (row < 0 || row >= grid.length)
return;
if (col < 0 || col >= grid[row].length)
return;
if (grid[row][col] != 1)
return;
grid[row][col] = num;
dfs(grid, row, col - 1, num);
dfs(grid, row, col + 1, num);
dfs(grid, row - 1, col, num);
dfs(grid, row + 1, col, num);
}

What is wrong with this flood fill algorithm?

https://www.kakaocode.com/tryouts/1353/intro
Given a picture array, the code should return the number of separated areas and size of a maximum area.
The color is represented as an integer (0 for white. white area doesn't count).
m and n are # of row and col each.
For example,
m = 6, n = 4
1 1 1 0
1 2 2 0
1 0 0 1
0 0 0 1
0 0 0 3
0 0 0 3
should return [4, 5] because there are 4 separate areas and the largest area contains 5 ones.
Another example:
1 1 1 0
1 1 1 0
0 0 0 1
0 0 0 1
0 0 0 1
this one should return [2, 6]
public int max = 0;
public int[] solution(int m, int n, int[][] picture) {
// answer[0] = numberOfArea
// answer[1] = maxSizeOfOneArea
int[] answer = new int[2];
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
if (picture[i][j] != 0){
max = 0;
floodFill(i, j, picture[i][j], picture);
if (max > answer[1]) answer[1] = max;
answer[0]++;
}
}
}
return answer;
}
public void floodFill(int i, int j, int num, int[][] picture){
if (i < 0 || j < 0 || i >= picture.length || j >= picture[0].length || picture[i][j] != num)
return;
max++;
picture[i][j] = 0;
floodFill(i - 1, j, num, picture);
floodFill(i + 1, j, num, picture);
floodFill(i, j - 1, num, picture);
floodFill(i, j + 1, num, picture);
}
I tried multiple test cases and it passed all, but it failed when I submitted.
What are some edge cases that I am missing?

Finding 5 values in a row diagonally in Java

I have this 10x10 array:
private static int[][] intersections = new int[10][10];
I'm using this code to find if there are 5 values in a row horizontally:
public static int horizontalCheck() {
String horizontal = "";
for (int i = 0; i < intersections.length; i++) {
for (int j = 0; j < intersections[i].length; j++) {
horizontal += Integer.toString(intersections[i][j]);
}
if (horizontal.indexOf("11111") != -1) {
// White wins.
return 1;
} else if (horizontal.indexOf("22222") != -1) {
// Black wins.
return 2;
}
horizontal = "";
}
return 0;
}
And a similar code to do it vertically. But my question is, how could I find if there are 5 values in a row diagonally? The board is sized 10x10 and the diagonals can be both ways anywhere on the board. If you have any questions or need some more information on the code, make sure to ask.
I suggest you write a helper function for this. The function should take these parameters:
r0 - The starting row from which the check needs to start
c0 - The starting column from which the check needs to start
dr - The vertical step from {-1, 0, 1}
dc - The horizontal step from {-1, 0, 1}
len - The number of items to be found
num - The number to find.
Here is how this function may look:
private static boolean checkRow(int r0, int c0, int dr, int dc, int len, int num) {
for (int k = 0 ; k != len ; k++) {
int r = r0 + k*dr;
int c = c0 + k*dc;
if (r < 0 || c < 0 || r >= intersections.length || c > intersections[r].length || intersections[r][c] != num) {
return false;
}
}
return true;
}
With this function in hand, you can check for len items in a row in any direction that you wish:
// See if we've got five eights in any direction:
for (int r = 0 ; r != intersections.length ; r++) {
for (int c = 0 ; c != intersections[r].length ; c++) {
if (checkRow(r, c, 0, 1, 5, 8)) {
System.out.println("Horizontal, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, 0, 5, 8)) {
System.out.println("Vertical, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, 1, 5, 8)) {
System.out.println("Diagonal descending right, starting at "+r+" " +c);
}
if (checkRow(r, c, 1, -1, 5, 8)) {
System.out.println("Diagonal descending left, starting at "+r+" " +c);
}
}
}

How to find escape routes from one point to another in a matrix?

This is not a homework. It's just a practice question.
Given a matrix find the number of possible escape routes from (0,0) to (N,N). You cannot move diagonally.
A '0' position represents an open cell, while a '1' represents a blocked cell. I started my journey from (0,0) and had to reach (N,N).
Input format
First line is a single odd positive integer, T (<= 85), which indicates the size of the matrix. T lines follow, each containing T space separated numbers which are either '0' or '1'.
Output format
Output the number of ways in which I could have escaped from (0,0) to (N,N).
Sample Input
7
0 0 1 0 0 1 0
1 0 1 1 0 0 0
0 0 0 0 1 0 1
1 0 1 0 0 0 0
1 0 1 1 0 1 0
1 0 0 0 0 1 0
1 1 1 1 0 0 0
Sample Output
4
According to my solution I have taken four directions - left (l), right(r), up(u), down(d).
The problem is that it is giving a wrong answer or a stackoverflow error. What is missing?
And is this the optimal solution to this question?
My Solution (Java)
import java.io.BufferedReader;
import java.io.InputStreamReader;
class testclass {
int no_of_escapes = 0 ;
int[][] arr;
int matrixlength;
public static void main(String[] args) throws Exception
{
testclass obj = new testclass();
obj.checkpaths(0,0,"");
System.out.print(obj.no_of_escapes);
}//main
testclass()
{
try
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
matrixlength =Integer.parseInt(br.readLine());
arr = new int[matrixlength][matrixlength];
for( int k = 0; k < matrixlength; k++){
String str = br.readLine();
int count = 0;
for(int j=0 ; j< ((2*matrixlength)-1); j++){
int v = (int)str.charAt(j) - 48;
if(v == -16){}
else{
arr[k][count] = v;
count++;
}
}//for j
}//for k
}
catch(Exception e){}
}
public void checkpaths(int m, int n,String direction){
if((m == matrixlength -1) && (n == matrixlength-1))
{
no_of_escapes = no_of_escapes +1;
return;
}
if(!direction.equals("l"))
{
if(m < matrixlength && n < matrixlength)
{
if((n+1) < matrixlength )
{
if(arr[m][n+1]==0 )
{
checkpaths(m,n+1,"r");
}
}
}
}
if(!direction.equals("u"))
{
if((m+1) < matrixlength )
{
if(arr[m+1][n]==0 )
{
checkpaths(m+1,n,"d");
}
}
}
if(!direction.equals("r"))
{
if(m < matrixlength && n < matrixlength)
{
if((n+1) < matrixlength )
{
if(arr[m][n+1]==0 )
{
checkpaths(m,n+1,"l");
}
}
}
}
if(!direction.equals("d"))
{
if((m-1)>=0)
{
if(arr[m-1][n]==0 )
{
checkpaths(m-1,n,"u");
}
}
}
}
}//class
I would keep a second 2D array of booleans to mark the cells you already visited, as shown in the snippet below. I also simplified some other parts of the code, to reduce code-duplication.
Of course, you need to initialize visited in your constructor, just as you initialized arr, by using visited = new boolean[matrixLength][matrixLength].
int[][] arr;
boolean[][] visited;
final int[][] directions = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
public boolean isValid(int x, int y) {
return 0 <= x && x < matrixLength
&& 0 <= y && y < matrixLength
&& arr[x][y] == 0
&& !visited[x][y];
}
public void checkPaths(int x, int y) {
if (x == matrixLength-1 && y == matrixLength-1) {
no_of_escaped++;
} else {
for (int[] d : directions) {
if (isValid(x + d[0], y + d[1])) {
visited[x + d[0]][y + d[1]] = true;
checkPaths(x + d[0], y + d[1]);
visited[x + d[0]][y + d[1]] = false;
}
}
}
}

Categories