PuzzleRouteFinder.getDirections returns proper order of steps.
This commit is contained in:
@@ -36,7 +36,7 @@ public class PuzzleAnimator implements IPuzzleAnimator {
|
||||
//animator.queue( new Animator.NoMove(x,y) );
|
||||
}
|
||||
|
||||
public void undoable(XYPair xy )
|
||||
public void moveImpossible(XYPair xy )
|
||||
{
|
||||
animator.queue( new Animator.NoMove(xy) );
|
||||
}
|
||||
|
||||
@@ -6,5 +6,5 @@ public interface IPuzzleAnimator {
|
||||
public void select( XYPair xy );
|
||||
public void unselect();
|
||||
public void buzz();
|
||||
public void undoable( XYPair xy );
|
||||
public void moveImpossible(XYPair xy );
|
||||
}
|
||||
|
||||
@@ -7,18 +7,14 @@ package org.vostan.banvor.model;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.vostan.banvor.model.IPuzzleAnimator;
|
||||
import org.vostan.banvor.model.Puzzle;
|
||||
import org.vostan.banvor.model.PuzzleRouteFinder;
|
||||
import org.vostan.banvor.model.XYPair;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class PuzzleChoreographer
|
||||
{
|
||||
protected Puzzle puzzle = null;
|
||||
protected PuzzleRouteFinder routeFinder;
|
||||
private Puzzle puzzle = null;
|
||||
private PuzzleRouteFinder routeFinder = null;
|
||||
private IPuzzleAnimator animator;
|
||||
|
||||
public PuzzleChoreographer()
|
||||
{}
|
||||
@@ -29,8 +25,9 @@ public class PuzzleChoreographer
|
||||
routeFinder = new PuzzleRouteFinder(p);
|
||||
}
|
||||
|
||||
public boolean createSteps(IPuzzleAnimator animator, XYPair xy )
|
||||
public boolean createSteps(IPuzzleAnimator _animator, XYPair xy )
|
||||
{
|
||||
animator = _animator;
|
||||
//
|
||||
// Check that the x,y are valid.
|
||||
//
|
||||
@@ -51,19 +48,18 @@ public class PuzzleChoreographer
|
||||
// Check if worker selected a box and can push it to the location?
|
||||
// If yes then we are done.
|
||||
//
|
||||
if ( puzzle.isSelected()
|
||||
&& tryMoveBox(animator, xy) )
|
||||
if ( puzzle.isSelected() && tryMoveSelectedBox(xy) )
|
||||
return true;
|
||||
//
|
||||
// Either nothing was selected or the box cannot be moved to
|
||||
// tapped location. Try move worker alone.
|
||||
//
|
||||
if ( tryMoveWorker( animator, xy ) )
|
||||
if ( tryMoveWorker(xy) )
|
||||
return true;
|
||||
//
|
||||
// Show that action is not allowed.
|
||||
//
|
||||
animator.undoable(xy);
|
||||
animator.moveImpossible(xy);
|
||||
}
|
||||
//
|
||||
// The tapped is the worker. Try move the box. If not possible
|
||||
@@ -84,8 +80,9 @@ public class PuzzleChoreographer
|
||||
// Check if worker selected a box and can push it to the location?
|
||||
// If yes then we are done.
|
||||
//
|
||||
if ( tryMoveBox(animator, xy) )
|
||||
if ( tryMoveSelectedBox(xy) ) {
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// If the box is not movable then unselect it.
|
||||
//
|
||||
@@ -112,12 +109,13 @@ public class PuzzleChoreographer
|
||||
// Try move the worker next to the box and select it if the
|
||||
// box is not selected yet.
|
||||
//
|
||||
if ( trySelectBox( animator, xy ) )
|
||||
if ( trySelectBox(xy) ) {
|
||||
return true;
|
||||
}
|
||||
//
|
||||
// Show that action is not allowed if reached till here.
|
||||
//
|
||||
animator.undoable(xy);
|
||||
animator.moveImpossible(xy);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -126,25 +124,27 @@ public class PuzzleChoreographer
|
||||
//
|
||||
// Routes to accessible cells from where worker stands.
|
||||
//
|
||||
protected boolean tryMoveWorker( IPuzzleAnimator animator, XYPair xy )
|
||||
protected boolean tryMoveWorker(XYPair xy)
|
||||
{
|
||||
//
|
||||
// If the filed is not accessable then move failed.
|
||||
//
|
||||
if ( !routeFinder.isAccessible(xy) )
|
||||
if ( !routeFinder.isAccessible(xy) ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// First unselect box.
|
||||
//
|
||||
if ( puzzle.isSelected() )
|
||||
if ( puzzle.isSelected() ) {
|
||||
animator.unselect();
|
||||
}
|
||||
//
|
||||
// Get directions and queue moves accordingly.
|
||||
//
|
||||
Vector<XYPair> dirs = routeFinder.getDirections(xy);
|
||||
ListIterator<XYPair> it = dirs.listIterator(dirs.size());
|
||||
while ( it.hasPrevious() ) {
|
||||
animator.move(it.previous());
|
||||
ListIterator<XYPair> it = dirs.listIterator();
|
||||
while ( it.hasNext() ) {
|
||||
animator.move(it.next());
|
||||
}
|
||||
//
|
||||
// Done.
|
||||
@@ -152,26 +152,57 @@ public class PuzzleChoreographer
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean tryMoveBox( IPuzzleAnimator animator, XYPair xy )
|
||||
|
||||
protected boolean tryMoveSelectedBox(XYPair xy)
|
||||
{
|
||||
//
|
||||
// If no box is selected then we cannot move no box.
|
||||
//
|
||||
if ( !puzzle.isSelected() )
|
||||
if ( !puzzle.isSelected() ) {
|
||||
return false;
|
||||
}
|
||||
final XYPair box_xy = puzzle.getSelected();
|
||||
//
|
||||
// There is no point to continue if we are asked to move the box to where is it.
|
||||
//
|
||||
if ( xy.isEqual(box_xy) ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Check that asked move is orthogonal to the slected box.
|
||||
//
|
||||
// TODO: check that all cells are empty on the route.
|
||||
//
|
||||
if ( xy.x() == box_xy.x() || xy.y() == box_xy.y() ) {
|
||||
return tryOrthogonalMoveSelectedBox(xy);
|
||||
}
|
||||
//
|
||||
// NOT IMPLEMENTED.
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean tryOrthogonalMoveSelectedBox(XYPair xy)
|
||||
{
|
||||
//
|
||||
// If no box is selected then we cannot move no box.
|
||||
//
|
||||
if ( !puzzle.isSelected() ) {
|
||||
return false;
|
||||
}
|
||||
final XYPair box_xy = puzzle.getSelected();
|
||||
XYPair dxy = xy.sub(box_xy);
|
||||
if ( dxy.x() != 0 && dxy.y() != 0 )
|
||||
return false;
|
||||
//
|
||||
// There is no point to continue also in case if the asked cell
|
||||
// is the box.
|
||||
// There is no point to continue if we are asked to move the box to where is it.
|
||||
//
|
||||
if ( dxy.isEqual(XYPair.ZERO) )
|
||||
if ( xy.isEqual(box_xy) ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Check that asked move is orthogonal to the selected box.
|
||||
//
|
||||
if ( xy.x() != box_xy.x() && xy.y() != box_xy.y() ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Now find the desired place for the worker to start push this
|
||||
// box.
|
||||
@@ -189,8 +220,9 @@ public class PuzzleChoreographer
|
||||
// Check if the desired place for the worker is accessable? If not
|
||||
// then there is no point to continue.
|
||||
//
|
||||
if ( !routeFinder.isAccessible(w) )
|
||||
if ( !routeFinder.isAccessible(w) ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Now check that all cell till x,y are empty and that we can
|
||||
// push box till there.
|
||||
@@ -210,7 +242,9 @@ public class PuzzleChoreographer
|
||||
//
|
||||
if ( !w.isEqual(puzzle.getWorker()) )
|
||||
{
|
||||
tryMoveWorker( animator, w );
|
||||
if (!tryMoveWorker(w)){
|
||||
return false;
|
||||
}
|
||||
animator.select(box_xy);
|
||||
}
|
||||
//
|
||||
@@ -225,16 +259,17 @@ public class PuzzleChoreographer
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean trySelectBox( IPuzzleAnimator animator, XYPair xy )
|
||||
|
||||
protected boolean trySelectBox(XYPair xy)
|
||||
{
|
||||
int north = puzzle.getSym(xy.up());
|
||||
int south = puzzle.getSym(xy.down());
|
||||
int west = puzzle.getSym(xy.left());
|
||||
int east = puzzle.getSym(xy.right());
|
||||
//
|
||||
// First check if there is a worker in a nighbour cell. If
|
||||
// yes then simplly select the box. If the box is already selected
|
||||
// then do nothing and if othe box is selected then unselect it first
|
||||
// First check if there is a worker in a neighboring cell. If
|
||||
// yes then simply select the box. If the box is already selected
|
||||
// then do nothing and if other box is selected then unselect it first
|
||||
// and then select the box.
|
||||
//
|
||||
if ( Puzzle.hasWorker( west )
|
||||
@@ -250,7 +285,7 @@ public class PuzzleChoreographer
|
||||
}
|
||||
}
|
||||
//
|
||||
// Otherwise, check which is of the cells is in closes walking
|
||||
// Otherwise, check which of the cells is in closes walking
|
||||
// distance and move worker to that cell, then select.
|
||||
//
|
||||
else
|
||||
@@ -285,9 +320,9 @@ public class PuzzleChoreographer
|
||||
// Move the worker to the direction. If we cannot move worker
|
||||
// next to the box then we cannot select it.
|
||||
//
|
||||
if ( !puzzle.isValid(pref)
|
||||
|| !tryMoveWorker(animator, pref) )
|
||||
if ( !puzzle.isValid(pref) || !tryMoveWorker(pref) ) {
|
||||
return false;
|
||||
}
|
||||
//
|
||||
// Select the box.
|
||||
//
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package org.vostan.banvor.model;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Vector;
|
||||
|
||||
public class PuzzleRouteFinder {
|
||||
protected Puzzle puzzle = null;
|
||||
protected int [] moves;
|
||||
protected Vector<XYPair> setOfCells = new Vector<XYPair>();
|
||||
|
||||
//
|
||||
// This is to avoid fragmentation of memory.
|
||||
//
|
||||
private Vector<XYPair> setOfCells = new Vector<XYPair>();
|
||||
|
||||
public PuzzleRouteFinder(Puzzle p) {
|
||||
puzzle = p;
|
||||
@@ -14,8 +19,7 @@ public class PuzzleRouteFinder {
|
||||
setOfCells.ensureCapacity(puzzle.getColumnCount() * puzzle.getRowCount());
|
||||
}
|
||||
|
||||
protected final int getMoves( XYPair xy )
|
||||
{
|
||||
protected final int getMoves( XYPair xy ) {
|
||||
return moves[puzzle.getIndex(xy)];
|
||||
}
|
||||
protected void setMoves( XYPair xy, int v )
|
||||
@@ -93,8 +97,7 @@ public class PuzzleRouteFinder {
|
||||
return getMoves(xy);
|
||||
}
|
||||
|
||||
public final boolean isAccessible( XYPair xy )
|
||||
{
|
||||
public final boolean isAccessible( XYPair xy ) {
|
||||
return puzzle.isValid(xy) && stepsAway(xy) != Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
@@ -126,6 +129,7 @@ public class PuzzleRouteFinder {
|
||||
steps.add(xy.up());
|
||||
}
|
||||
}
|
||||
Collections.reverse(steps);
|
||||
return steps;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,11 +27,11 @@ public class XYPair
|
||||
_y = op.y();
|
||||
}
|
||||
|
||||
public int x(){
|
||||
public final int x(){
|
||||
return _x;
|
||||
}
|
||||
|
||||
public int y(){
|
||||
public final int y(){
|
||||
return _y;
|
||||
}
|
||||
|
||||
@@ -57,44 +57,44 @@ public class XYPair
|
||||
return new XYPair(op1._x*scaliar, op1._y*scaliar);
|
||||
}
|
||||
|
||||
public XYPair mul(int scaliar){
|
||||
public final XYPair mul(int scaliar){
|
||||
return mul(this, scaliar);
|
||||
}
|
||||
|
||||
public XYPair sub(XYPair op){
|
||||
public final XYPair sub(XYPair op){
|
||||
return sub(this, op);
|
||||
}
|
||||
|
||||
public XYPair add(XYPair op){
|
||||
public final XYPair add(XYPair op){
|
||||
return add(this, op);
|
||||
}
|
||||
|
||||
public int l1_norm(){
|
||||
public final int l1_norm(){
|
||||
return abs(_x)+abs(_y);
|
||||
}
|
||||
|
||||
public boolean isEqual(XYPair op){
|
||||
public final boolean isEqual(XYPair op){
|
||||
return _x == op._x && _y == op._y;
|
||||
}
|
||||
|
||||
public boolean isInside(XYPair op1, XYPair op2){
|
||||
public final boolean isInside(XYPair op1, XYPair op2){
|
||||
return op1.x() <= this.x() && this.x() < op2.x()
|
||||
&& op1.y() <= this.y() && this.y() < op2.y();
|
||||
}
|
||||
|
||||
public XYPair left(){
|
||||
public final XYPair left(){
|
||||
return this.add(LEFT);
|
||||
}
|
||||
|
||||
public XYPair right(){
|
||||
public final XYPair right(){
|
||||
return this.add(RIGHT);
|
||||
}
|
||||
|
||||
public XYPair up(){
|
||||
public final XYPair up(){
|
||||
return this.add(UP);
|
||||
}
|
||||
|
||||
public XYPair down(){
|
||||
public final XYPair down(){
|
||||
return this.add(DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user