📄 puzzlestate.java
字号:
/*
* Created on 9-okt-2004
*
* To change the template for this generated file go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
package logic;
import java.util.ArrayList;
import java.util.List;
/**
* @author gebruiker
*
* To change the template for this generated type comment go to
* Window>Preferences>Java>Code Generation>Code and Comments
*/
public class PuzzleState implements Cloneable {
/* (non-Javadoc)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public static int NMBR_OF_ROWS = 3, NMBR_OF_COLUMNS = 3; //de dimensies van het speelbord
public final static int MOVE_EAST = 0, MOVE_WEST = 1, MOVE_SOUTH = 2, MOVE_NORTH = 3;
private PuzzleState parent = null;
private Object puzzleMatrix[][];
private int emptyRow = -1, emptyColumn = -1;
public PuzzleState()
{
puzzleMatrix = new Object[NMBR_OF_ROWS][NMBR_OF_COLUMNS];
}
/*
* Each puzzle has a parent.
* Get the parent
* */
public PuzzleState getParent()
{
return this.parent;
}
/*
* Each puzzle has a parent.
* Set the parent
* */
private void setParent(PuzzleState parent)
{
this.parent = parent;
}
public int getNumberOfRows()
{
return NMBR_OF_ROWS;
}
public int getNumberOfColumns()
{
return NMBR_OF_COLUMNS;
}
/**
* This method moves a number in the puzzle in the given direction
* @param direction The direction of the move. MOVE_EAST = 0, MOVE_WEST = 1, MOVE_SOUTH = 2, MOVE_NORTH = 3
* @return boolean returns true if it is possible to make the requested move.
*/
public boolean move(int direction)
{
int newEmptyRow = -1, newEmptyColumn = -1;
switch(direction)
{
case MOVE_EAST:
newEmptyRow = emptyRow;
newEmptyColumn = emptyColumn - 1;
break;
case MOVE_WEST:
newEmptyRow = emptyRow;
newEmptyColumn = emptyColumn + 1;
break;
case MOVE_NORTH:
newEmptyRow = emptyRow + 1;
newEmptyColumn = emptyColumn;
break;
case MOVE_SOUTH:
newEmptyRow = emptyRow - 1;
newEmptyColumn = emptyColumn;
break;
default:
return false;
}
if(newEmptyRow >= 0 && newEmptyRow < PuzzleState.NMBR_OF_ROWS && newEmptyColumn >= 0 && newEmptyColumn < PuzzleState.NMBR_OF_COLUMNS)
{
this.puzzleMatrix[emptyRow][emptyColumn] = this.puzzleMatrix[newEmptyRow][newEmptyColumn];
this.puzzleMatrix[newEmptyRow][newEmptyColumn] = null;//the empty part of the puzzle contains 'null'
this.emptyRow = newEmptyRow;
this.emptyColumn = newEmptyColumn;
return true;
}else
{
return false;
}
}
public void setPuzzleNumber(PuzzleNumber puzzleNumber, int row, int column)
{
puzzleMatrix[row][column] = puzzleNumber;
if(puzzleNumber == null)
{
this.emptyRow = row;
this.emptyColumn = column;
}
}
/*
* A successor can be seen as 'a possible move' for the given puzzle state.
* */
public List getSuccessors()
{
List list = new ArrayList();
PuzzleState successor;
//Try a move for each direction (NORTH EAST SOUTH WEST)
for(int i= 0; i < 4; i++)
{
successor = (PuzzleState)this.clone();
//If it conserns a possible move
if(successor.move(i))
{
//Set the successors parent.
successor.setParent(this);
//add it to the successsors list.
list.add(successor);
}
}
return list;
}
/*
* 'Clone' the current puzzle state.
* */
public Object clone()
{
PuzzleState clone = new PuzzleState();
clone.setParent(this.getParent());
clone.puzzleMatrix = new Object[NMBR_OF_ROWS][NMBR_OF_COLUMNS];
for(int i = 0; i < PuzzleState.NMBR_OF_ROWS; i++)
{
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
clone.puzzleMatrix[i][j] = this.puzzleMatrix[i][j];
}
}
clone.emptyColumn = this.emptyColumn;
clone.emptyRow = this.emptyRow;
return clone;
}
/*
* Compare the PuzzleState to another PuzzleState (to see if they are equal)
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public boolean equals(Object o)
{
PuzzleState otherPuzzleState = (PuzzleState)o;
//first we test if in this puzzle the 'empty' cell is located at the same place.
//with this easy check we cover most of the 'equals' requests => enhances performance if equals method is called very often
if(otherPuzzleState.emptyColumn != this.emptyColumn || otherPuzzleState.emptyRow != this.emptyRow)
return false;
//compare the contents of both puzzles
for(int i = 0; i < PuzzleState.NMBR_OF_ROWS; i++)
{
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
PuzzleNumber tegelUitDitSpeelbord = (PuzzleNumber)this.puzzleMatrix[i][j];
PuzzleNumber tegelUitAnderSpeelbord = (PuzzleNumber)otherPuzzleState.puzzleMatrix[i][j];
if(tegelUitAnderSpeelbord != null && tegelUitDitSpeelbord != null)
{
if(tegelUitAnderSpeelbord.equals(tegelUitDitSpeelbord) == false)
return false;
}
}
}
return true;
}
/**
* Shuffle the current puzzle state x number of times
* @param numberOfMoves The number of times a random move is made
* @return a shuffled puzzle state
*/
public PuzzleState shuffle(int numberOfMoves)
{
List successors = this.getSuccessors();
int random = (int)((double)Math.random() * (double)(successors.size()));
PuzzleState newPuzzleState = (PuzzleState)successors.get(random);
numberOfMoves--;
while(numberOfMoves > 0)
{
newPuzzleState = newPuzzleState.shuffle();
numberOfMoves--;
}
newPuzzleState.setParent(null); //the new puzzle may not know it's parent!!!
return newPuzzleState;
}
private PuzzleState shuffle()
{
List successors = this.getSuccessors();
int random = (int)((double)Math.random() * (double)(successors.size()));
return (PuzzleState)successors.get(random);
}
public String toString()
{
StringBuffer buffer = new StringBuffer("");
for(int i = 0; i < PuzzleState.NMBR_OF_ROWS; i++)
{
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
PuzzleNumber tegel = (PuzzleNumber)this.puzzleMatrix[i][j];
if(tegel == null)
buffer.append(" ### ");
else
buffer.append(tegel.toString());
}
buffer.append("\n");
}
return buffer.toString();
}
/*
* Get a HTML representation of the given PuzzleState.
* */
public String getHtml()
{
StringBuffer buffer = new StringBuffer("<html><body><b><table border='1'>");
for(int i = 0; i < PuzzleState.NMBR_OF_ROWS; i++)
{
buffer.append("<tr>");
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
PuzzleNumber tegel = (PuzzleNumber)this.puzzleMatrix[i][j];
if(tegel == null)
buffer.append("<td bgcolor='black'></td>");
else
{
buffer.append("<td bgcolor='#FF3333'><b><font color='white'>");
buffer.append(tegel.toString());
buffer.append("</font></b></td>");
}
}
buffer.append("</tr>");
}
buffer.append("</table></b></body></html>");
return buffer.toString();
}
/*
* Calculate for the current and the other puzzleState how much
* they are different. (for each row and each column).
*
* Make a sum of all these values, which will end up in the 'manhattan distance'
*
*/
public int getManhattanDistance(PuzzleState otherPuzzleState)
{
// by default, check for all rows!
return this.getManhattanDistance(otherPuzzleState, PuzzleState.NMBR_OF_ROWS);
}
public int getManhattanDistance(PuzzleState otherPuzzleState, int maxRowToControl)
{
int intManhattanDistance = 0;
for(int i = 0; i < maxRowToControl; i++)
{
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
PuzzleNumber puzzleNumber = (PuzzleNumber)otherPuzzleState.puzzleMatrix[i][j];
if(puzzleNumber != null)
{
intManhattanDistance += getManhattanDistance(puzzleNumber, i, j);
}
}
}
return intManhattanDistance;
}
/* This method 'helps' the calculation of the manhattan distance
*
* This method gets a PuzzleNumber from another PuzzleState
* It also gets the row and column for which it has to calculate the manhattan distance
*/
private int getManhattanDistance(PuzzleNumber tegelUitAnderBord, int row, int column)
{
for(int i = 0; i < PuzzleState.NMBR_OF_ROWS; i++)
{
for(int j = 0; j < PuzzleState.NMBR_OF_COLUMNS; j++)
{
PuzzleNumber puzzleNumberOfThisPuzzleState = (PuzzleNumber)this.puzzleMatrix[i][j];
if(puzzleNumberOfThisPuzzleState != null)
{
if(puzzleNumberOfThisPuzzleState.equals(tegelUitAnderBord))
return makePositive(row - i) + makePositive(column - j);
}
}
}
return 0;
}
private int makePositive(int aNumber)
{
if(aNumber < 0)
return aNumber * -1;
else
return aNumber;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -