PuzzleRouteFinder.getDirections returns proper order of steps.

This commit is contained in:
2021-10-17 23:04:24 +01:00
parent faa6ccc296
commit 66d04087f8
5 changed files with 97 additions and 58 deletions

View File

@@ -36,7 +36,7 @@ public class PuzzleAnimator implements IPuzzleAnimator {
//animator.queue( new Animator.NoMove(x,y) ); //animator.queue( new Animator.NoMove(x,y) );
} }
public void undoable(XYPair xy ) public void moveImpossible(XYPair xy )
{ {
animator.queue( new Animator.NoMove(xy) ); animator.queue( new Animator.NoMove(xy) );
} }

View File

@@ -6,5 +6,5 @@ public interface IPuzzleAnimator {
public void select( XYPair xy ); public void select( XYPair xy );
public void unselect(); public void unselect();
public void buzz(); public void buzz();
public void undoable( XYPair xy ); public void moveImpossible(XYPair xy );
} }

View File

@@ -7,18 +7,14 @@ package org.vostan.banvor.model;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.Vector; 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 public class PuzzleChoreographer
{ {
protected Puzzle puzzle = null; private Puzzle puzzle = null;
protected PuzzleRouteFinder routeFinder; private PuzzleRouteFinder routeFinder = null;
private IPuzzleAnimator animator;
public PuzzleChoreographer() public PuzzleChoreographer()
{} {}
@@ -29,8 +25,9 @@ public class PuzzleChoreographer
routeFinder = new PuzzleRouteFinder(p); 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. // 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? // Check if worker selected a box and can push it to the location?
// If yes then we are done. // If yes then we are done.
// //
if ( puzzle.isSelected() if ( puzzle.isSelected() && tryMoveSelectedBox(xy) )
&& tryMoveBox(animator, xy) )
return true; return true;
// //
// Either nothing was selected or the box cannot be moved to // Either nothing was selected or the box cannot be moved to
// tapped location. Try move worker alone. // tapped location. Try move worker alone.
// //
if ( tryMoveWorker( animator, xy ) ) if ( tryMoveWorker(xy) )
return true; return true;
// //
// Show that action is not allowed. // Show that action is not allowed.
// //
animator.undoable(xy); animator.moveImpossible(xy);
} }
// //
// The tapped is the worker. Try move the box. If not possible // 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? // Check if worker selected a box and can push it to the location?
// If yes then we are done. // If yes then we are done.
// //
if ( tryMoveBox(animator, xy) ) if ( tryMoveSelectedBox(xy) ) {
return true; return true;
}
// //
// If the box is not movable then unselect it. // 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 // Try move the worker next to the box and select it if the
// box is not selected yet. // box is not selected yet.
// //
if ( trySelectBox( animator, xy ) ) if ( trySelectBox(xy) ) {
return true; return true;
}
// //
// Show that action is not allowed if reached till here. // Show that action is not allowed if reached till here.
// //
animator.undoable(xy); animator.moveImpossible(xy);
} }
return true; return true;
} }
@@ -126,25 +124,27 @@ public class PuzzleChoreographer
// //
// Routes to accessible cells from where worker stands. // 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 the filed is not accessable then move failed.
// //
if ( !routeFinder.isAccessible(xy) ) if ( !routeFinder.isAccessible(xy) ) {
return false; return false;
}
// //
// First unselect box. // First unselect box.
// //
if ( puzzle.isSelected() ) if ( puzzle.isSelected() ) {
animator.unselect(); animator.unselect();
}
// //
// Get directions and queue moves accordingly. // Get directions and queue moves accordingly.
// //
Vector<XYPair> dirs = routeFinder.getDirections(xy); Vector<XYPair> dirs = routeFinder.getDirections(xy);
ListIterator<XYPair> it = dirs.listIterator(dirs.size()); ListIterator<XYPair> it = dirs.listIterator();
while ( it.hasPrevious() ) { while ( it.hasNext() ) {
animator.move(it.previous()); animator.move(it.next());
} }
// //
// Done. // Done.
@@ -152,26 +152,57 @@ public class PuzzleChoreographer
return true; 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 no box is selected then we cannot move no box.
// //
if ( !puzzle.isSelected() ) if ( !puzzle.isSelected() ) {
return false; 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. // 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(); 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 // There is no point to continue if we are asked to move the box to where is it.
// is the box.
// //
if ( dxy.isEqual(XYPair.ZERO) ) if ( xy.isEqual(box_xy) ) {
return false; 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 // Now find the desired place for the worker to start push this
// box. // box.
@@ -189,8 +220,9 @@ public class PuzzleChoreographer
// Check if the desired place for the worker is accessable? If not // Check if the desired place for the worker is accessable? If not
// then there is no point to continue. // then there is no point to continue.
// //
if ( !routeFinder.isAccessible(w) ) if ( !routeFinder.isAccessible(w) ) {
return false; return false;
}
// //
// Now check that all cell till x,y are empty and that we can // Now check that all cell till x,y are empty and that we can
// push box till there. // push box till there.
@@ -210,7 +242,9 @@ public class PuzzleChoreographer
// //
if ( !w.isEqual(puzzle.getWorker()) ) if ( !w.isEqual(puzzle.getWorker()) )
{ {
tryMoveWorker( animator, w ); if (!tryMoveWorker(w)){
return false;
}
animator.select(box_xy); animator.select(box_xy);
} }
// //
@@ -225,16 +259,17 @@ public class PuzzleChoreographer
return true; return true;
} }
protected boolean trySelectBox( IPuzzleAnimator animator, XYPair xy )
protected boolean trySelectBox(XYPair xy)
{ {
int north = puzzle.getSym(xy.up()); int north = puzzle.getSym(xy.up());
int south = puzzle.getSym(xy.down()); int south = puzzle.getSym(xy.down());
int west = puzzle.getSym(xy.left()); int west = puzzle.getSym(xy.left());
int east = puzzle.getSym(xy.right()); int east = puzzle.getSym(xy.right());
// //
// First check if there is a worker in a nighbour cell. If // First check if there is a worker in a neighboring cell. If
// yes then simplly select the box. If the box is already selected // yes then simply select the box. If the box is already selected
// then do nothing and if othe box is selected then unselect it first // then do nothing and if other box is selected then unselect it first
// and then select the box. // and then select the box.
// //
if ( Puzzle.hasWorker( west ) 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. // distance and move worker to that cell, then select.
// //
else else
@@ -285,9 +320,9 @@ public class PuzzleChoreographer
// Move the worker to the direction. If we cannot move worker // Move the worker to the direction. If we cannot move worker
// next to the box then we cannot select it. // next to the box then we cannot select it.
// //
if ( !puzzle.isValid(pref) if ( !puzzle.isValid(pref) || !tryMoveWorker(pref) ) {
|| !tryMoveWorker(animator, pref) )
return false; return false;
}
// //
// Select the box. // Select the box.
// //

View File

@@ -1,12 +1,17 @@
package org.vostan.banvor.model; package org.vostan.banvor.model;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.Vector; import java.util.Vector;
public class PuzzleRouteFinder { public class PuzzleRouteFinder {
protected Puzzle puzzle = null; protected Puzzle puzzle = null;
protected int [] moves; 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) { public PuzzleRouteFinder(Puzzle p) {
puzzle = p; puzzle = p;
@@ -14,8 +19,7 @@ public class PuzzleRouteFinder {
setOfCells.ensureCapacity(puzzle.getColumnCount() * puzzle.getRowCount()); setOfCells.ensureCapacity(puzzle.getColumnCount() * puzzle.getRowCount());
} }
protected final int getMoves( XYPair xy ) protected final int getMoves( XYPair xy ) {
{
return moves[puzzle.getIndex(xy)]; return moves[puzzle.getIndex(xy)];
} }
protected void setMoves( XYPair xy, int v ) protected void setMoves( XYPair xy, int v )
@@ -93,8 +97,7 @@ public class PuzzleRouteFinder {
return getMoves(xy); return getMoves(xy);
} }
public final boolean isAccessible( XYPair xy ) public final boolean isAccessible( XYPair xy ) {
{
return puzzle.isValid(xy) && stepsAway(xy) != Integer.MAX_VALUE; return puzzle.isValid(xy) && stepsAway(xy) != Integer.MAX_VALUE;
} }
@@ -126,6 +129,7 @@ public class PuzzleRouteFinder {
steps.add(xy.up()); steps.add(xy.up());
} }
} }
Collections.reverse(steps);
return steps; return steps;
} }

