Creating matrices Java - java

I have trouble creating a matrice for a game map design.
void prepareMatrix(int width, int height)
{
room = new int[height][width];
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
if(i < height/4)
{
room[i][j] = 2;
}
else if(j == 0 || j == --width)
{
room[i][j] = 1;
}
else if(i == --height)
{
room[i][j] = 1;
}
else
{
room[i][j] = 0;
}
}
}
}
I want to create something like this: (1- Wall1, 2- wall2, 0-floor)
2 2 2 2 2 2
2 2 2 2 2 2
1 0 0 0 0 1
1 0 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
And I get this:
2 2 2 2 2 2 2 2 2 2
2 2 2 2 2 2 2 2 2 2
1 0 0 0 0 1 0 0 0 0
1 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 0 0 0 0 0 0 0 0 0
The matrice would be a blueprint for the map.

You are using --width and --height. It appears from the expected result that you want the 1's to go in the first and last columns and in the last row. As a commenter implied, --width does not just return the width minus one, it also reduces width by 1. You may want width - 1 and height - 1 instead.

Like M. Aroosi said, try to change the --width to width-1 and --height to height-1. You don't want to modify the value of a parameter. I think what is happening is that every time it goes through the loop, the values change for width and height.

Related

How to change the values of a multidimensional array in a range?

I want to change the values of a 2d array from a given starting position (rowPos and colPos) for a certain amount of rows and columns.
So far I have the code below:
int[][] block = new int[10][10];
int rowPos = 3, colPos = 3;
int rows = 4, columns = 4;
for (int i = rowPos; i < rows; i++)
for (int j = colPos; j < columns; j++)
block[i][j] = 1;
for (int[] x : block) {
for (int y : x)
System.out.print(y + " ");
System.out.println();
}
However this gives me the following output:
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 1 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 0 0 0 0 0 0
It is only setting the value at rowPos and colPos. This is my expected output:
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 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 0 0 0
0 0 0 1 1 1 1 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
I feel like I'm close but missing something small, please help me!
Change the loops to this:
for (int i = rowPos; i < rows + rowPos; i++)
for (int j = colPos; j < columns + colPos; j++)
block[i][j] = 1;
In your code, you let i and j start at the row and column you want to begin changing the values. That's fine, but it also means your condition doesn't work anymore. Let me show you what happens:
You declare i and set it's value to 3.
You check if i (3) is less than rows (4). Success!
You declare j and set it's value to 3.
You check if j (3) is less than columns (4). Success!
You set block[3][3] to 1.
j is incremented by 1 and is now 4.
You check if j (4) is less than columns (4). Fail!
i is incremented by 1 and is now 4.
You check if i (4) is less than rows (4). Fail!
You print the array's contents.
The problem is that because you start i and j at values greater than 0, you need to keep that in mind when performing the check.

Get last made move from game boards

