From 66d04087f84a0e77ba803e1269442fbdc4af7506 Mon Sep 17 00:00:00 2001 From: Vahagn Khachatryan Date: Sun, 17 Oct 2021 23:04:24 +0100 Subject: [PATCH] PuzzleRouteFinder.getDirections returns proper order of steps. --- .../vostan/banvor/board/PuzzleAnimator.java | 2 +- .../vostan/banvor/model/IPuzzleAnimator.java | 2 +- .../banvor/model/PuzzleChoreographer.java | 113 ++++++++++++------ .../banvor/model/PuzzleRouteFinder.java | 14 ++- .../java/org/vostan/banvor/model/XYPair.java | 24 ++-- 5 files changed, 97 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/org/vostan/banvor/board/PuzzleAnimator.java b/app/src/main/java/org/vostan/banvor/board/PuzzleAnimator.java index bfd0359..a12cccb 100644 --- a/app/src/main/java/org/vostan/banvor/board/PuzzleAnimator.java +++ b/app/src/main/java/org/vostan/banvor/board/PuzzleAnimator.java @@ -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) ); } diff --git a/app/src/main/java/org/vostan/banvor/model/IPuzzleAnimator.java b/app/src/main/java/org/vostan/banvor/model/IPuzzleAnimator.java index d5fb543..4779fa3 100644 --- a/app/src/main/java/org/vostan/banvor/model/IPuzzleAnimator.java +++ b/app/src/main/java/org/vostan/banvor/model/IPuzzleAnimator.java @@ -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 ); } diff --git a/app/src/main/java/org/vostan/banvor/model/PuzzleChoreographer.java b/app/src/main/java/org/vostan/banvor/model/PuzzleChoreographer.java index 3a176c7..4b365db 100644 --- a/app/src/main/java/org/vostan/banvor/model/PuzzleChoreographer.java +++ b/app/src/main/java/org/vostan/banvor/model/PuzzleChoreographer.java @@ -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,52 +124,85 @@ 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 dirs = routeFinder.getDirections(xy); - ListIterator it = dirs.listIterator(dirs.size()); - while ( it.hasPrevious() ) { - animator.move(it.previous()); + ListIterator it = dirs.listIterator(); + while ( it.hasNext() ) { + animator.move(it.next()); } // // Done. // 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. // diff --git a/app/src/main/java/org/vostan/banvor/model/PuzzleRouteFinder.java b/app/src/main/java/org/vostan/banvor/model/PuzzleRouteFinder.java index e790598..523f065 100644 --- a/app/src/main/java/org/vostan/banvor/model/PuzzleRouteFinder.java +++ b/app/src/main/java/org/vostan/banvor/model/PuzzleRouteFinder.java @@ -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 setOfCells = new Vector(); + + // + // This is to avoid fragmentation of memory. + // + private Vector setOfCells = new Vector(); 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; } diff --git a/app/src/main/java/org/vostan/banvor/model/XYPair.java b/app/src/main/java/org/vostan/banvor/model/XYPair.java index b5b1389..c040987 100644 --- a/app/src/main/java/org/vostan/banvor/model/XYPair.java +++ b/app/src/main/java/org/vostan/banvor/model/XYPair.java @@ -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); } }