View File

@@ -27,11 +27,11 @@ public class XYPair
_y = op.y(); _y = op.y();
} }
public int x(){ public final int x(){
return _x; return _x;
} }
public int y(){ public final int y(){
return _y; return _y;
} }
@@ -57,44 +57,44 @@ public class XYPair
return new XYPair(op1._x*scaliar, op1._y*scaliar); return new XYPair(op1._x*scaliar, op1._y*scaliar);
} }
public XYPair mul(int scaliar){ public final XYPair mul(int scaliar){
return mul(this, scaliar); return mul(this, scaliar);
} }
public XYPair sub(XYPair op){ public final XYPair sub(XYPair op){
return sub(this, op); return sub(this, op);
} }
public XYPair add(XYPair op){ public final XYPair add(XYPair op){
return add(this, op); return add(this, op);
} }
public int l1_norm(){ public final int l1_norm(){
return abs(_x)+abs(_y); return abs(_x)+abs(_y);
} }
public boolean isEqual(XYPair op){ public final boolean isEqual(XYPair op){
return _x == op._x && _y == op._y; 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() return op1.x() <= this.x() && this.x() < op2.x()
&& op1.y() <= this.y() && this.y() < op2.y(); && op1.y() <= this.y() && this.y() < op2.y();
} }
public XYPair left(){ public final XYPair left(){
return this.add(LEFT); return this.add(LEFT);
} }
public XYPair right(){ public final XYPair right(){
return this.add(RIGHT); return this.add(RIGHT);
} }
public XYPair up(){ public final XYPair up(){
return this.add(UP); return this.add(UP);
} }
public XYPair down(){ public final XYPair down(){
return this.add(DOWN); return this.add(DOWN);
} }
} }