I have two 2D int arrays that represent game boards. (The initial board and the new board)
Content of the initial board:
013 | 6 0 0 0 4 4 4 4 4 0 0 0 6
012 | 0 0 0 0 0 0 4 0 0 0 0 0 0
011 | 0 0 0 0 0 0 0 0 0 0 0 0 0
010 | 0 0 0 0 0 0 2 0 0 0 0 0 0
009 | 4 0 0 0 0 0 2 0 0 0 0 0 4
008 | 4 0 0 0 0 0 2 0 0 0 0 0 4
007 | 4 4 0 2 2 2 5 2 2 2 0 4 4
006 | 4 0 0 0 0 0 2 0 0 0 0 0 4
005 | 4 0 0 0 0 0 2 0 0 0 0 0 4
004 | 0 0 0 0 0 0 2 0 0 0 0 0 0
003 | 0 0 0 0 0 0 0 0 0 0 0 0 0
002 | 0 0 0 0 0 0 4 0 0 0 0 0 0
001 | 6 0 0 0 4 4 4 4 4 0 0 0 6
A B C D E F G H I J K L M
Content of the new board (after applying a move):
013 | 6 0 0 0 4 4 4 4 4 0 0 0 6
012 | 0 0 0 0 0 0 4 0 0 0 0 0 0
011 | 0 0 0 0 0 0 0 0 0 0 0 0 0
010 | 0 0 0 0 0 0 2 0 0 0 0 0 0
009 | 4 0 0 0 0 0 2 0 0 0 0 0 4
008 | 4 0 0 0 0 0 2 0 0 0 0 0 4
007 | 4 4 0 2 2 2 5 2 2 2 0 4 4
006 | 4 0 0 0 0 0 2 0 0 0 0 0 4
005 | 4 0 0 0 0 0 2 0 0 0 0 0 4
004 | 0 0 0 0 0 0 2 0 0 0 0 0 0
003 | 0 0 0 0 0 0 0 0 0 0 0 0 0
002 | 0 0 0 0 4 0 4 0 0 0 0 0 0
001 | 6 0 0 0 0 4 4 4 4 0 0 0 6
A B C D E F G H I J K L M
I wanna compare the two game boards to get the last fetched move. How can I determine the last made move on this board?
As you can see the last made move is: "E1 - E2" -> The pawn "E1" was put in "E2"
Is there a fast way to compare the two to determine this last made move "E1 - E2"
What I have:
for (int y = 0; y < Board.DIMENSION; y++) {
for (int x = 0; x < Board.DIMENSION; x++) {
// Check where not equal
if (initialBoard.grid[x][y] != newBoard.grid[x][y]) {
// What to add??
}
}
}
Assuming that the user can only make a move over the empty places(0).
You can do something like this:
for (int y = 0; y < size; y++) {
for (int x = 0; x < size; x++) {
// Check where not equal
if (initialBoard.grid[x][y] != newBoard.grid[x][y] && newBoard.grid[x][y] == 0) {
// From move
String from = x +""+ (char)y+65;
}
if(initialBoard.grid[x][y] != newBoard.grid[x][y] && newBoard.grid[x][y] != 0) {
// To move
}
}
}
You will need to find two spots where the boards differ. You already seem to have the logic down to find a spot where the game board has changed. Now you need to decide what direction the move occurs in.
To me, it looks like the board going from 0 to 4 means a piece has moved there. So, if the new int is > the old int... we know this is the end location.
Since you've gotten this far, I think you can figure it out with the follow logic: (maybe there are cases in this game I am not aware of - so you will have to check for those cases)
String startPos, endPos;
for (int y = 0; y < Board.DIMENSION; y++) {
for (int x = 0; x < Board.DIMENSION; x++) {
// Check where not equal
if (initialBoard.grid[x][y] != newBoard.grid[x][y]) {
// if we go from a 0 to a 4, this is the starting position
if (initialBoard.grid[x][y] < newBoard.grid[x][y]) {
// translate the location into a position and store it as startPos
} else {
// translate the location into a position and store it as endPos
}
}
}
}
System.out.println(startPos + " -> " + endPos); // something like that

Java recursion Issue with the flood fill algorithm

