libgdx splitting texture with textureregion and trying to shuffle pieces

I’d like to make a shuffle puzzle, but running into some issues:
I have a texture that i split up in 3x3 pieces using textureRegion.
puzzlePieces and puzzlePieces_scrambled are 2D TextureRegion arrays

and what I’m trying to do is shuffle up my original 2d array (puzzlePieces) and call it PuzzlePieces scrambled.
I had no clue how to do this. So I thought let’s just put all the pieces of the original TextureRegion array (puzzlePieces) into an array and use
the Array.shuffle() method to shuffle up the texarray (textureRegion array) and then loop over the texarray to provide the puzzlePieces_Scrambled[][] with the shuffled pieces.

Unfortunatley my puzzlePieces_Scrambled[][] contains pieces that are double and some pieces are not there.
It seems that array.shuffle() is not restricted when putting the content of a location to another place to not use that content again.

If you get what I mean…

How do I solve this?
Or maybe I am using a wrong approach? And/or overcomplicating things?
(and Libgdx (!) code examples for shuffle puzzle would be great too)

Here is my code:

		int arrayIndex = 0;
		puzzleTextures = new Texture("img/portret_JacobCornelisz800x480.jpg");
		tile_width = puzzleTextures.getWidth() / numberOfTiles_hor; // =3
		tile_height = puzzleTextures.getHeight() / numberOfTiles_ver; // =3

                // create a 3x3 textureRegion[][]
		puzzlePieces = TextureRegion.split(puzzleTextures, (int) tile_width,
				(int) tile_height);

		puzzlePieces_scrambled = puzzlePieces;

                // put the textureRegion[][] in an Array (TextureRegion has no shuffle method -> array does....)
		texarray = new Array<TextureRegion>();
		for (int row = 0; row < numberOfTiles_hor; row++) {
			for (int col = 0; col < numberOfTiles_ver; col++) {
				texarray.add(puzzlePieces[row][col]);
			}
		}

                // shuffle Array
		texarray.shuffle();

		//put shuffled array into 2nd TextureRegion for shuffled puzzle pieces
		for (int row = 0; row < numberOfTiles_hor; row++) {
			for (int col = 0; col < numberOfTiles_ver; col++) {
					puzzlePieces_scrambled[row][col].setRegion(texarray
						.get(arrayIndex));
				System.out.println("arrayindex" + arrayIndex);
				arrayIndex++;

			}
		}

// but unfortunately Array.shuffle() doesnt take every object in array just once :(

Don’t use an Array, just use PuzzlePiece[][].

You can easily make up your own cheap shuffle algorithm.

Psuedo:



for (x < 100, x++)
    for(y < 100; y++){
        int x1 = random(0, puzzlePieces.length);
        int y1 = random(0, puzzlePieces[0].length);
        int x2 = random(0, puzzlePieces.length);
        int y2 = random(0, puzzlePieces[0].length);

        PuzzlePiece p1 = puzzlePieces[x1, y1];
        PuzzlePiece p2 = puzzlePieces[x2, y2];

        puzzlePieces[x1][y1] = p2;
        puzzlePieces[x2][y2] = p1;
}

I think this works, but the solution is quite simple.

  • Grab object1 and store it and it’s index
  • Grab object2 and store it and it’s index
  • Put object1 in object2’s index
  • put object2 in object1’s index

Obviously you would want to copy the original array so you can do comparisons, or you could store the index of the puzzle piece within itself and have the objects check if their new position is equal to their original.[/list]

i don’t understand this.
Your code is kind of confusing to me. Is it even taking into account that it’s using every shopped up puzzle/texture piece just one time?
As how I read it in your code p1 & p2 could be stored in the same array position.
And

Are you trolling me Gibbo ^__^?

I don’t see what is really happening there, but I’m not sure it will do what i am looking for.

So i’n my case say i chop my image up into 3x3 = 9 pieces and I (either) store it in a 2D array (or even 1D could do it)

I just want to get the content of the 9 item array shuffled with every content being used exactly 1 time.

Not a troll post, let’s simplify.

Now from what I read, you are simply wanting to shuffle objects around in an array, right? Take texture regions and everything else out of the equation, it does not matter the data type. We simply want to swap values.

Lets start simple:

I am sure you are familiar with the main method but anyway:



public class Main {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new ArrayShuffler();
	}

}


So we now have a new instance of the ArrayShuffler, all the work is done in the constructor (don’t do this :p) so let’s take a look. I have commented it well enough that hopefully you understand:


public class ArrayShuffler {

	// Just create a very basic array with 2 elements, we will swap them about
	PuzzlePiece[] puzzlePieces = new PuzzlePiece[2];

