I need to take a 2D array and move everything as far left as possible. It is a 4x4 array and I have tried to do it but either only move certain items or the index goes out of bounds.
The gameBoard array looks like this:
{0 2 4 2}
{0 0 2 0}
{2 2 0 0}
{0 4 0 2}
and after you call the swipeLeft() method it should look like this:
{2 4 2 0}
{2 0 0 0}
{2 2 0 0}
{4 2 0 0}
There is also the issue of placing a zero into the previous index that you moved it from.
I created a double for loop to just loop through the array and tried to code something that would move it over but it hasn't worked.
Here was the code I had so far
public void swipeLeft() {
for ( int r = 0; r < gameBoard.length; r ) {
for ( int c = 0; c < gameBoard[r].length; c ) {
gameBoard[r][c] = gameBoard[r][ (c 1) %
gameBoard.length];
}
}
}
CodePudding user response:
From the example in the question, it appears to me that what is wanted is to shift all non-zero elements to the left, and zero elements are shifted to the right. The order of the non-zero elements is to be retained.
Note that each row is independent of other rows.
One way to approach this is to create a method that works on a 1D array. This method takes a 1D array as a parameter, and returns another 1D array with the elements shifted:
public static int [] zeroShift (int [] arr) {
int [] left = new int [arr.length];
int count = 0;
for (int i = 0; i < arr.length; i ) {
if (arr[i] != 0) {
left [count ] = arr [i];
}
}
return left;
}
This copies each non-zero element to a new array of the same size, keeping track (count
) of how many have been copied so far. Note this relies on left
being initialized to all-zeros.
Once that method is working, it can be used for gameBoard
on a row-by-row basis:
public void swipeLeft() {
for (int r = 0; r < gameBoard.length; r ) {
gameBoard [r] = zeroShift (gameBoard [r]);
}
// output for testing
for (int i = 0; i < gameBoard.length; i) {
System.out.println(Arrays.toString(gameBoard[i]));
}
}
CodePudding user response:
Based on your desired OUTPUT, it looks like swipeLeft()
is supposed to push all non-zero values to the very left of their row, displacing the zeroes to the right of all non-zero values.
If that's correct, this is similar to Old Dog Programmer's approach, except all shifting is done "in place" without creating any new arrays:
import java.util.*;
class Main {
private static int[][] gameBoard;
public static void main(String[] args) {
gameBoard = new int[][] {
{0, 2, 4, 2},
{0, 0, 2, 0},
{2, 2, 0, 0},
{0, 4, 0, 2}
};
System.out.println("Before:");
displayBoard();
swipeLeft();
System.out.println("\nAfter:");
displayBoard();
}
public static void displayBoard() {
for(int[] row : gameBoard) {
System.out.println(Arrays.toString(row));
}
}
public static void swipeLeft() {
for(int[] row : gameBoard) {
// find the first blank (zero) spot
int nextIndex = 0;
while(nextIndex < row.length && row[nextIndex] != 0) {
nextIndex ;
}
// start with the first blank, and shift any non-zero
// values afterwards to the left
for(int col=nextIndex; col < row.length; col ) {
if (row[col] != 0) {
row[nextIndex] = row[col];
row[col] = 0;
nextIndex ;
}
}
}
}
}
Output:
Before:
[0, 2, 4, 2]
[0, 0, 2, 0]
[2, 2, 0, 0]
[0, 4, 0, 2]
After:
[2, 4, 2, 0]
[2, 0, 0, 0]
[2, 2, 0, 0]
[4, 2, 0, 0]
CodePudding user response:
To rotate the array in place, you should roteate the array 3 times:
123456
->654312
654321
3456..
....12
public static void shiftLeft(int[] arr, int offs) {
if (offs <= 0)
return;
offs = arr.length - offs % arr.length - 1;
for (int i = 0, j = arr.length - 1; i < j; i , j--)
swap(arr, i, j);
for (int i = 0, j = offs; i < j; i , j--)
swap(arr, i, j);
for (int i = offs 1, j = arr.length - 1; i < j; i , j--)
swap(arr, i, j);
}
private static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
CodePudding user response:
So your code intends to rotate the board one column to the left. Rotate? Well, the numbers you push out on the left might come back on the end, right?
Probably the line
gameBoard[r][c] = gameBoard[r][ (c 1) % gameBoard.length];
should be
gameBoard[r][c] = gameBoard[r][ (c 1) % gameBoard[r].length];
But try to do this stuff with pen & paper, and you should notice that you are going to loose one column/copy the values from the second column into the first, then copy that into the last column again.
You will need to change two items:
- store the value from the first column somewhere if you still need it so you can push it into the last one.
- only rotate the column data if it needs to be rotated. Or in other words, rotate the remainder of the row if you find a zero. In this case you do not need to remember the first column, as you will overwrite a zero and push a zero into the last column. And then it would not be called rotate but shift.
Exercise this with pen & paper until you can write down instructions for someone else to perform the same operation. Then you are ready to also write it in Java.