package de.christianix.puzzle.client;
import java.util.Arrays;
import com.google.gwt.user.client.Random;
public class PuzzleBoard {
private int board[] = null;
private int rowSize = 0;
private int emptyPos = 0;
/**
* Construct puzzle board.
*
* @param ydim y dimension
* @param xdim x dimension
*/
public PuzzleBoard( int ydim, int xdim ) {
rowSize = xdim;
board = new int[ydim * xdim];
init();
}
/**
* Initialize with permutation.
* The Fisher–Yates shuffle is used to generate the permutations.
*/
public void init() {
board[0] = 0;
int pc = 0;
do {
for ( int i = 1; i < board.length-1; ++i ) {
int j = Random.nextInt(i+1);
board[i] = board[j];
board[j] = i;
}
/* Check if puzzle is solvable */
pc = permutationCount();
if ( (pc % 2) != 0 ) {
switchTiles(0, 1);
}
} while ( pc == 0 );
emptyPos = board.length-1;
board[emptyPos] = -1;
}
/**
* Get index of tile at give position.
*
* @param y coordinate
* @param x coordinate
* @return tile index
*/
public int getTileIndex( int y, int x ) {
int i = (y * rowSize) + x;
return board[i];
}
/**
* Get x coordinate of empty tile.
*
* @return x coordinate
*/
public int getEmptyX() {
return (emptyPos % rowSize);
}
/**
* Get y coordinate of empty tile.
*
* @return y coordinate
*/
public int getEmptyY() {
return (emptyPos / rowSize);
}
/**
* Count permutations of board.
* Two tiles x and y are permuted if x < y but index(x) > index(y).
*
* @return number of permutations
*/
public int permutationCount() {
int cnt = 0;
for ( int i = 0; i < (board.length - 1); ++i ) {
for ( int j = i + 1; j < board.length; ++j ) {
if ( (board[i] > board[j]) && (board[j] != -1) ) ++cnt;
}
}
return cnt;
}
/**
* Move tile if allowed.
* Movement of a tile is only allowed if the empty tile is in the
* neighborhood.
*
* @param x coordinate
* @param y coordinate
* @return true if move was allowed, false otherwise
*/
public boolean moveTile( int x, int y ) {
int i = (y * rowSize) + x;
/* Check if movable */
if ( (i+1 == emptyPos) ||
(i-1 == emptyPos) ||
(i+rowSize == emptyPos) ||
(i-rowSize == emptyPos) )
{
board[emptyPos] = board[i];
emptyPos = i;
board[emptyPos] = -1;
return true;
}
return false;
}
/**
* Debug method
*/
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append( Arrays.toString(board) ).append( "\n" );
return builder.toString();
}
/**
* Switch tiles.
* Uses arithmetics only.
*
* @param i first index
* @param j second index
*/
protected void switchTiles( int i, int j ) {
board[j] += board[i];
board[i] = board[j] - board[i];
board[j] -= board[i];
}
}