I am trying to write a program to locate and count all connected regions in a grid. A connected region consists of a set of marked cells (value 1) such that each cell in the region can be reached by moving up, down, left or right from another marked cell in the region, cells on a diagonal line are not considered connected.
So, it would take an input of:
10 20
0 1 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0
0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 1 1
0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 0 0 1 1 1
1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 1 0
1 1 0 1 0 0 0 1 1 1 0 0 0 1 1 0 1 1 0 0
1 1 1 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 0
0 1 1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 1 1 0
0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0
1 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0
And outputs:
0 1 1 0 0 0 2 0 3 3 0 0 0 0 4 0 0 0 5 0
0 1 1 1 0 2 2 0 0 3 0 0 4 4 4 0 0 0 5 5
0 0 1 0 0 0 2 2 0 3 0 0 0 4 0 0 0 5 5 5
6 0 0 0 0 0 0 0 3 3 0 0 7 0 0 0 5 5 5 0
6 6 0 6 0 0 0 3 3 3 0 0 0 8 8 0 5 5 0 0
6 6 6 6 0 0 0 0 0 0 9 0 8 8 8 0 0 0 0 0
0 6 6 6 0 0 0 9 9 9 9 0 0 8 8 0 8 0 0 0
0 6 6 6 6 6 0 0 9 9 9 0 0 0 8 8 8 8 8 0
0 0 0 6 6 0 0 0 0 9 0 0 0 8 8 0 0 8 8 0
10 0 6 6 6 6 6 0 0 0 0 0 0 0 8 8 0 8 0 0
Right now, when I run the code, I get:
0 2 2 0 0 0 2 0 2 2 0 0 0 0 2 0 0 0 2 0
0 3 3 3 0 3 3 0 0 3 0 0 3 3 3 0 0 0 3 3
0 0 4 0 0 0 4 4 0 4 0 0 0 4 0 0 0 4 4 4
5 0 0 0 0 0 0 0 5 5 0 0 5 0 0 0 5 5 5 0
6 6 0 6 0 0 0 6 6 6 0 0 0 6 6 0 6 6 0 0
7 7 7 7 0 0 0 0 0 0 7 0 7 7 7 0 0 0 0 0
0 8 8 8 0 0 0 8 8 8 8 0 0 8 8 0 8 0 0 0
0 9 9 9 9 9 0 0 9 9 9 0 0 0 9 9 9 9 9 0
0 0 0 10 10 0 0 0 0 10 0 0 0 10 10 0 0 10 10 0
11 0 11 11 11 11 11 0 0 0 0 0 0 0 11 11 0 11 0 0
Here is my code:
package project2;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class Project2 {
private static int height;
private static int length;
public static void main(String[] args) {
String inputFile;
Scanner input = new Scanner(System.in);
System.out.print("Enter input file name: ");
inputFile = "test_case_proj2.txt";
try {
Integer grid[][] = loadGrid(inputFile);
System.out.println("Before flood fill");
printGrid(grid);
findGroups(grid, 0, 0, 2, height, length);
System.out.println("After flood fill");
printGrid(grid);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
public static void findGroups(Integer[][] array, int column, int row,
int counter, int height, int length) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < length; j++) {
if (row < 0 || row >= length || column < 0 || column >= height) {
} else {
if (array[column][j] == 1) {
array[column][j] = counter;
findGroups(array, column, row + 1, counter, height, length);
findGroups(array, column, row - 1, counter, height, length);
findGroups(array, column - row, j, counter, height, length);
findGroups(array, column + row, j, counter, height, length);
}
}
}
counter++;
column++;
row++;
}
}
public static Integer[][] loadGrid(String fileName) throws IOException {
FileInputStream fin;
fin = new FileInputStream(fileName);
Scanner input = new Scanner(fin);
height = input.nextInt();
length = input.nextInt();
Integer grid[][] = new Integer[height][length];
for (int r = 0; r < height; r++) {
for (int c = 0; c < length; c++) {
grid[r][c] = input.nextInt();
}
}
fin.close();
return (grid);
}
public static void printGrid(Integer[][] grid) {
for (Integer[] grid1 : grid) {
for (int c = 0; c < grid[0].length; c++) {
System.out.printf("%3d", grid1[c]);
}
System.out.println();
}
}
}
Does someone see what I am doing wrong?
You put too much responsibilities into one method. You combine the floodfill algorithm with your island numbering algorithm.
I've created this jdoodle.
First of all you better create a single fill method, that does nothing more than filling islands with the value of a counter (I've made it static so you don't need to pass it through the algorithm, although this is arbitrary):
public static void fill(Integer[][] array, int column, int row, int height, int length) {
if (row >= 0 && row < length && column >= 0 && column < height && array[column][row] == 1) {
array[column][row] = counter;
fill(array, column, row + 1, height, length);
fill(array, column, row - 1, height, length);
fill(array, column - 1, row, height, length);
fill(array, column + 1, row, height, length);
}
}
As you can see, it's a simple algorithm that uses recursion.
Secondly, you simply create a method that calls the fill algorithm on all the possible tiles. If you reach a point with a value of 1, you know that this island has not been claimed by another king yet :D. Thus you fill it and claim it to the king with the counter id. Normally one uses a special array of boolean to prevent the fill algorithm to go into an infinite loop. You solved this smartly by starting to assign number from index counter = 2, of course once all island are claimed, you need to decrement the value.
public static void findGroups(Integer[][] array, int column, int row, int height, int length) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < length; j++) {
if (array[i][j] == 1) {
fill(array, i,j, height, length);
counter++;
}
}
}
for (int i = 0; i < height; i++) {
for (int j = 0; j < length; j++) {
if (array[i][j] > 1) {
array[i][j]--;
}
}
}
}
The rest of the algorithm remains the same (the algorithm now reads from stdin, but this is simply to make sure the jdoodle keeps working).
About your algorithm, it's quite hard to understand. For instance you use a fill and part of the calls use column and row, other parts use j. Next your counter is only updated for each row. This causes problems if two idlands start at the same row (as you can see with your output).

