diff --git a/java/org/artisanlogiciel/games/Display.java b/java/org/artisanlogiciel/games/Display.java index 26408e0..d9571ee 100644 --- a/java/org/artisanlogiciel/games/Display.java +++ b/java/org/artisanlogiciel/games/Display.java @@ -553,6 +553,50 @@ public class Display extends JFrame g.drawLine(x, y, x, y + (int) height); } + public void drawPath(Graphics g, int pX, int pY, short path) + { + int x = offsetX + (int) (pX * width); + int y = offsetY + (int) (pY * height); + int xm = x+ (int) (width / 2); + int ym = y+ (int) (height / 2); + if ( (path & LabyModel.HORIZONTAL) == LabyModel.HORIZONTAL) + { + g.drawLine(x, ym, x + (int) width, ym); + if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE ) + { + g.drawLine(x, ym + (int) (height / 4), x + (int) width, ym); + } + if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE ) + { + g.drawLine(x, ym , x + (int) width, ym - (int) (height / 4)); + } + } + if ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL) + { + g.drawLine(xm, y, xm , y + (int) height); + if ( (path & LabyModel.POSITIVE) == LabyModel.POSITIVE ) + { + g.drawLine(xm - (int) (width / 4), y , xm, y + (int) height); + } + if ( (path & LabyModel.NEGATIVE) == LabyModel.NEGATIVE ) + { + g.drawLine(xm, y , xm + (int) (width /4), y + (int) (height)); + } + } + /* + if ((path & LabyModel.HORIZONTAL) ==LabyModel.HORIZONTAL) + { + y=y+ (int) (height / 2); + g.drawLine(x + (int) width, y, x + (int) width, y + (int) height); + } + if ( (pX == 0 ) && ((path & LabyModel.VERTICAL) == LabyModel.VERTICAL)) + { + x=x+ (int) (width / 2); + g.drawLine(x, y, x, y + (int) height); + } + */ + } + public void drawDot(Graphics g, Position dot, int pX, int pY, int mX, int mY) { double radius = (height > width) ? width : height; @@ -748,6 +792,7 @@ public class Display extends JFrame int x = 0; int y = 0; short walls = 0; + short path = 0; // try to display only visible part... // should compute pX, pY, mX, mY based on clip... @@ -808,6 +853,9 @@ public class Display extends JFrame } } + int aX = pX; + int aY = pY; + g.setColor(Color.black); // draw all walls within clip bounds horiz first then lines @@ -819,7 +867,31 @@ public class Display extends JFrame cp.drawWalls(g, pX, pY, walls); } } - } + + pX = aX; + pY = aY; + + // draw all path within clip bounds horiz first then lines + for (; pY < mY; pY++) + { + for (pX = 0; pX < mX; pX++) + { + path = map.getPath(pX,pY); + if ( ( path & LabyModel.SOLVED ) == LabyModel.SOLVED ) + { + g.setColor(Color.green); + } + else + { + g.setColor(Color.blue); + } + if ( path != 0 ) + { + cp.drawPath(g,pX,pY,path); + } + } + } +} public boolean notifySearch(Position pPosition) diff --git a/java/org/artisanlogiciel/games/LabyModel.java b/java/org/artisanlogiciel/games/LabyModel.java index fceb05a..4472716 100644 --- a/java/org/artisanlogiciel/games/LabyModel.java +++ b/java/org/artisanlogiciel/games/LabyModel.java @@ -28,13 +28,14 @@ public class LabyModel implements WallsProvider private final static short FLAGLENGTH = 7; private final static short CLEAR = 0; // mandatory 0 since array creation is // initialized with 0. - private final static short HORIZONTAL = 1; - private final static short VERTICAL = 2; - private final static short DIRECTION = 4; // could we get rid of that to + public final static short HORIZONTAL = 1; + public final static short VERTICAL = 2; + public final static short DIRECTION = 4; // could we get rid of that to // free one bit for other purpose // ? - private final static short POSITIVE = 8; - private final static short NEGATIVE = 16; + public final static short POSITIVE = 8; + public final static short NEGATIVE = 16; + private final static short OPEN = 32; // can be reused once generation is // completed private final static short CLOSED = 64; // can be reused once generation is @@ -52,7 +53,7 @@ public class LabyModel implements WallsProvider // wall should // be open to // access this. - private final static short SOLVED = 64 << FLAGLENGTH; // flag when solution + public final static short SOLVED = 64 << FLAGLENGTH; // flag when solution // is on this path. private final static short FREE = 128 << FLAGLENGTH; // free flag // remains 2 free bits ( keep one out for sign ) @@ -545,89 +546,100 @@ public class LabyModel implements WallsProvider /** * resolve this labrynth using internal representation + * initial (x,y) is exit, will return list of positions from start to end. **/ public LinkedList resolve(int x, int y, MazeResolutionListener rlistener) { + long safeguard = width * height; int newx = x; int newy = y; + // list of positions from start to end LinkedList backpath = new LinkedList(); while (!((newx == 0) && (newy == 0))) { + // position that point to (x,y). Position found = null; + if (( x == newx ) && ( y == newy )) + { + System.out.println("[ERROR] path contains same consecutive point" + new Position(newx, newy).toString()); + } x = newx; y = newy; backpath.addFirst(new Position(x, y)); - // should find from all direction one that point to this. - ArrayList freeDirection = new ArrayList(); + // should find from all adjacent cells (directions) one that point to this. + { + ArrayList freeDirection = new ArrayList(); - for (int didx = 0; didx < 4; didx++) - { - int delta = 0; - short direction = AllDirections[didx]; - short reversedirection = AllDirections[(didx + 2) % 4]; - short pointingdirection = DIRECTION; + // didx is index of four cell adjacent to this (x,y) + for (int didx = 0; didx < 4; didx++) + { + int delta = 0; + short direction = AllDirections[didx]; + short reversedirection = AllDirections[(didx + 2) % 4]; + short pointingdirection = DIRECTION; - if ((direction & POSITIVE) == POSITIVE) - { - delta = 1; - pointingdirection |= NEGATIVE; - } - else - { - delta = -1; - pointingdirection |= POSITIVE; - } + if ((direction & POSITIVE) == POSITIVE) + { + delta = 1; + pointingdirection |= NEGATIVE; + } + else + { + delta = -1; + pointingdirection |= POSITIVE; + } - if ((direction & HORIZONTAL) == HORIZONTAL) - { - newx = x + delta; - newy = y; - pointingdirection |= HORIZONTAL; - } - else - { - newy = y + delta; - newx = x; - pointingdirection |= VERTICAL; - } + if ((direction & HORIZONTAL) == HORIZONTAL) + { + newx = x + delta; + newy = y; + pointingdirection |= HORIZONTAL; + } + else + { + newy = y + delta; + newx = x; + pointingdirection |= VERTICAL; + } - // internal GUARD. - if ((reversedirection & pointingdirection) != pointingdirection) - { - System.out.println("Internal ERROR. Please check AllDirections order " - + (reversedirection & pointingdirection) + " " + pointingdirection); - return backpath; - } + // internal GUARD. + if ((reversedirection & pointingdirection) != pointingdirection) + { + System.out.println("Internal ERROR. Please check AllDirections order " + + (reversedirection & pointingdirection) + " " + pointingdirection); + return backpath; + } - if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height)) - { - if ((t[newx][newy] & reversedirection) == reversedirection) - { - if (found != null) - { - // could be a unique parent of two paths... - // but search from other entry/exits than generated - // from - // ie entry(0,0) exit(width-1,height-1) not yet - // implemented. - if (rlistener != null) - { - rlistener.notifySearchError("Model Error : two parents " + found.toString() + " " - + new Position(newx, newy).toString()); - } - return backpath; - } - found = new Position(newx, newy); - if (rlistener != null) - { - rlistener.notifySearch(found); - } - break; - } - } - } + if ((newx >= 0) && (newy >= 0) && (newx < width) && (newy < height)) + { + if ((t[newx][newy] & reversedirection) == reversedirection) + { + if (found != null) + { + // could be a unique parent of two paths... + // but search from other entry/exits than generated + // from + // ie entry(0,0) exit(width-1,height-1) not yet + // implemented. + if (rlistener != null) + { + rlistener.notifySearchError("Model Error : two parents " + found.toString() + " " + + new Position(newx, newy).toString()); + } + return backpath; + } + found = new Position(newx, newy); + if (rlistener != null) + { + rlistener.notifySearch(found); + } + break; + } + } + } + } if (found == null) { rlistener.notifySearchError("No path found !"); @@ -636,7 +648,22 @@ public class LabyModel implements WallsProvider // System.out.println(found); newx = found.getX(); newy = found.getY(); - t[newx][newy] |= SOLVED; + if ( ( t[newx][newy] & SOLVED ) == SOLVED ) + { + System.out.println("[INFO] position already solved" + new Position(newx, newy).toString() + " *length:" + backpath.size()); + } + else + { + t[newx][newy] |= SOLVED; + } + + + safeguard --; + if ( safeguard < 0 ) + { + rlistener.notifySearchError("Path too long ( or long overflow ) for width*height:" + (width*height) + " length:" + backpath.size()); + break; + } } if (rlistener != null) { @@ -813,6 +840,16 @@ public class LabyModel implements WallsProvider return walls; } + public short getPath(int x, int y) + { + short path = 0; + if (( x < width ) && ( y < height )) + { + path = t[x][y]; + } + return path; + } + /** * is there a wall in that direction ? **/