	public ArrayShuffler() {
		// Fill the array with new puzzle pieces and pass their index into them,
		// so we can print out data
		for (int x = 0; x < puzzlePieces.length; x++) {
			puzzlePieces[x] = new PuzzlePiece(x);
		}
		
		/*
		 * So lets make 2 local variables, we grab the first element we want to swap and the second element we want to swap
		 */
		PuzzlePiece p1 = puzzlePieces[0];
		PuzzlePiece p2 = puzzlePieces[1];
	
		/*
		 * Now we basically put p1 into where p2 used to be and vice versa 
		 */
		puzzlePieces[0] = p2;
		puzzlePieces[1] = p1;
		
		/*
		 * Iterate over the array, we grab the first piece in the array and pass in the current element we are checking.
		 * We then go ahead and print the data inside
		 */
		for(int x = 0; x < puzzlePieces.length; x++){
			puzzlePieces[x].setNewIndex(x).print();
		}

	}

}

The output of the process:


I was first at index 1, now I am at index 0
I was first at index 0, now I am at index 1

Here is what the PuzzlePiece class looks like, all it does is append a string and print it:


public class PuzzlePiece {
	
	StringBuilder stringBuilder = new StringBuilder();

	public PuzzlePiece(int index) {
		stringBuilder.append("I was first at index " + String.valueOf(index));
	}
	
	public PuzzlePiece setNewIndex(int newIndex){
		stringBuilder.append(", now I am at index " + String.valueOf(newIndex));
		return this;
	}
	
	public void print(){
		System.out.println(stringBuilder);
	}

}

Now, lets apply this to something a bit more well, random.


	StringBuilder stringBuilder = new StringBuilder();

	public PuzzlePiece(int indexX, int indexY) {
		stringBuilder.append("I was first at index " + String.valueOf(indexX) + ":" + String.valueOf(indexY));
	}
	
	public PuzzlePiece setNewIndex(int newIndexX, int newIndexY){
		stringBuilder.append(", now I am at index " + String.valueOf(newIndexX) + ":" + String.valueOf(newIndexY));
		return this;
	}
	
	public void print(){
		System.out.println(stringBuilder);
	}

}

And for the actual shuffling bit, here it is and hopefully I have commented it enough for you to make use of it.


public class ArrayShuffler {

	// Just create an array with 3*3 elements, we will swap them about
	PuzzlePiece[][] puzzlePieces = new PuzzlePiece[3][3];

	public ArrayShuffler() {
		/*
		 * We are going to create a 2d array of puzzle peices and pass their X
		 * and Y indexes (I usually presume these are coordinates since face it,
		 * 2d arrays are create with tiles and coordinates!
		 */
		for (int x = 0; x < puzzlePieces.length; x++) {
			for (int y = 0; y < puzzlePieces.length; y++) {
				puzzlePieces[x][y] = new PuzzlePiece(x, y);
			}
		}

		/*
		 * So lets make 2 local variables, we grab the first element we want to
		 * swap and the second element we want to swap
		 */
		PuzzlePiece p1;
		PuzzlePiece p2;
		/*
		 * These are the indexes of each puzzle piece, x1 and y1 being the index
		 * of the first element we want to swap, x2 and y2 being the index of
		 * the second element we want to swap
		 */
		int x1;
		int x2;
		int y1;
		int y2;
		int maxShuffles = 50;

		for (int currentShuffles = 0; currentShuffles < maxShuffles; currentShuffles++) {
			/*
			 * Now pick a the indexes at random
			 */
			x1 = MathUtils.random(0, puzzlePieces.length - 1);
			y1 = MathUtils.random(0, puzzlePieces[0].length - 1);
			x2 = MathUtils.random(0, puzzlePieces.length - 1);
			y2 = MathUtils.random(0, puzzlePieces[0].length - 1);

			/*
			 * Now the fun part! Lets simply get a copy of the elements that are
			 * at [x1][y1] and [x2][y2]
			 */
			p1 = puzzlePieces[x1][y1];
			p2 = puzzlePieces[x2][y2];

			/*
			 * Last but not least, the part you have been waiting for. Lets swap
			 * them :D
			 */
			puzzlePieces[x1][y1] = p2;
			puzzlePieces[x2][y2] = p1;
		}

		/*
		 * Now lets check to ensure that all our pieces are at different indexes
		 * from what they started at. We could have done this in the loop above
		 * but I am sure your CPU will cope with the 1 extra loop :p
		 */
		for (int x = 0; x < puzzlePieces.length; x++) {
			for (int y = 0; y < puzzlePieces.length; y++) {
				puzzlePieces[x][y].setNewIndex(x, y).print();
			}
		}

	}

}

And the output:


I was first at index 2:1, now I am at index 0:0
I was first at index 1:1, now I am at index 0:1
I was first at index 0:2, now I am at index 0:2
I was first at index 0:0, now I am at index 1:0
I was first at index 0:1, now I am at index 1:1
I was first at index 1:0, now I am at index 1:2
I was first at index 2:2, now I am at index 2:0
I was first at index 1:2, now I am at index 2:1
I was first at index 2:0, now I am at index 2:2

JGO Wizard +1

Now I understand. Thanks a lot for the help!