Java counting connected regions in a grid

I am trying to locate all four-connected regions in the grid. A four-connected region consists of a set of marked cells (value 1) such that each cell in the region can be reached by moving up, down, left or right from another marked cell in the region. The assignment states that we should use recursion.
An example input would be:
10 20
0 1 1 0 0 0 1 0 1 1 0 0 0 0 1 0 0 0 1 0
0 1 1 1 0 1 1 0 0 1 0 0 1 1 1 0 0 0 1 1
0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 0 0 1 1 1
1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 1 0
1 1 0 1 0 0 0 1 1 1 0 0 0 1 1 0 1 1 0 0
1 1 1 1 0 0 0 0 0 0 1 0 1 1 1 0 0 0 0 0
0 1 1 1 0 0 0 1 1 1 1 0 0 1 1 0 1 0 0 0
0 1 1 1 1 1 0 0 1 1 1 0 0 0 1 1 1 1 1 0
0 0 0 1 1 0 0 0 0 1 0 0 0 1 1 0 0 1 1 0
1 0 1 1 1 1 1 0 0 0 0 0 0 0 1 1 0 1 0 0
And the output should be:
0 1 1 0 0 0 2 0 3 3 0 0 0 0 4 0 0 0 5 0
0 1 1 1 0 2 2 0 0 3 0 0 4 4 4 0 0 0 5 5
0 0 1 0 0 0 2 2 0 3 0 0 0 4 0 0 0 5 5 5
6 0 0 0 0 0 0 0 3 3 0 0 7 0 0 0 5 5 5 0
6 6 0 6 0 0 0 3 3 3 0 0 0 8 8 0 5 5 0 0
6 6 6 6 0 0 0 0 0 0 9 0 8 8 8 0 0 0 0 0
0 6 6 6 0 0 0 9 9 9 9 0 0 8 8 0 8 0 0 0
0 6 6 6 6 6 0 0 9 9 9 0 0 0 8 8 8 8 8 0
0 0 0 6 6 0 0 0 0 9 0 0 0 8 8 0 0 8 8 0
10 0 6 6 6 6 6 0 0 0 0 0 0 0 8 8 0 8 0 0
Right now when I run the code I have, I get this output:
0 2 2 0 0 0 2 0 2 2 0 0 0 0 2 0 0 0 2 0
0 2 2 2 0 2 2 0 0 2 0 0 2 2 2 0 0 0 2 2
0 0 2 0 0 0 2 2 0 2 0 0 0 2 0 0 0 2 2 2
2 0 0 0 0 0 0 0 2 2 0 0 2 0 0 0 2 2 2 0
2 2 0 2 0 0 0 2 2 2 0 0 0 2 2 0 2 2 0 0
2 2 2 2 0 0 0 0 0 0 2 0 2 2 2 0 0 0 0 0
0 2 2 2 0 0 0 2 2 2 2 0 0 2 2 0 2 0 0 0
0 2 2 2 2 2 0 0 2 2 2 0 0 0 2 2 2 2 2 0
0 0 0 2 2 0 0 0 0 2 0 0 0 2 2 0 0 2 2 0
2 0 2 2 2 2 2 0 0 0 0 0 0 0 2 2 0 2 0 0
My code looks like:
package project2;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Scanner;
public class project2 {
private static int height;
private static int length;
public static void main(String[] args) {
String inputFile;
Scanner input = new Scanner(System.in);
System.out.print("Enter input file name: ");
inputFile = input.nextLine();
try {
Integer grid[][] = loadGrid(inputFile);
System.out.println("Before flood fill");
printGrid(grid);
findGroups(grid, 0, 0, 2, height, length);
System.out.println("After flood fill");
printGrid(grid);
} catch (IOException e) {
System.err.println(e.getMessage());
}
}
public static void findGroups(Integer[][] array, int column, int row,
int counter, int height, int length) {
for (int i = 0; i < height; i++) {
for (int j = 0; j < length; j++) {
if (row < 0 || row >= length || column < 0 || column >= height) {
} else {
if (array[i][j] == 1) {
array[i][j] = counter;
findGroups(array, column, row + 1, counter, height, length);
findGroups(array, column, row - 1, counter, height, length);
findGroups(array, column - 1, row, counter, height, length);
findGroups(array, column + 1, row, counter, height, length);
counter++;
}
}
}
}
}
public static Integer[][] loadGrid(String fileName) throws IOException {
FileInputStream fin;
fin = new FileInputStream(fileName);
Scanner input = new Scanner(fin);
height = input.nextInt();
length = input.nextInt();
Integer grid[][] = new Integer[height][length];
for (int r = 0; r < height; r++) {
for (int c = 0; c < length; c++) {
grid[r][c] = input.nextInt();
}
}
fin.close();
return (grid);
}
public static void printGrid(Integer[][] grid) {
for (Integer[] grid1 : grid) {
for (int c = 0; c < grid[0].length; c++) {
System.out.printf("%3d", grid1[c]);
}
System.out.println();
}
}
}
I'm not sure what I am doing wrong, I believe I am moving the counter up after each time. Does anyone have a recommendation of what the issue might be?
Thanks in advance.

