I'm trying to draw an array, but I don't know the proper way of performing that.
Here's my array.
int[][] map=
{
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1}
};
I know I'm missing alot, and I can't seem to find any answers that are understandable to a beginner coder.
int[][] map=
{
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1}
};
int rows = 5;
int cols = 5;
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
System.out.print(map[i][j] + " ");
}
System.out.println("");
}
Using a GridPane:
public static void printImage(idPicture, path){
image = new Image(path);
this.idPicture = idPicture; //in your case 0 or 1
for(int i = 0; i < width; i++){
for (int j = 0; j< height; j++){
if(map[i][j] == idPicture){ //check the current id
imageViewMatrix[i][j] = new ImageView(image); //load the image in the matrix
imageViewMatrix[i][j].setPreserveRatio(true);
imageViewMatrix[i][j].setFitWidth(imageWidth);
pane.add(imageViewMatrix[i][j], i, j); //add image to the pane
}
}
}
}
This is the easiest way for me. But you have to repeat this process for each image you want to print, setting the ID and the path.
If you just want to print them in the console then you can try loops. However you can use some magic of Java 8 too.
public static void main(String[] args) {
System.out.println("Started");
int[][] map=
{
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1},
{0,0,1,0,0},
{1,1,1,1,1}
};
Arrays.asList(map).stream().forEach((a) -> System.out.println(Arrays.toString(a)));
System.out.println("");
Arrays.asList(map).stream().forEach((a) -> {
String b = Arrays.toString(a);
System.out.println(b.substring(1, b.length() - 1));
});
System.out.println("");
Arrays.asList(map).stream().forEach((a) -> {
String b = Arrays.toString(a);
System.out.println(b.substring(1, b.length() - 1).replaceAll(",", " "));
});
}
Output
Started
[1, 1, 1, 1, 1]
[0, 0, 1, 0, 0]
[1, 1, 1, 1, 1]
[0, 0, 1, 0, 0]
[1, 1, 1, 1, 1]
1, 1, 1, 1, 1
0, 0, 1, 0, 0
1, 1, 1, 1, 1
0, 0, 1, 0, 0
1, 1, 1, 1, 1
1 1 1 1 1
0 0 1 0 0
1 1 1 1 1
0 0 1 0 0
1 1 1 1 1
Related
I am making a snake game where the snake crosses through a 2D int array as its terrain. The values stored in the 2D array represent the time in seconds it takes to cross.
For example,
int[][] MAP = {
{ 1, 1, 1, 2, 2 },
{ 1, 2, 2, 2, 2 },
{ 3, 2, 2, 3, 1 },
{ 1, 1, 3, 2, 1 },
{ 1, 1, 3, 2, 1 }
};
So going from map[0][0] to map[0][4] takes 1 + 1 + 2 + 2 seconds. How would I make an algorithm that would find the shortest possible path for a snake to travel from position map[startX][startY] to map[endX][endY]?
This isn't a homework assignment, I'm just making a game for fun and would like to learn how to do this.
This is one is kinda known problem when discussing "dynamic programming", and even resembles an old post.
Still, I didn't find a solution that also prints the shortest path, so:
public class FastestPathCalculator {
private final int[][] map;
public FastestPathCalculator(int[][] map) {
this.map=map;
}
public static void main(String[] args) {
int[][] map = new int[][]{
{1, 1, 1, 4, 2},
{1, 2, 5, 2, 2},
{3, 2, 2, 3, 1},
{1, 1, 3, 2, 1},
{3, 1, 3, 2, 1}
};
FastestPathCalculator c = new FastestPathCalculator(map);
boolean[] result = c.computeFastestPath(map);
c.printPath(result);
}
Here, the boolean array represents the steps taken from (0,0) to (4,4). A value of TRUE means the step is to the right, FALSE means go down.
In this example, the array has 8 cells.
public boolean[] computeFastestPath(int[][] map) {
int pathLength = map.length + map[0].length - 2;
boolean[] result = new boolean[pathLength];
int[][] mapOfMinimalSums = buildMapOfMinimalSums();
int x = map.length-1;
int y = map[0].length-1;
for (int i = pathLength - 1 ; i >= 0; i--) {
if (x == 0)
result[i] = true;
else if (y == 0)
result[i] = false;
else if (mapOfMinimalSums[x][y] == map[x][y] + mapOfMinimalSums[x][y-1]) {
result[i] = true;
y--;
}
else {
result[i] = false;
x--;
}
}
return result;
}
public void printPath(boolean[] result) {
String[][] newPath = new String[map.length][map[0].length];
int x = 0;
int y = 0;
newPath[x][y] = String.valueOf(map[x][y]);
for (int i = 0 ; i < result.length; i++) {
if (result[i]) {
y++;
} else {
x++;
}
newPath[x][y] = String.valueOf(map[x][y]);
}
for (int i = 0 ; i < map.length; i++) {
for (int j = 0 ; j < map[0].length; j++) {
if (newPath[i][j] == null) {
System.out.print(" , ");
} else {
System.out.print(newPath[i][j] + ", ");
}
}
System.out.println();
}
System.out.println();
}
private int[][] buildMapOfMinimalSums() {
int[][] mapOfSums = new int[map.length][map[0].length];
for (int i = 0 ; i < map.length; i++) {
for (int j = 0 ; j < map[0].length; j++) {
if (i == 0 && j == 0)
mapOfSums[i][j] = map[i][j];
else if (i == 0) {
mapOfSums[i][j] = mapOfSums[i][j - 1] + map[i][j];
}
else if (j == 0)
mapOfSums[i][j] = mapOfSums[i-1][j] + map[i][j];
else
mapOfSums[i][j] = Math.min(mapOfSums[i-1][j], mapOfSums[i][j-1]) + map[i][j];
}
}
return mapOfSums;
}
}
I'm making a Sudoku solver which tries every possible value in a square and backtracks if it doesn't lead to a solution. I believe I have a nearly-working algorithm, but it only has worked so far on rows 0, 2, and 3 of a 16-cell puzzle.
public boolean fillBoard(int[][] board, int row, int col){
int index = 1; //Next value to try when an empty is found
boolean solved = false;
for(int i = row; i < width; i++){ //For each row
for(int j = col; j < height; j++){ //For each column
if(board[i][j]==0){ //0 represents empty
while(!solved){
board[i][j] = index;
if(checker.checkRow(board[i])
&& checker.checkColumn(columnToArray(board, j))
//&& checker.checkBox(<input>)
){
solved = fillBoard(board, i, 0);
}else{
if(index < width){
index++;
}else{
return false;
}
}
}
}
}
}
puzzle = copyPuzzle(board);
return true;
}
Right now it doesn't check for the third Sudoku rule, it only checks for columns and rows. However, it should still return a puzzle that follows the row and column rules, right? And once the checkBox method is written, it should just be able to solve the puzzle. Where did I mess up here?
EDIT with a few examples:
For an input of
{1, 2, 0, 0},
{0, 4, 0, 0},
{0, 0, 1, 0},
{0, 0, 3, 2}
The program returns
1 2 4 3
4 4 4 4
2 3 1 4
4 1 3 2
For an input of
{1, 0},
{2, 0}
It solves it correctly.
For an input of
{ 1, 0, 3, 4, 0, 0 },
{ 4, 0, 6, 0, 0, 3 },
{ 2, 0, 1, 0, 6, 0 },
{ 5, 0, 4, 2, 0, 0 },
{ 3, 0, 2, 0, 4, 0 },
{ 6, 0, 5, 0, 0, 2 }
It returns the puzzle unsolved
EDIT: checkRow for those who have asked
public boolean checkRow(int[]row){
HashSet<Integer> set = new HashSet<Integer>();
for(int i = 0; i < row.length;i++){
if(!set.add(row[i]) && row[i]>0){//Duplicate?
return false;
}
}
return true;
}
The issue was that it didn't reset the space to 0 when the value was incorrect, so if it ever reached the max index and wasn't correct, it just left it. The below code works. Just waiting on another person in my group to deliver the box-checking method, but I will probably end up having to do that myself.
public boolean fillBoard(int[][] board, int row, int col){
int index = 1; //Next value to try when an empty is found
boolean solved = false;
for(int i = row; i < width; i++){ //For each row
for(int j = col; j < height; j++){ //For each column
if(board[i][j]==0){ //0 represents empty
while(!solved){ //While the puzzle is unsolved
board[i][j] = index; //Try to fill with index
if(checker.checkRow(board[i])
&& checker.checkColumn(columnToArray(board, j))
//&& checker.checkBox(<input>)
){
solved = fillBoard(board, i, 0); //Next space
}
if(!solved) board[i][j] = 0;
if(index < width){
index++;
}else{
return false;
}
}
}
}
}
puzzle = copyPuzzle(board);
return true;
}
Currently I'm working on a program that generates random 0's and 1's in a 8x8 2D array board. What I have to do is check whether or not if all the numbers on the diagonal are the same (starting from the corners, not just any diagonals).
example:
int[][] array = {
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 1, 0}
};
So if by chance all the numbers starting from the top left corner (0,0),(1,1)...(7,7) are all either 0's or 1's then I have to output to the scanner indicating that "There is a major diagonal of 0" (from the example above).
Also from this example, we can see that from the top-right, the number "1" is repeated diagonally towards the bottom left, then I also have to display "There is a minor diagonal of 1".
So far I have figured out how to generate and input the numbers into the array, but I don't know how to check. This is what I have so far:
public class JavaTest{
// Main method
public static void main(String[] args) {
int[][] array = {
{0, 0, 0, 0, 0, 0, 0, 1},
{0, 0, 1, 0, 1, 0, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 0, 0, 1, 1, 1, 0},
{0, 0, 1, 1, 0, 1, 1, 0},
{0, 0, 1, 0, 0, 0, 1, 0},
{0, 1, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 1, 1, 1, 1, 0}
};
// Print array numbers
for (int i = 0; i < array.length; i++) {
for (int j = 0; j < array[i].length; j++)
System.out.print(array[i][j] + " ");
System.out.println();
}
// Print checkers
checkMajorDiagonal(array);
}
// Check major diagonal
public static void checkMajorDiagonal(int array[][]) {
int majDiag;
boolean isMatching = true;
int row = 0;
for(row = 0; row < array.length; row++){
majDiag = row;
if(array[row][row] != array[row+1][row+1]){
isMatching = false;
break;
}
}
//If all elements matched print output
if(isMatching)
System.out.println("Major diagonal is all " + array[row][row]);
}
}
Though what I have so far is not working as I want it to be as there is an error, and I still have to do the minor diagonal. Thanks in advance.
There are a bunch of answers already. Here is one more way to do it. You are on the right track, but there is no need to complicate things by checking a diagonal element with the next element and so on. Just check each diagonal element with the first diagonal element. The moment you find a difference, you stop checking!
public static void checkDiagonal(int[][] array){
// Start with the assumption that both diagonals are consistent.
boolean majorConsistent = true;
boolean minorConsistent = true;
int length = array.length;
int tempMajor = array[0][0]; // all elements in the Major must be equal to this
int tempMinor = array[0][length-1]; // all elements in the Minor must be equal to this
// Check major diagonal, and update the boolean if our assumption is wrong.
for(int i=0; i<length; i++){
if (array[i][i] != tempMajor) { //(0,0);(1,1);(3,3);...
majorConsistent = false;
break;
}
}
// Check minor diagonal, and update the boolean if our assumption is wrong.
for(int i=0,j=length-1; i<length; i++,j--){
if (array[i][j] != tempMinor) { //(0,7);(1,6);(2,5);...
minorConsistent = false;
break;
}
}
System.out.println("Major elements all same = "+majorConsistent);
System.out.println("Minor elements all same = "+minorConsistent);
}
This way you are still doing both the checks in O(n) and you don't need nested for loops! Note that you can refine this code to remove redundancy i.e. have a single for loop, etc.
If you are using Java 8 then you could potentially do this with streams rather than iterating through the values manually. That might be a more direct approach than checking against previous values.
if (IntStream.range(0, size).map(n -> array[n][n]).allMatch(n -> n == 0)) {
}
if (IntStream.range(0, size).map(n -> array[n][size-n-1]).allMatch(n -> n == 1)) {
}
The error probably comes from the fact that you loop while row < array.length but you index into array[row+1]. This will result in an out of bounds exception.
For checking the minor diagonal, try something similar:
int maxIndex = array.length - 1;
for(row = 0; row < maxIndex; row++){
majDiag = row;
if(array[row][maxIndex - row] != array[row+1][maxIndex - (row+1)]){
isMatching = false;
break;
}
}
Some points about your method checkMajorDiagonal :
int majDiag;
boolean isMatching = true;
int row = 0;
for(row = 0; row < array.length; row++){
majDiag = row; //not being used anywhere
if(array[row][row] != array[row+1][row+1]){ //out of bounds with row+1
isMatching = false;
break;
}
}
You can remove the unused majDiag variable and change the loop code as
for(row = 0; row < array.length-1; row++)
Minor diagonal logic :
for(row = 0; row < array.length; row++){
for(col = 0; col < array[i].length; col++){
if(row+col==array[i].length){
array[row][col] // this would be your minor diagonal element row wise
}
}
int diagonalValue = 0;
for(int i = 0; i < 8 ; i++){
diagonalValue = array[i][j];
for(int j = 0; j < 8 ; j++)
if(i==j){
if(array[i][j]==diagonalValue){
counter++;
}
else
break;
}
}
}
if(counter==8) // yes they are same else not
keep size of array i.e. 9 in a variable to make it loosely coupled.
I am trying to remove an int from an ArrayList containing [9, 0, 0, 6, 2, 3, 0, 0, 0] using the following code
static void appendRow(ArrayList<ArrayList<Integer>> ans) {
int ind = 0;
while(yolo.size() < 81) {
for(int x = 0; x < ans.size(); x++) {
ArrayList<Integer> an = ans.get(x);
for(int i = ind; i < ind+3; i++) {
yolo.add(an.get(i));
}
for(int y = 0; y < 3; y++) {
an.remove(y);
}
}
ind+=3;
}
System.out.println(yolo);
}
What happened here is that after I add the first 3 ints from ans, I will delete them. There are more than one items that will be passed into the appendRow function but I only need the first three and the next function only needs the rest (i.e. [6, 2, 3, 0, 0, 0]).
The problem is that when y = 2, an.remove(y) does not remove the 0 with index of 2, instead it removes 2 so the list becomes [0, 6, 3, 0, 0, 0], which is totally wrong.
Reverse the direction of your for loop. Change
for (int y = 0; y < 3; y++) {
an.remove(y);
}
to something like
for (int y = 2; y >= 0; y--) {
an.remove(y);
}
or something like
for (int y = 0; y < 3; y++) {
an.remove(0);
}
because when your remove the first element the second element is now what was the third. That is 9, 0, 0, 6, 2, 3, 0, 0, 0 becomes 0, 0, 6, 2, 3, 0, 0, 0 then 0, 6, 2, 3, 0, 0, 0 and then your reported 0, 6, 3, 0, 0, 0 (which is exactly what you told it to do).
I keep getting an out of bounds error whenever i try to run my code. Does anyone know what is wrong with it? I can't seem to figure it out.
public class Swapper{
/**
This method swaps the first and second half of the given array.
#param values an array
*/
public void swapFirstAndSecondHalf(int[] values) {
// your work here
int[] first = new int[values.length/2];
int[] second = new int[values.length/2];
for(int i = 0; i < values.length / 2; i++) {
second[i] = values[i];
}
for (int j = values.length / 2; j < values.length; j++) {
first[j] = values[j];
}
for(int k = 0; k < values.length / 2; k++) {
values[k] = first[k];
}
for(int l = values.length / 2; l < values.length; l++) {
values[l] = second[l];
}
}
// This method is used to check your work
public int[] check(int[] values) {
swapFirstAndSecondHalf(values);
return values;
}
}
int[] first = new int[values.length/2];
So indexes [0..values.length/2 - 1] are valid for first.
for (int j=values.length/2; j<values.length; j++)
{
first[j] = values[j];
}
So with the first value of j being values.length/2, it's already out of bounds.
You need to practice debugging, placing a break point and tracing the code as it executes.
You could have used System.arraycopy() instead of all the for looping.
public static void main(String[] args) throws Exception {
int[] values = {1, 2, 3, 4, 5};
values = swapFirstAndSecondHalf(values);
System.out.println(Arrays.toString(values));
values = new int[]{1, 2, 3, 4, 5, 6};
values = swapFirstAndSecondHalf(values);
System.out.println(Arrays.toString(values));
}
public static int[] swapFirstAndSecondHalf(int[] values) {
boolean evenSize = values.length % 2 == 0;
int half = values.length / 2;
int[] swapper = new int[values.length];
System.arraycopy(values, evenSize ? half : half + 1, swapper, 0, half);
System.arraycopy(values, 0, swapper, evenSize ? half : half + 1, half);
// The middle number stays the middle number
if (!evenSize) {
swapper[half] = values[half];
}
return swapper;
}
Results:
[4, 5, 3, 1, 2]
[4, 5, 6, 1, 2, 3]
If you're wanting the middle number, for an odd sized array, to be part of the second half then the swapFirstAndSecondHalf() would look like this:
public static int[] swapFirstAndSecondHalf(int[] values) {
boolean evenSize = values.length % 2 == 0;
int half = values.length / 2;
int[] swapper = new int[values.length];
System.arraycopy(values, half, swapper, 0, evenSize ? half : half + 1);
System.arraycopy(values, 0, swapper, evenSize ? half : half + 1, half);
return swapper;
}
Results:
[4, 5, 3, 1, 2]
[4, 5, 6, 1, 2, 3]
Allocating new arrays is a waste of space. Just swap the halves in-place:
public static void swapFirstAndSecondHalf(int[] values) {
final int len = values.length / 2;
final int offset = values.length - len;
for (int i = 0; i < len; i++) {
int temp = values[i];
values[i] = values[offset + i];
values[offset + i] = temp;
}
}
The code allows odd length, and will leave center value alone.