Cloning/Copying an Object

I am creating a connect 4 game in Java and i'm trying to make a deep copy of a custom object (The game Board), then modify that copy and add it to a list as part of the mini max algorithm.
This is the code i'm using for copying:
public void getPossibleBoards(Board board) {
for(int i = 0; i < 7; i++) {
if(!board.columns.get(i).isFull()) {
Board tmpBoard = board.copy(board);
tmpBoard.columns.get(i).addCounter(turn);
boardList.add(tmpBoard);
}
}
}
public Board copy(Board other) {
Board b = new Board(other);
b.columns = other.columns;
return b;
}
This takes the main board (passed as a parameter), loops through the columns on the board and if the column isn't full it creates a new board object and puts a counter in a empty column, then adds this new board object to a list for later use.
The problem is that when I copy the board, it keeps referencing the main board and modifying that, then each loop it adds a counter to a column without wiping the board clear first.
Expected output is: (Player 1 is human, player 2 is the computer)
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
2 0 0 0 0 0 1
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 2 0 0 0 0 1
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 2 0 0 0 1
And so on until the 7 loops are over.
Actual output:
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 2
2 2 2 2 2 2 1
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 2
2 2 2 2 2 2 1
and so on until the 7 loops are over.
EDIT:
I had problems with the solution below so I decided to try another way, but got the same result and I don't understand why.
I'm basically creating a new Board object, within the constructor i'm assigning new blank columns to it, then looping through the main_board to get the colours of the counters at each slot (Stored as integers in the Slot class), and altering the new Board respectively.
if(!board.columns.get(i).isFull()) {
Board tmpBoard = new Board();
for(int j = 0; j < 7; j++) {
for(int k = 0; k < 7; k++) {
tmpBoard.columns.get(j).slots.get(k).setColour(board.columns.get(j).slots.get(k).getColour());
}
}
}
Board constructor
public Board() {
for(int i = 0; i < 7; i++) {
columns.add(new Column());
}
}
EDIT: Nevermind, above solution worked, just me forgetting to add a new counter after the copy.
The line b.columns = other.columns; causes the problem since you are doing a reference assignment (i.e. its not doing a deep copy as you are expecting). You can copy that array by using System.arraycopy method.
I think in your case you are using an ArrayList to represent columns/rows if so, you can use:
Collections.copy(arrayList2,arrayList1);
or simply
new ArrayList<Integer>(oldList)
in order to create a copy.
Why does Board take another Board as a constructor parameter?
Your problem is that you don't copy the columns, you only do b.columns = other.columns in your copy method. If one of the two boards is changed both boards are affected. Create a new column instances when copying and also deep copy all elements in an column until you reach immutable objects or primitives.

Categories

Resources