initial commit for labryinth project on git_hub.
Signed-off-by: philippe lhardy <philippe@pavilionartlogiciel>
This commit is contained in:
48
java/Makefile
Normal file
48
java/Makefile
Normal file
@@ -0,0 +1,48 @@
|
||||
PACKAGE=org.artisanlogiciel.games
|
||||
PACKAGE_DIR=$(subst .,/,$(PACKAGE))
|
||||
OUT=out
|
||||
|
||||
$(OUT):
|
||||
mkdir -p $(OUT)
|
||||
|
||||
clean:
|
||||
find $(OUT) -name "*.class" -type f -print0|xargs -0 rm
|
||||
|
||||
test:
|
||||
javac -d $(OUT) $(PACKAGE_DIR)/LabyModel.java
|
||||
javac -d $(OUT) $(PACKAGE_DIR)/Main.java
|
||||
java -cp $(OUT) $(PACKAGE).Main
|
||||
|
||||
|
||||
run/%: $(OUT)
|
||||
javac -d $(OUT) $(PACKAGE_DIR)/$(subst run/,,$@).java
|
||||
java -cp $(OUT) $(PACKAGE)/$(subst run/,,$@)
|
||||
|
||||
display: run/Display
|
||||
|
||||
|
||||
display/%: $(OUT)
|
||||
javac -d $(OUT) $(PACKAGE_DIR)/Display.java
|
||||
java -cp $(OUT) $(PACKAGE).Display $(subst display/,,$@)
|
||||
|
||||
compile/%:
|
||||
javac -d $(OUT) $(PACKAGE_DIR)/$(subst compile/,,$@).java
|
||||
|
||||
$(PACKAGE_DIR)/%.java:
|
||||
./generate_newclass.sh $(subst .java,,$(subst $(PACKAGE_DIR)/,,$@))
|
||||
|
||||
work/%: $(PACKAGE_DIR)/$(subst work/,,%).java
|
||||
emacs $<
|
||||
|
||||
work: work/LabyModel
|
||||
|
||||
save:
|
||||
git citool
|
||||
|
||||
.PHONY: clean test work display work/% run/% save compile/%
|
||||
|
||||
# tried to avoid intermediate file removal : does not work
|
||||
# .SECONDARY: $(PACKAGE_DIR)/%.java
|
||||
|
||||
# this does work : once precious intermediate file is not removed.
|
||||
.PRECIOUS: $(PACKAGE_DIR)/%.java
|
||||
21
java/README
Normal file
21
java/README
Normal file
@@ -0,0 +1,21 @@
|
||||
A Maze generator that keep all reverse paths to solutions.
|
||||
|
||||
See Makefile
|
||||
|
||||
#clean
|
||||
make clean
|
||||
|
||||
#console
|
||||
make test
|
||||
|
||||
#gui
|
||||
make display
|
||||
|
||||
#code emacs : work/ClassName
|
||||
make work/Display
|
||||
|
||||
#run a class
|
||||
make run/Display
|
||||
|
||||
#save work with git (ie git citool )
|
||||
make save
|
||||
15
java/TODO
Normal file
15
java/TODO
Normal file
@@ -0,0 +1,15 @@
|
||||
By pref
|
||||
|
||||
- rendering
|
||||
GUI
|
||||
* WALK it...
|
||||
* regenerate it
|
||||
|
||||
CONSOLE :
|
||||
* provide interactive ( view a part of maze )
|
||||
|
||||
- model
|
||||
* saving in stream ( better than in toString() that basically fails... )
|
||||
|
||||
- format :
|
||||
3D format ( for 3Dprinting )
|
||||
74
java/generate_newclass.sh
Executable file
74
java/generate_newclass.sh
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
PACKAGE=org.artisanlogiciel.games
|
||||
|
||||
while [[ $# > 0 ]]
|
||||
do
|
||||
case $1 in
|
||||
package=*)
|
||||
PACKAGE=${1/package=/}
|
||||
;;
|
||||
*)
|
||||
CLASS=${1}
|
||||
;;
|
||||
esac
|
||||
shift 1
|
||||
done
|
||||
|
||||
if [[ -z $CLASS ]]
|
||||
then
|
||||
echo "[ERROR] Missing class" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PACKAGE_DIR=${PACKAGE//\./\/}
|
||||
|
||||
if [[ ! -d $PACKAGE_DIR ]]
|
||||
then
|
||||
echo "Missing $PACKAGE_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
JAVA_FILE=$PACKAGE_DIR/$CLASS.java
|
||||
if [[ -e $JAVA_FILE ]]
|
||||
then
|
||||
echo "[ERROR] $JAVA_FILE already exists" >&2
|
||||
exit 1
|
||||
else
|
||||
|
||||
cat <<EOF >$JAVA_FILE
|
||||
package $PACKAGE;
|
||||
|
||||
/**
|
||||
$CLASS was autogenerated by $0
|
||||
**/
|
||||
public class $CLASS
|
||||
{
|
||||
Object param;
|
||||
|
||||
$CLASS(Object param)
|
||||
{
|
||||
this.param=param;
|
||||
}
|
||||
|
||||
void method()
|
||||
{
|
||||
System.out.println("Method of $PACKAGE.$CLASS");
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
if ( args.length > 1 )
|
||||
{
|
||||
$CLASS instance=new $CLASS(args[1]);
|
||||
instance.method();
|
||||
}
|
||||
else
|
||||
{
|
||||
System.err.println("Missing argument for $CLASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "$JAVA_FILE generated"
|
||||
122
java/org/artisanlogiciel/games/Brick.java
Normal file
122
java/org/artisanlogiciel/games/Brick.java
Normal file
@@ -0,0 +1,122 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
/*
|
||||
2x2 Tile to represent a labyrinth position
|
||||
|
||||
ab
|
||||
cd
|
||||
|
||||
a is 'H' or '.' or ' '
|
||||
bcd is 'H' or ' '
|
||||
|
||||
*/
|
||||
public class Brick {
|
||||
|
||||
public final static short LEFT=1;
|
||||
public final static short DOWN=2;
|
||||
public final static short RIGHT=4;
|
||||
public final static short UP=8;
|
||||
public final static short ENTRY=16;
|
||||
public final static short GOAL=32;
|
||||
|
||||
char a;
|
||||
char b;
|
||||
char c;
|
||||
char d;
|
||||
short walls; // according to LabyModel.getWalls();
|
||||
|
||||
public Brick(char center, char right, char down, char downright,short walls)
|
||||
{
|
||||
a=center;
|
||||
b=right;
|
||||
c=down;
|
||||
d=downright;
|
||||
this.walls=walls;
|
||||
}
|
||||
|
||||
public Brick(String up, String low, short walls)
|
||||
{
|
||||
a = up.charAt(0);
|
||||
b = up.charAt(1);
|
||||
c = low.charAt(0);
|
||||
d = low.charAt(1);
|
||||
this.walls=walls;
|
||||
}
|
||||
|
||||
private boolean check()
|
||||
{
|
||||
// Not Yet Implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
public String getUpString()
|
||||
{
|
||||
return "" + a + b;
|
||||
}
|
||||
|
||||
public String getLowString()
|
||||
{
|
||||
return "" + c + d;
|
||||
}
|
||||
|
||||
public static String getDirLine()
|
||||
{
|
||||
char dir[] = new char[16];
|
||||
String s="";
|
||||
|
||||
/*
|
||||
dir[LEFT | DOWN | RIGHT | UP]='O';
|
||||
dir[LEFT | DOWN | RIGHT]='U';
|
||||
dir[LEFT | UP | RIGHT]='M';
|
||||
dir[LEFT | UP | DOWN]='[';
|
||||
dir[RIGHT | UP | DOWN]=']';
|
||||
dir[UP | DOWN]='=';
|
||||
dir[LEFT | RIGHT]='|';
|
||||
dir[RIGHT | DOWN]='J';
|
||||
dir[LEFT | DOWN]='L';
|
||||
dir [LEFT | UP]='T';
|
||||
dir[UP | RIGHT]='7';
|
||||
dir[LEFT] = '!';
|
||||
dir[RIGHT] ='|';
|
||||
dir[DOWN]= '_';
|
||||
dir[UP]= '¨';
|
||||
dir[0]=' ';
|
||||
*/
|
||||
|
||||
dir[LEFT | DOWN | RIGHT | UP]='O';
|
||||
dir[LEFT | DOWN | RIGHT]='U';
|
||||
dir[LEFT | UP | RIGHT]='M';
|
||||
dir[LEFT | UP | DOWN]='[';
|
||||
dir[RIGHT | UP | DOWN]=']';
|
||||
dir[UP | DOWN]='=';
|
||||
dir[LEFT | RIGHT]=226;
|
||||
dir[RIGHT | DOWN]='J';
|
||||
dir[LEFT | DOWN]='L';
|
||||
dir [LEFT | UP]=169;
|
||||
dir[UP | RIGHT]=170;
|
||||
dir[LEFT] = 173;
|
||||
dir[RIGHT] ='|';
|
||||
dir[DOWN]= '_';
|
||||
dir[UP]= '¨';
|
||||
dir[0]=' ';
|
||||
|
||||
for (int i=0;i< 16; i++)
|
||||
{
|
||||
s=s+dir[i];
|
||||
}
|
||||
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
public char getChar()
|
||||
{
|
||||
// return getDirLine().charAt(walls & 0xFFF0);
|
||||
return getDirLine().charAt(walls);
|
||||
}
|
||||
|
||||
public short getWalls()
|
||||
{
|
||||
return walls;
|
||||
}
|
||||
}
|
||||
542
java/org/artisanlogiciel/games/Display.java
Normal file
542
java/org/artisanlogiciel/games/Display.java
Normal file
@@ -0,0 +1,542 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Container;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Scanner;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
Display
|
||||
**/
|
||||
public class Display extends JFrame
|
||||
|
||||
{
|
||||
Object param;
|
||||
JPanel pane = new JPanel();
|
||||
MazeComponent maze;
|
||||
MazeControler controler;
|
||||
LabyModel model;
|
||||
|
||||
Display(LabyModel model, MazeComponent comp)
|
||||
{
|
||||
super("Maze display");
|
||||
maze=comp;
|
||||
this.param=param;
|
||||
this.model=model;
|
||||
Container con = this.getContentPane();
|
||||
con.add(pane);
|
||||
con.add(new JScrollPane(comp), BorderLayout.CENTER);
|
||||
controler = new MazeControler();
|
||||
con.add(controler,BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
void resolve()
|
||||
{
|
||||
model.resolve(model.getWidth()-1,model.getHeight()-1,maze);
|
||||
}
|
||||
|
||||
void goNorth()
|
||||
{
|
||||
maze.goNorth();
|
||||
}
|
||||
|
||||
void goSouth()
|
||||
{
|
||||
maze.goSouth();
|
||||
}
|
||||
|
||||
void goEast()
|
||||
{
|
||||
maze.goEast();
|
||||
}
|
||||
|
||||
void goWest()
|
||||
{
|
||||
maze.goWest();
|
||||
}
|
||||
|
||||
void setWallSize(int size)
|
||||
{
|
||||
maze.setWallSize(size);
|
||||
}
|
||||
|
||||
private class MazeControler extends JPanel
|
||||
{
|
||||
public MazeControler()
|
||||
{
|
||||
JPanel controlPanel = new JPanel();
|
||||
JButton button=new JButton("Resolve");
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
//
|
||||
System.out.println("Resolving");
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
JButton north = new JButton("North");
|
||||
Action goNorth = new AbstractAction()
|
||||
{
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
//
|
||||
System.out.println("go North");
|
||||
goNorth();
|
||||
}
|
||||
};
|
||||
KeyStroke kup=KeyStroke.getKeyStroke("UP");
|
||||
getInputMap().put(kup,"goNorth");
|
||||
getActionMap().put("goNorth",goNorth);
|
||||
controlPanel.getInputMap().put(kup,"goNorth");
|
||||
controlPanel.getActionMap().put("goNorth",goNorth);
|
||||
north.getActionMap().put("goNorth",goNorth);
|
||||
JButton east = new JButton("East");
|
||||
Action goEast = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
//
|
||||
System.out.println("go East");
|
||||
goEast();
|
||||
}
|
||||
};
|
||||
east.addActionListener(goEast);
|
||||
KeyStroke kright=KeyStroke.getKeyStroke("RIGHT");
|
||||
getInputMap().put(kright,"goEast");
|
||||
getActionMap().put("goEast",goEast);
|
||||
controlPanel.getInputMap().put(kright,"goEast");
|
||||
controlPanel.getActionMap().put("goEast",goEast);
|
||||
JButton west = new JButton("West");
|
||||
Action goWest = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
//
|
||||
System.out.println("go West");
|
||||
goWest();
|
||||
}
|
||||
};
|
||||
west.addActionListener(goWest);
|
||||
KeyStroke kwest=KeyStroke.getKeyStroke("LEFT");
|
||||
getInputMap().put(kwest,"goWest");
|
||||
getActionMap().put("goWest",goWest);
|
||||
controlPanel.getInputMap().put(kwest,"goWest");
|
||||
controlPanel.getActionMap().put("goWest",goWest);
|
||||
JButton south = new JButton("South");
|
||||
Action goSouth = new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent evt)
|
||||
{
|
||||
//
|
||||
System.out.println("go South");
|
||||
goSouth();
|
||||
}
|
||||
};
|
||||
south.addActionListener(goSouth);
|
||||
KeyStroke kdown=KeyStroke.getKeyStroke("DOWN");
|
||||
controlPanel.getInputMap().put(kdown,"goSouth");
|
||||
controlPanel.getActionMap().put("goSouth",goSouth);
|
||||
getInputMap().put(KeyStroke.getKeyStroke("DOWN"),"goSouth");
|
||||
getActionMap().put("goSouth",goSouth);
|
||||
controlPanel.getInputMap().put(KeyStroke.getKeyStroke("DOWN"),"goSouth");
|
||||
controlPanel.getActionMap().put("goSouth",goSouth);
|
||||
|
||||
controlPanel.add(button,BorderLayout.NORTH);
|
||||
controlPanel.add(north,BorderLayout.NORTH);
|
||||
controlPanel.add(east,BorderLayout.EAST);
|
||||
controlPanel.add(west,BorderLayout.WEST);
|
||||
controlPanel.add(south,BorderLayout.SOUTH);
|
||||
add(controlPanel,BorderLayout.NORTH);
|
||||
final JSlider slider=new JSlider(2,40);
|
||||
slider.addChangeListener(new ChangeListener() {
|
||||
public void stateChanged(ChangeEvent e)
|
||||
{
|
||||
setWallSize(slider.getValue());
|
||||
}
|
||||
});
|
||||
add(slider,BorderLayout.SOUTH);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class MazeComponent extends JComponent
|
||||
implements MazeCreationListener,
|
||||
MazeResolutionListener
|
||||
{
|
||||
WallsProvider map;
|
||||
int width = 10;
|
||||
int height = 10;
|
||||
int offsetX = 5;
|
||||
int offsetY = 5;
|
||||
Position current = null;
|
||||
LinkedList<Position> solvedPath = null;
|
||||
final Object lockChange = new Object();
|
||||
// current postion of human resolution
|
||||
int sX = 0;
|
||||
int sY = 0;
|
||||
// goal exit
|
||||
int gX = -1;
|
||||
int gY = -1;
|
||||
|
||||
void checkExit()
|
||||
{
|
||||
if ((sX == gX) && (sY == gY))
|
||||
{
|
||||
System.out.println("Exit found by human !");
|
||||
}
|
||||
}
|
||||
void goNorth()
|
||||
{
|
||||
resetResolution();
|
||||
if ( (map.getWalls(sX,sY) & Brick.UP) == 0 )
|
||||
{
|
||||
sY = sY -1;
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
|
||||
checkExit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void goSouth()
|
||||
{
|
||||
resetResolution();
|
||||
if ( (map.getWalls(sX,sY) & Brick.DOWN) == 0 )
|
||||
{
|
||||
sY =sY + 1;
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
|
||||
checkExit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void goEast()
|
||||
{
|
||||
resetResolution();
|
||||
if ( (map.getWalls(sX,sY) & Brick.RIGHT) == 0 )
|
||||
{
|
||||
sX = sX + 1;
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
|
||||
checkExit();
|
||||
}
|
||||
}
|
||||
|
||||
void goWest()
|
||||
{
|
||||
resetResolution();
|
||||
if ( (map.getWalls(sX,sY) & Brick.LEFT) == 0 )
|
||||
{
|
||||
sX = sX - 1;
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
|
||||
checkExit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public MazeComponent(WallsProvider map, int width, int height, int offsetX, int offsetY)
|
||||
{
|
||||
super();
|
||||
this.map=map;
|
||||
this.width=width;
|
||||
this.height=height;
|
||||
this.offsetX=offsetX;
|
||||
this.offsetY=offsetY;
|
||||
setPreferredSize(new Dimension(1+2*offsetX+map.getWidth()*width,
|
||||
1+2*offsetY+map.getHeight()*height));
|
||||
gX = map.getWidth() -1;
|
||||
gY = map.getHeight() -1;
|
||||
}
|
||||
|
||||
public void setWallSize(int size)
|
||||
{
|
||||
|
||||
width=size;
|
||||
height=size;
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void changed(Position cl, Position cr, WallsProvider map)
|
||||
{
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
Object waiter = new Object();
|
||||
synchronized(waiter)
|
||||
{
|
||||
try {
|
||||
waiter.wait(10);
|
||||
}
|
||||
catch( InterruptedException e)
|
||||
{
|
||||
System.err.println("Interrupted !");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawWalls(Graphics g, int x, int y, short walls, boolean full)
|
||||
{
|
||||
if ( (full) && (( walls & Brick.UP ) == Brick.UP )) g.drawLine(x, y, x+width, y);
|
||||
if ( ( walls & Brick.DOWN ) == Brick.DOWN ) g.drawLine(x, y+height, x+width, y+height);
|
||||
if ( ( walls & Brick.RIGHT ) == Brick.RIGHT ) g.drawLine(x+width, y, x+width, y+height);
|
||||
if ( (full) && (( walls & Brick.LEFT ) == Brick.LEFT )) g.drawLine(x, y, x, y+height);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
super.paintComponent(g);
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
short walls=0;
|
||||
|
||||
// try to display only visible part...
|
||||
// should compute pX, pY, mX, mY based on clip...
|
||||
// Shape s=g.getClip();
|
||||
Rectangle r= g.getClipBounds();
|
||||
|
||||
int mX = (int) ( (double) r.getWidth() / width);
|
||||
int mY = (int) ( (double) r.getHeight() / height);
|
||||
int pX = (int) ( (double) (r.getX() - offsetX) / width);
|
||||
int pY = (int) ( (double) (r.getY() - offsetY) / height);
|
||||
|
||||
if ( pX < 0) pX = 0;
|
||||
if ( pY < 0) pY = 0;
|
||||
if ( pX >= map.getWidth()) return;
|
||||
if ( pY >= map.getHeight()) return;
|
||||
|
||||
mX=mX+pX;
|
||||
mY=mY+pY;
|
||||
|
||||
if ( mX > map.getWidth() )
|
||||
{
|
||||
mX = map.getWidth();
|
||||
}
|
||||
if ( mY > map.getHeight())
|
||||
{
|
||||
mY = map.getHeight();
|
||||
}
|
||||
|
||||
if ((sX == gX ) && (sY == gY ))
|
||||
{
|
||||
g.setColor(Color.red);
|
||||
}
|
||||
else
|
||||
{
|
||||
g.setColor(Color.blue);
|
||||
}
|
||||
drawDot(g,new Position(sX,sY),pX,pY,mX,mY);
|
||||
|
||||
synchronized(lockChange)
|
||||
{
|
||||
g.setColor(Color.red);
|
||||
if ( current != null)
|
||||
{
|
||||
drawDot(g,current,pX,pY,mX,mY);
|
||||
}
|
||||
if (solvedPath != null)
|
||||
{
|
||||
for ( Position resolved : solvedPath )
|
||||
{
|
||||
drawDot(g,resolved,pX,pY,mX,mY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g.setColor(Color.black);
|
||||
for ( ; pY < mY ; pY ++)
|
||||
{
|
||||
for ( pX = 0; pX < mX ; pX ++)
|
||||
{
|
||||
x=offsetX+pX*width;
|
||||
y=offsetY+pY*height;
|
||||
walls = map.getWalls(pX,pY);
|
||||
drawWalls(g,x,y,walls,(pX == 0) || (pY==0));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawDot(Graphics g,Position dot, int pX, int pY, int mX, int mY)
|
||||
{
|
||||
int radius = ( height > width ) ? width : height;
|
||||
int a = radius / 4;
|
||||
if (( dot.getX() >= pX ) && ( dot.getY() >= pY ) && ( dot.getX() < mX ) && ( dot.getY() < mY ) )
|
||||
{
|
||||
int x=offsetX+dot.getX()*width;
|
||||
int y=offsetY+dot.getY()*height;
|
||||
g.drawOval(x+1,y+1,radius-a,radius-a);
|
||||
//g.drawLine(x+a,y+a,x+width-a,y+height-a);
|
||||
//g.drawLine(x+a,y+height-a,x+width-a,y+a);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int x=offsetX+pX*width;
|
||||
int y=offsetY+pY*height;
|
||||
g.drawLine(x+1,y+1,x+width-1,y+height-1);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean notifySearch(Position pPosition)
|
||||
{
|
||||
synchronized(lockChange)
|
||||
{
|
||||
current = pPosition;
|
||||
}
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
public void notifySearchError(String error)
|
||||
{
|
||||
System.err.println(error);
|
||||
}
|
||||
|
||||
public void notifyCompletion(LinkedList<Position> solvedPath)
|
||||
{
|
||||
LinkedList<Position> newPath = (LinkedList<Position>) solvedPath.clone();
|
||||
System.out.println("resolution completed");
|
||||
synchronized(lockChange)
|
||||
{
|
||||
this.solvedPath = newPath;
|
||||
}
|
||||
// should redraw ...
|
||||
invalidate();
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void resetResolution()
|
||||
{
|
||||
solvedPath = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String pArgs[])
|
||||
{
|
||||
LabyModel model = null;
|
||||
int W = 600;
|
||||
int H = 400;
|
||||
|
||||
if ( pArgs.length > 0 )
|
||||
{
|
||||
try {
|
||||
model = new LabyModel("raw",new FileInputStream(pArgs[0]));
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
io.printStackTrace(System.err);
|
||||
}
|
||||
|
||||
int w = W / model.getWidth();
|
||||
int h = H / model.getHeight();
|
||||
if ( w < 5 ) w = 5;
|
||||
if ( h < 5 ) h = 5;
|
||||
MazeComponent comp = new MazeComponent(model,w,h,3,3);
|
||||
Display display=new Display(model, comp);
|
||||
model.setMazeListener(comp);
|
||||
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
display.setBounds(W,H,W,H);
|
||||
display.setVisible(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.println("enter width height and maxdepth");
|
||||
Scanner console = new Scanner(System.in);
|
||||
int width = console.nextInt();
|
||||
int height = console.nextInt();
|
||||
int maxdepth = console.nextInt();
|
||||
model = new LabyModel(width, height,maxdepth, new java.util.Random());
|
||||
int w = W / width;
|
||||
int h = H / height;
|
||||
if ( w < 5 ) w = 5;
|
||||
if ( h < 5 ) h = 5;
|
||||
MazeComponent comp = new MazeComponent(model,w,h,3,3);
|
||||
Display display=new Display(model,comp);
|
||||
model.setMazeListener(comp);
|
||||
display.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
display.setBounds(W,H,W,H);
|
||||
display.setVisible(true);
|
||||
|
||||
model.generateWithEntry(0, 0);
|
||||
LinkedList<Position> exits = new LinkedList<Position>();
|
||||
model.addEntryOrExit(-1,0);
|
||||
model.addEntryOrExit(width,height -1);
|
||||
System.out.println("Generation completed");
|
||||
String name="lab" + width + "x" + height;
|
||||
File outfile = new File(new File("lab"), name + ".raw");
|
||||
if ( ! outfile.exists())
|
||||
{
|
||||
System.out.println( "Saving to " + outfile + " ...");
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(outfile);
|
||||
model.streamOut("raw",out);
|
||||
out.flush();
|
||||
out.close();
|
||||
System.out.println( "... Done.");
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
io.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println( "" + outfile + " already exists");
|
||||
}
|
||||
outfile = new File(new File("lab"),name + ".stl");
|
||||
if ( ! outfile.exists())
|
||||
{
|
||||
System.out.println( "Saving to " + outfile + " ...");
|
||||
try {
|
||||
FileOutputStream out = new FileOutputStream(outfile);
|
||||
Wall3d.streamWallsOut(name,(WallsProvider) model,out);
|
||||
out.flush();
|
||||
out.close();
|
||||
System.out.println( "... Done.");
|
||||
}
|
||||
catch (IOException io)
|
||||
{
|
||||
io.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
else {
|
||||
System.out.println( "" + outfile + " already exists");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
106
java/org/artisanlogiciel/games/LabyMap.java
Normal file
106
java/org/artisanlogiciel/games/LabyMap.java
Normal file
@@ -0,0 +1,106 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
class LabyMap
|
||||
implements WallsProvider
|
||||
{
|
||||
|
||||
Brick[][] tileMap;
|
||||
LinkedList<Position> exits = new LinkedList<Position>();
|
||||
|
||||
public LabyMap(Brick[][] tileMap, LinkedList<Position> exits)
|
||||
{
|
||||
this.tileMap = tileMap;
|
||||
this.exits = exits;
|
||||
}
|
||||
|
||||
Brick getAt(int x, int y)
|
||||
{
|
||||
return tileMap[x][y];
|
||||
}
|
||||
|
||||
public short getWalls(int x, int y)
|
||||
{
|
||||
return getAt(x,y).getWalls();
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return tileMap[0].length;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return tileMap.length;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
int entryX = -1;
|
||||
int entryY = -1;
|
||||
for ( Position exit: exits )
|
||||
{
|
||||
if ( exit.getX() == -1 )
|
||||
{
|
||||
entryY = exit.getY();
|
||||
}
|
||||
if ( exit.getY() == -1 )
|
||||
{
|
||||
entryX= exit.getX();
|
||||
}
|
||||
}
|
||||
String laby="H";
|
||||
for ( int x=0; x < tileMap.length; x ++) {
|
||||
if ( entryX == x ) { laby += " H" ; }
|
||||
else { laby+="HH";}
|
||||
}
|
||||
laby+="\n";
|
||||
for ( int y=0; y < tileMap[0].length; y++)
|
||||
{
|
||||
if ( entryY == y ) { laby += ">";}
|
||||
else { laby += "H"; }
|
||||
for ( int x=0; x < tileMap.length; x ++)
|
||||
{
|
||||
laby+= tileMap[x][y].getUpString();
|
||||
}
|
||||
laby+="\n";
|
||||
laby += "H";
|
||||
for ( int x=0; x < tileMap.length; x ++)
|
||||
{
|
||||
laby+= tileMap[x][y].getLowString();
|
||||
}
|
||||
laby+="\n";
|
||||
}
|
||||
return laby;
|
||||
}
|
||||
|
||||
|
||||
public String toShortString()
|
||||
{
|
||||
int entryX = -1;
|
||||
int entryY = -1;
|
||||
for ( Position exit: exits )
|
||||
{
|
||||
if ( exit.getX() == -1 )
|
||||
{
|
||||
entryY = exit.getY();
|
||||
}
|
||||
if ( exit.getY() == -1 )
|
||||
{
|
||||
entryX= exit.getX();
|
||||
}
|
||||
}
|
||||
String laby="";
|
||||
for ( int y=0; y < tileMap[0].length; y++)
|
||||
{
|
||||
for ( int x=0; x < tileMap.length; x ++)
|
||||
{
|
||||
laby+= "" + tileMap[x][y].getChar();
|
||||
}
|
||||
laby+="\n";
|
||||
}
|
||||
return laby;
|
||||
}
|
||||
|
||||
}
|
||||
808
java/org/artisanlogiciel/games/LabyModel.java
Normal file
808
java/org/artisanlogiciel/games/LabyModel.java
Normal file
@@ -0,0 +1,808 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Collections;
|
||||
import java.util.Random;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
|
||||
/**
|
||||
Model of labyrinth storing only paths not walls. wall are regenerated later on based on adjacent paths.
|
||||
each position (x,y) stores what move can be done from here to go do deeper path.
|
||||
a node is tagged OPEN and contained in openList if all moves from its position have not been resolved
|
||||
a node is tagged CLOSED when fully processed
|
||||
**/
|
||||
public class LabyModel
|
||||
implements WallsProvider
|
||||
{
|
||||
|
||||
/** WARNING don't change those values, they are used as it is for optimisation */
|
||||
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 free one bit for other purpose ?
|
||||
private final static short POSITIVE=8;
|
||||
private 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 completed
|
||||
private final static short LEFT=Brick.LEFT<<FLAGLENGTH|DIRECTION|HORIZONTAL|NEGATIVE;
|
||||
private final static short DOWN=Brick.DOWN<<FLAGLENGTH|DIRECTION|VERTICAL|POSITIVE;
|
||||
private final static short RIGHT=Brick.RIGHT<<FLAGLENGTH|DIRECTION|HORIZONTAL|POSITIVE;
|
||||
private final static short UP=Brick.UP<<FLAGLENGTH|DIRECTION|VERTICAL|NEGATIVE;
|
||||
private final static short ENTRY=Brick.ENTRY<<FLAGLENGTH; // flag when a wall should be open to access this.
|
||||
private final static short GOAL=Brick.GOAL<<FLAGLENGTH; // flag when a wall should be open to access this.
|
||||
private 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 )
|
||||
|
||||
private static final short[] AllDirections = {LEFT,DOWN,RIGHT,UP};
|
||||
|
||||
private int width;
|
||||
private int height;
|
||||
private short [][] t;
|
||||
private int depth=0;
|
||||
/** will enforce maxdepth as maxium length of path in depth first.
|
||||
It means that after every maxdepth moves there should be crossing paths.
|
||||
I think that to shorter maxdepth is the harder the labyrinth is ...
|
||||
**/
|
||||
private int maxdepth=0;
|
||||
private int deepest=0; // longest path found
|
||||
private int linearwork=0;
|
||||
private Position deepestEnd = null;
|
||||
boolean maxreached = false;
|
||||
java.util.Random random;
|
||||
private final LinkedList<Position> openList = new LinkedList<Position>();
|
||||
//list of entries and exits.
|
||||
private final LinkedList<Position> entryExits = new LinkedList<Position>();
|
||||
private final Object coherentLock = new Object(); // before getting the lock and after lock release all is coherent ( ie check() is ok ),
|
||||
|
||||
MazeCreationListener listener = null;
|
||||
|
||||
|
||||
public LabyModel(int width, int height,int maxdepth, Random random){
|
||||
this.width=width;
|
||||
this.height=height;
|
||||
this.maxdepth=maxdepth;
|
||||
this.random = random;
|
||||
// CLEAR == 0 and array is initialized with 0s
|
||||
t= new short[width][height];
|
||||
}
|
||||
|
||||
public LabyModel(String pFormat, InputStream pIn)
|
||||
throws IOException
|
||||
{
|
||||
parseInputStream(pFormat, pIn);
|
||||
}
|
||||
|
||||
public void setMazeListener(MazeCreationListener listener)
|
||||
{
|
||||
this.listener=listener;
|
||||
}
|
||||
|
||||
// entry and exit can be outside the model boundaries a one x or one y out.
|
||||
public boolean addEntryOrExit(int x, int y)
|
||||
{
|
||||
entryExits.add(new Position(x,y));
|
||||
if (( x > 0 ) && ( x < width ) && ( y > 0 ) && ( y < height ))
|
||||
{
|
||||
t[x][y] |= ENTRY;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void debugOut()
|
||||
{
|
||||
for (int y=0; y < height; y++)
|
||||
{
|
||||
for (int x=0; x < width; x++)
|
||||
{
|
||||
out4XY(x,y);
|
||||
}
|
||||
System.out.print('\n');
|
||||
}
|
||||
}
|
||||
|
||||
public void out4XY(int x,int y)
|
||||
{
|
||||
int direction=t[x][y];
|
||||
if ( ( direction & OPEN ) == OPEN )
|
||||
{
|
||||
System.out.print("?");
|
||||
}
|
||||
else if ( ( direction & CLOSED ) == CLOSED )
|
||||
{
|
||||
System.out.print(".");
|
||||
}
|
||||
else {
|
||||
System.out.print(" ");
|
||||
}
|
||||
// don't display information about short.
|
||||
direction &= ~OPEN;
|
||||
direction &= ~GOAL;
|
||||
direction &= ~CLOSED;
|
||||
switch(direction){
|
||||
case LEFT: // left
|
||||
System.out.print("<-");
|
||||
break;
|
||||
case DOWN: // down
|
||||
System.out.print("vv");
|
||||
break;
|
||||
case RIGHT: // right
|
||||
System.out.print("->");
|
||||
break;
|
||||
case UP: // up
|
||||
System.out.print("^^");
|
||||
break;
|
||||
case HORIZONTAL: // -
|
||||
System.out.print("--");
|
||||
break;
|
||||
case VERTICAL: // |
|
||||
System.out.print("||");
|
||||
break;
|
||||
case CLEAR:
|
||||
System.out.print(" ");
|
||||
break;
|
||||
case CLOSED:
|
||||
System.out.print("00");
|
||||
break;
|
||||
case RIGHT|LEFT:
|
||||
System.out.print("--");
|
||||
break;
|
||||
case UP|DOWN:
|
||||
System.out.print("||");
|
||||
break;
|
||||
case RIGHT|UP:
|
||||
System.out.print("^>");
|
||||
break;
|
||||
case RIGHT|DOWN:
|
||||
System.out.print("v>");
|
||||
break;
|
||||
case LEFT|DOWN:
|
||||
System.out.print("<v");
|
||||
break;
|
||||
case LEFT|UP:
|
||||
System.out.print("<^");
|
||||
break;
|
||||
case LEFT|RIGHT|UP:
|
||||
System.out.print("LL");
|
||||
break;
|
||||
case LEFT|RIGHT|DOWN:
|
||||
System.out.print("TT");
|
||||
break;
|
||||
case LEFT|DOWN|UP:
|
||||
System.out.print("<|");
|
||||
break;
|
||||
case RIGHT|DOWN|UP:
|
||||
System.out.print("|>");
|
||||
break;
|
||||
case LEFT|RIGHT|UP|DOWN:
|
||||
System.out.print("++");
|
||||
break;
|
||||
case OPEN:
|
||||
System.out.print("??");
|
||||
break;
|
||||
case GOAL:
|
||||
System.out.print("**");
|
||||
break;
|
||||
default:
|
||||
System.out.print("..");
|
||||
}
|
||||
|
||||
if ( ( (t[x][y] & RIGHT) == RIGHT ) ||
|
||||
( ( x+ 1 < width) && ( ( t[x+1][y] & LEFT ) == LEFT ) ))
|
||||
{
|
||||
System.out.print("-");
|
||||
}
|
||||
else
|
||||
{
|
||||
System.out.print("H");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String outHorizWall2XY(int x, int y)
|
||||
{
|
||||
String freeway= " ";
|
||||
if ( (t[x][y] & SOLVED) == SOLVED)
|
||||
{
|
||||
freeway="*";
|
||||
}
|
||||
if ( ( x < 0 ) || ( x >width ) )
|
||||
{
|
||||
return " H";
|
||||
}
|
||||
if ( ( y < 0 ) || ( y >= height ) )
|
||||
{
|
||||
return "HH";
|
||||
}
|
||||
|
||||
if ( ( (t[x][y] & DOWN) == DOWN ) || (( y+ 1 < height) && ( ( t[x][y+1] & UP ) == UP )))
|
||||
{
|
||||
return freeway + "H";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "HH";
|
||||
}
|
||||
}
|
||||
|
||||
public String out2XY(int x,int y)
|
||||
{
|
||||
// can check for entry exits.
|
||||
|
||||
if ( ( y < 0 ) || ( y >= height ) || ( x < 0 ) || ( x >width ) )
|
||||
{
|
||||
return " H";
|
||||
}
|
||||
String low="";
|
||||
int direction=t[x][y];
|
||||
String freeway= " ";
|
||||
if ( (t[x][y] & SOLVED) == SOLVED)
|
||||
{
|
||||
freeway="*";
|
||||
}
|
||||
// don't display information about short.
|
||||
direction &= ~OPEN;
|
||||
direction &= ~GOAL;
|
||||
direction &= ~CLOSED;
|
||||
direction &= ~SOLVED;
|
||||
switch(direction){
|
||||
case LEFT:
|
||||
case DOWN:
|
||||
case RIGHT:
|
||||
case UP:
|
||||
low=freeway;
|
||||
break;
|
||||
case HORIZONTAL: // -
|
||||
low=" ";
|
||||
break;
|
||||
case VERTICAL: // |
|
||||
low=" ";
|
||||
break;
|
||||
case CLEAR:
|
||||
low=" ";
|
||||
break;
|
||||
case CLOSED:
|
||||
low="0";
|
||||
break;
|
||||
case RIGHT|LEFT:
|
||||
case UP|DOWN:
|
||||
case RIGHT|UP:
|
||||
case RIGHT|DOWN:
|
||||
case LEFT|DOWN:
|
||||
case LEFT|UP:
|
||||
case LEFT|RIGHT|UP:
|
||||
case LEFT|RIGHT|DOWN:
|
||||
case LEFT|DOWN|UP:
|
||||
case RIGHT|DOWN|UP:
|
||||
case LEFT|RIGHT|UP|DOWN:
|
||||
low=".";
|
||||
break;
|
||||
case OPEN:
|
||||
low="?";
|
||||
break;
|
||||
case GOAL:
|
||||
low="*";
|
||||
break;
|
||||
default:
|
||||
low=".";
|
||||
}
|
||||
|
||||
|
||||
for ( Position exit: entryExits )
|
||||
{
|
||||
if ( ( exit.getX() == x + 1 ) && ( exit.getY() == y ))
|
||||
{
|
||||
low=low+">";
|
||||
return low;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( (t[x][y] & RIGHT) == RIGHT ) ||
|
||||
( ( x+ 1 < width) && ( ( t[x+1][y] & LEFT ) == LEFT ) ))
|
||||
{
|
||||
low=low+freeway;
|
||||
}
|
||||
else
|
||||
{
|
||||
low=low+"H";
|
||||
}
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
public LabyMap toLabyMap()
|
||||
{
|
||||
synchronized (coherentLock)
|
||||
{
|
||||
Brick[][] brickMap = new Brick[width][height];
|
||||
for (int y=0; y< height; y++)
|
||||
{
|
||||
for ( int x=0; x < width; x++)
|
||||
{
|
||||
brickMap[x][y]=new Brick(out2XY(x,y), outHorizWall2XY(x, y),getWalls(x,y));
|
||||
}
|
||||
}
|
||||
return new LabyMap(brickMap, (LinkedList<Position>) entryExits.clone());
|
||||
}
|
||||
}
|
||||
|
||||
public int getWidth(){
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight(){
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public LinkedList<Position> getOpenList()
|
||||
{
|
||||
return openList;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
depth = 0;
|
||||
computeOpenList();
|
||||
}
|
||||
|
||||
public void fullReset()
|
||||
{
|
||||
depth = 0;
|
||||
openList.clear();
|
||||
maxreached = false;
|
||||
deepest=0;
|
||||
deepestEnd=null;
|
||||
// clear open
|
||||
for (int y=0; y < height; y++)
|
||||
{
|
||||
for (int x=0; x < width; x++)
|
||||
{
|
||||
t[x][y] &= ~OPEN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
check model coherency and fix
|
||||
if model needed a fix it means that algorithm has a problem
|
||||
|
||||
@return true if model is ok and no fix was applied.
|
||||
**/
|
||||
public boolean check()
|
||||
{
|
||||
boolean check = true;
|
||||
synchronized(coherentLock)
|
||||
{
|
||||
// node in OPEN should be tagged OPEN and not CLOSED.
|
||||
for ( Position p : openList)
|
||||
{
|
||||
int x = p.getX();
|
||||
int y = p.getY();
|
||||
if ( (t[x][y] & OPEN ) != OPEN )
|
||||
{
|
||||
check = false;
|
||||
t[x][y] |= OPEN;
|
||||
}
|
||||
if ( (t[x][y] & CLOSED ) == CLOSED )
|
||||
{
|
||||
check = false;
|
||||
t[x][y] &= ~CLOSED;
|
||||
}
|
||||
}
|
||||
// should do reverse : every node tagged OPEN should be in open list.
|
||||
// a little more cpu consuming...
|
||||
}
|
||||
return check;
|
||||
}
|
||||
|
||||
public void computeOpenList()
|
||||
{
|
||||
openList.clear();
|
||||
for (int y=0; y < height; y++)
|
||||
{
|
||||
for (int x=0; x < width; x++)
|
||||
{
|
||||
if ( (t[x][y] & CLOSED ) == CLOSED )
|
||||
{
|
||||
t[x][y] &= ~OPEN;
|
||||
}
|
||||
if ( ( (t[x][y] & OPEN) == OPEN ) || ( t[x][y] == CLEAR ))
|
||||
{
|
||||
openList.add(new Position(x,y));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void generateWithEntry(int x, int y){
|
||||
|
||||
openList.add(new Position(x,y));
|
||||
while ( ! openList.isEmpty() )
|
||||
{
|
||||
step(0); // fixme depth not set
|
||||
|
||||
synchronized(coherentLock)
|
||||
{
|
||||
linearwork ++;
|
||||
|
||||
if ( linearwork % maxdepth == 0 )
|
||||
{
|
||||
coherentLock.notifyAll();
|
||||
if (listener != null)
|
||||
{
|
||||
listener.changed(null,null,this);
|
||||
}
|
||||
// should not continue in depth first...
|
||||
if ( ! openList.isEmpty() )
|
||||
{
|
||||
// insert head as next position to pick up.
|
||||
Position current = openList.removeFirst();
|
||||
openList.add(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( deepestEnd != null )
|
||||
{
|
||||
t[deepestEnd.getX()][deepestEnd.getY()]|=GOAL;
|
||||
}
|
||||
}
|
||||
|
||||
public int getDepth()
|
||||
{
|
||||
return depth;
|
||||
}
|
||||
|
||||
public Position getDeepestEnd()
|
||||
{
|
||||
return deepestEnd;
|
||||
}
|
||||
|
||||
public int getDeepestPath()
|
||||
{
|
||||
return deepest;
|
||||
}
|
||||
|
||||
public boolean maxReached()
|
||||
{
|
||||
return maxreached;
|
||||
}
|
||||
|
||||
/**
|
||||
@param p Position
|
||||
@return true if newly added , false if already open.
|
||||
**/
|
||||
private boolean open(boolean first, Position p)
|
||||
{
|
||||
int x = p.getX();
|
||||
int y = p.getY();
|
||||
if ( ( t[x][y] & OPEN ) != OPEN )
|
||||
{
|
||||
t[x][y]|=OPEN;
|
||||
openList.addLast(p);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
resolve this labrynth using internal representation
|
||||
**/
|
||||
public LinkedList<Position> resolve(int x, int y, MazeResolutionListener rlistener)
|
||||
{
|
||||
int newx=x;
|
||||
int newy=y;
|
||||
LinkedList<Position> backpath = new LinkedList<Position>();
|
||||
|
||||
while ( ! (( newx == 0 ) && ( newy == 0 )))
|
||||
{
|
||||
Position found=null;
|
||||
x = newx;
|
||||
y = newy;
|
||||
backpath.addFirst( new Position(x,y));
|
||||
|
||||
// should find from all direction one that point to this.
|
||||
ArrayList<Short> freeDirection = new ArrayList<Short>();
|
||||
|
||||
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 & 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;
|
||||
}
|
||||
|
||||
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 !");
|
||||
break;
|
||||
}
|
||||
// System.out.println(found);
|
||||
newx=found.getX();
|
||||
newy=found.getY();
|
||||
t[newx][newy] |= SOLVED;
|
||||
}
|
||||
if (rlistener != null)
|
||||
{
|
||||
rlistener.notifyCompletion(backpath);
|
||||
}
|
||||
return backpath;
|
||||
}
|
||||
|
||||
/**
|
||||
@returns wheter process closed current node.
|
||||
**/
|
||||
public boolean step(int depth)
|
||||
{
|
||||
boolean complete = false;
|
||||
Position current = null;
|
||||
|
||||
synchronized(coherentLock)
|
||||
{
|
||||
|
||||
if ( ! openList.isEmpty() )
|
||||
{
|
||||
// last : in depth before.
|
||||
current = openList.getLast();
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( current != null )
|
||||
{
|
||||
int x = current.getX();
|
||||
int y = current.getY();
|
||||
|
||||
// should find all free positions...
|
||||
ArrayList<Short> freeDirection = new ArrayList<Short>();
|
||||
|
||||
for (short direction : AllDirections ) {
|
||||
int delta=0;
|
||||
int newx = -1;
|
||||
int newy = -1;
|
||||
|
||||
if ( ( direction & POSITIVE ) == POSITIVE ) { delta = 1; }
|
||||
else { delta = -1; }
|
||||
|
||||
if ( ( direction & HORIZONTAL ) == HORIZONTAL ) { newx = x + delta; newy = y; }
|
||||
else { newy = y + delta; newx = x; }
|
||||
|
||||
if ( (newx >= 0) && ( newy >= 0 ) && (newx < width) && (newy < height) ) {
|
||||
if( (t[newx][newy] ) == CLEAR){
|
||||
freeDirection.add(new Short(direction));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! freeDirection.isEmpty())
|
||||
{
|
||||
// control random using our own pseudorandom
|
||||
short direction = 0;
|
||||
if ( freeDirection.size() > 1 )
|
||||
{
|
||||
direction=freeDirection.get(random.nextInt(freeDirection.size()));
|
||||
}
|
||||
else
|
||||
{
|
||||
direction=freeDirection.get(0);
|
||||
Position last=openList.removeLast();
|
||||
if ( last != current )
|
||||
{
|
||||
// GUARD, should not happen ( or multi-thread access to model error )
|
||||
System.err.println("INTERNAL ERROR 3");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int delta=0;
|
||||
int newx = -1;
|
||||
int newy = -1;
|
||||
|
||||
if ( ( direction & POSITIVE ) == POSITIVE ) { delta = 1; }
|
||||
else { delta = -1; }
|
||||
|
||||
if ( ( direction & HORIZONTAL ) == HORIZONTAL ) { newx = x + delta; newy = y; }
|
||||
else { newy = y + delta; newx = x; }
|
||||
|
||||
Position target = new Position(newx,newy,current.getDepth()+1);
|
||||
open(false,target);
|
||||
if (( t[x][y] & DIRECTION ) == DIRECTION ) { t[x][y] |= direction; }
|
||||
else { t[x][y] = direction; } // not a 'direction' ... is it necessary to check ?
|
||||
if ( freeDirection.size() > 1 )
|
||||
{
|
||||
// keep it open at the very same place, previous open did add another node to inspect.
|
||||
return false;
|
||||
}
|
||||
// else this was the unique direction , object already removed ( since if we try to remove it now it is not the last )
|
||||
|
||||
// can proceed to close
|
||||
}
|
||||
else {
|
||||
// no free direction remaining => closing
|
||||
Position last=openList.removeLast();
|
||||
if ( last != current )
|
||||
{
|
||||
// GUARD, should not happen.
|
||||
System.err.println("INTERNAL ERROR 3");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
complete = true;
|
||||
t[x][y]&=~OPEN;
|
||||
t[x][y]|=CLOSED;
|
||||
if ( current.getDepth() > deepest )
|
||||
{
|
||||
deepest = depth;
|
||||
deepestEnd = current;
|
||||
}
|
||||
} // current != null;
|
||||
} // synchronized
|
||||
return complete;
|
||||
}
|
||||
|
||||
public short getWalls(int x, int y)
|
||||
{
|
||||
short walls=0;
|
||||
for (short direction: AllDirections)
|
||||
{
|
||||
if (hasWallInDirection(x,y,direction))
|
||||
{
|
||||
walls |= (direction>>FLAGLENGTH);
|
||||
}
|
||||
}
|
||||
return walls;
|
||||
}
|
||||
|
||||
/** is there a wall in that direction ?
|
||||
**/
|
||||
public boolean hasWallInDirection(int x, int y, short direction)
|
||||
{
|
||||
int newx=0;
|
||||
int newy=0;
|
||||
int delta=0;
|
||||
// best way to find reversedirection ?
|
||||
int reversedirection=0;
|
||||
|
||||
// is this direction on the path ? yes => no wall
|
||||
if ( ( t[x][y] & direction ) == direction )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// is adjacent tile in direction pointing in reverse direction ? yes => no wall
|
||||
if ( ( direction & POSITIVE ) == POSITIVE ) { delta = 1; }
|
||||
else { delta = -1; }
|
||||
|
||||
if ( ( direction & HORIZONTAL ) == HORIZONTAL ) {
|
||||
newx = x + delta;
|
||||
newy = y;
|
||||
reversedirection = (direction == RIGHT) ? LEFT : RIGHT;
|
||||
}
|
||||
else {
|
||||
newy = y + delta;
|
||||
newx = x;
|
||||
reversedirection = (direction == UP) ? DOWN : UP;
|
||||
}
|
||||
|
||||
if ( (newx >= 0) && ( newy >= 0 ) && (newx < width) && (newy < height) ) {
|
||||
return ( (t[newx][newy]&reversedirection) != reversedirection );
|
||||
}
|
||||
else {
|
||||
// outside boundaries.
|
||||
// TODO CHECK exits.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void streamOut( String pFormat, OutputStream pOut)
|
||||
throws IOException
|
||||
{
|
||||
if ((pFormat == null ) || (pFormat.equals("raw")))
|
||||
{
|
||||
// first raw format, not smart.
|
||||
DataOutputStream dataOut = new DataOutputStream(pOut);
|
||||
// should dump this to stream.
|
||||
dataOut.write( new byte[] { (byte) 'L', (byte) 'A', (byte) 'B', (byte) '0' });
|
||||
dataOut.writeInt(getWidth());
|
||||
dataOut.writeInt(getHeight());
|
||||
dataOut.flush();
|
||||
for (int y = 0; y < getHeight(); y++)
|
||||
{
|
||||
for (int x = 0 ; x < getWidth() ; x++)
|
||||
{
|
||||
dataOut.writeShort(t[x][y]);
|
||||
}
|
||||
}
|
||||
dataOut.flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Format " + pFormat + " Not yet implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
private void streamIn( String pFormat, InputStream pIn)
|
||||
throws IOException
|
||||
{
|
||||
throw new IOException("Use correct constructor.");
|
||||
}
|
||||
|
||||
private void parseInputStream( String pFormat, InputStream pIn)
|
||||
throws IOException
|
||||
{
|
||||
if (( pFormat == null) || ( pFormat.equals("raw") ))
|
||||
{
|
||||
byte[] header = new byte[4];
|
||||
DataInputStream in = new DataInputStream(pIn);
|
||||
in.read(header);
|
||||
int rwidth = in.readInt();
|
||||
int rheight = in.readInt();
|
||||
width=rwidth;
|
||||
height=rheight;
|
||||
maxdepth=maxdepth;
|
||||
random = null;
|
||||
// SHOULD CHECK max width and max height...
|
||||
// CLEAR == 0 and array is initialized with 0s
|
||||
t= new short[width][height];
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
for (int x = 0 ; x < width ; x++)
|
||||
{
|
||||
t[x][y] = in.readShort();
|
||||
}
|
||||
}
|
||||
// should be at end of stream ? Not necessary can stream multiple labs ( or tiling ).
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IOException("Format " + pFormat + " Not yet implemented.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
59
java/org/artisanlogiciel/games/Main.java
Normal file
59
java/org/artisanlogiciel/games/Main.java
Normal file
@@ -0,0 +1,59 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class Main
|
||||
{
|
||||
|
||||
public WallsProvider generate(int width,int height, int maxdepth, MazeListener listener)
|
||||
{
|
||||
LabyModel model = new LabyModel(width, height,maxdepth, new java.util.Random());
|
||||
if ( listener != null )
|
||||
{
|
||||
model.setListener(listener);
|
||||
}
|
||||
model.generateWithEntry(0, 0);
|
||||
LinkedList<Position> exits = new LinkedList<Position>();
|
||||
model.addEntryOrExit(-1,0);
|
||||
model.addEntryOrExit(width,height -1);
|
||||
if ( ! model.check() )
|
||||
{
|
||||
System.out.println("Check failed");
|
||||
}
|
||||
model.resolve(width-1,height-1);
|
||||
return model;
|
||||
}
|
||||
|
||||
public LabyMap generate2(int width,int height, int maxdepth)
|
||||
{
|
||||
LabyModel model = new LabyModel(width, height,maxdepth, new java.util.Random( 1024L));
|
||||
model.generateWithEntry(0, 0);
|
||||
LinkedList<Position> exits = new LinkedList<Position>();
|
||||
model.addEntryOrExit(-1,0);
|
||||
model.addEntryOrExit(width,height -1);
|
||||
System.out.println(model.toLabyMap().toString());
|
||||
if ( ! model.check() )
|
||||
{
|
||||
System.out.println("Check failed");
|
||||
}
|
||||
model.debugOut();
|
||||
model.resolve(width-1,height-1);
|
||||
LabyMap labyMap =model.toLabyMap();
|
||||
return labyMap;
|
||||
}
|
||||
|
||||
public static void main(String pArgs[])
|
||||
{
|
||||
System.out.println("enter width height and maxdepth");
|
||||
Scanner console = new Scanner(System.in);
|
||||
int width = console.nextInt();
|
||||
int height = console.nextInt();
|
||||
int maxdepth = console.nextInt();
|
||||
Main m= new Main();
|
||||
LabyMap map = m.generate2(width,height,maxdepth);
|
||||
System.out.println(map.toShortString());
|
||||
System.out.println(map.toString());
|
||||
System.out.println(Brick.getDirLine());
|
||||
}
|
||||
}
|
||||
9
java/org/artisanlogiciel/games/MazeCreationListener.java
Normal file
9
java/org/artisanlogiciel/games/MazeCreationListener.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
/**
|
||||
MazeCreationListener
|
||||
**/
|
||||
interface MazeCreationListener
|
||||
{
|
||||
void changed(Position cornerleft, Position cornerright, WallsProvider provider);
|
||||
}
|
||||
17
java/org/artisanlogiciel/games/MazeResolutionListener.java
Normal file
17
java/org/artisanlogiciel/games/MazeResolutionListener.java
Normal file
@@ -0,0 +1,17 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
MazeResolutionListener used as interface between resolver and (mostly) GUI
|
||||
**/
|
||||
public interface MazeResolutionListener
|
||||
{
|
||||
|
||||
public boolean notifySearch(Position pPosition);
|
||||
|
||||
public void notifySearchError(String error);
|
||||
|
||||
public void notifyCompletion(LinkedList<Position> solvedPath);
|
||||
|
||||
}
|
||||
38
java/org/artisanlogiciel/games/Position.java
Normal file
38
java/org/artisanlogiciel/games/Position.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
public class Position {
|
||||
private int x, y;
|
||||
private int depth;
|
||||
|
||||
public Position(int x, int y,int depth){
|
||||
this.x=x;
|
||||
this.y=y;
|
||||
this.depth=depth;
|
||||
}
|
||||
|
||||
public Position(int x, int y){
|
||||
this.x=x;
|
||||
this.y=y;
|
||||
this.depth=0;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public int getDepth()
|
||||
{
|
||||
return depth;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "(" + x + "," + y + ")" + "/" + depth ;
|
||||
}
|
||||
}
|
||||
220
java/org/artisanlogiciel/games/Wall3d.java
Normal file
220
java/org/artisanlogiciel/games/Wall3d.java
Normal file
@@ -0,0 +1,220 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
import java.util.Scanner;
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
Wall3d to create walls in 3d
|
||||
South, West North East...
|
||||
**/
|
||||
public class Wall3d
|
||||
{
|
||||
// 4 triangles in 2 dim space reused 3 times
|
||||
final static int BASE[][][] = {{{0,0},{1,0},{0,1}},{{1,0},{1,1},{0,1}},{{0,0},{1,0},{1,1}},{{0,0},{1,1},{0,1}}};
|
||||
|
||||
final static short X=1;
|
||||
final static short Y=2;
|
||||
final static short Z=4;
|
||||
|
||||
// final static short AXIS[][]= {{X,Y},{-Z,Y},{X,Y},{Z,Y},{X,-Z},{X,-Z}};
|
||||
final static short AXIS[][]= {{X,Y,0},{Z,Y,0},{X,Y,1},{Z,Y,1},{X,Z,0},{X,Z,1}};
|
||||
|
||||
public final static Wall3d South = new Wall3d(10,1,10,0,0,0);
|
||||
public final static Wall3d West = new Wall3d(1,10,10,0,0,0);
|
||||
public final static Wall3d North = new Wall3d(10,1,10,0,10,0);
|
||||
public final static Wall3d East = new Wall3d(1,10,10,10,0,0);
|
||||
|
||||
int triangle[][][] = null;
|
||||
|
||||
public Wall3d(int t[][][])
|
||||
{
|
||||
triangle = t;
|
||||
}
|
||||
|
||||
public Wall3d(Wall3d origin, int dx, int dy, int dz)
|
||||
{
|
||||
triangle=origin.translate(dx,dy,dz);
|
||||
}
|
||||
|
||||
Wall3d(int xl, int yl, int zl, int dx, int dy, int dz)
|
||||
{
|
||||
int f=0;
|
||||
triangle = new int[12][3][3];
|
||||
int[] factor = {xl,yl,zl};
|
||||
int[] translate = {dx,dy,dz};
|
||||
for (int i=0; i < 12; i++)
|
||||
{
|
||||
// point in a triangle
|
||||
for (int p=0; p<3; p++)
|
||||
{
|
||||
short uaxis=0;
|
||||
for (int axis=0; axis <2; axis++)
|
||||
{
|
||||
short caxis = AXIS[i/2][axis];
|
||||
if ( caxis >0 )
|
||||
{
|
||||
f=1;
|
||||
}
|
||||
else
|
||||
if ( caxis <0 )
|
||||
{
|
||||
f=-1;
|
||||
caxis=(short) -caxis;
|
||||
}
|
||||
uaxis|=caxis;
|
||||
if ( caxis == X )
|
||||
{
|
||||
caxis=0;
|
||||
}
|
||||
else if ( caxis == Y)
|
||||
{
|
||||
caxis=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
caxis=2;
|
||||
}
|
||||
// if ( f == 0 )
|
||||
// {
|
||||
// System.out.println("ERROR");
|
||||
// }
|
||||
//System.out.println("i " + i + " p " + p + " a " + caxis + " , " + BASE[i%4][p][axis] );
|
||||
triangle[i][p][caxis]=translate[caxis] + BASE[i%4][p][axis]*f*factor[caxis];
|
||||
}
|
||||
if ( (uaxis & X) == 0 )
|
||||
{
|
||||
uaxis=0;
|
||||
}
|
||||
else if ( (uaxis & Y) == 0)
|
||||
{
|
||||
uaxis=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
uaxis=2;
|
||||
}
|
||||
triangle[i][p][uaxis]=translate[uaxis] + AXIS[i/2][2]*factor[uaxis];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int[][][] translate(int dx, int dy, int dz)
|
||||
{
|
||||
int[] translate = {dx,dy,dz};
|
||||
int t[][][] = new int[12][3][3];
|
||||
|
||||
for (int i=0; i < 12; i++)
|
||||
{
|
||||
// point in a triangle
|
||||
for (int p=0; p<3; p++)
|
||||
{
|
||||
for (int axis=0; axis <3; axis++)
|
||||
{
|
||||
t[i][p][axis]=translate[axis] + triangle[i][p][axis];
|
||||
}
|
||||
}
|
||||
}
|
||||
return t;
|
||||
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
for (int t=0; t<12; t++)
|
||||
{
|
||||
s+="facet normal 0 0 0\nouter loop\n";
|
||||
for (int p=0; p<3; p++)
|
||||
{
|
||||
s+="vertex";
|
||||
for (int a=0; a<3; a++)
|
||||
{
|
||||
// s+=" t "+ t + " p " + p + " a " + a + "=" + triangle[t][p][a];
|
||||
s+= " " + triangle[t][p][a];
|
||||
}
|
||||
s+="\n";
|
||||
}
|
||||
s=s+"endloop\nendfacet\n";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public static void prepare()
|
||||
{
|
||||
System.out.println(South.toString());
|
||||
System.out.println(East.toString());
|
||||
System.out.println(North.toString());
|
||||
System.out.println(West.toString());
|
||||
}
|
||||
|
||||
public static void streamWallsOut(String name, WallsProvider provider, OutputStream stream)
|
||||
throws IOException
|
||||
{
|
||||
int width = provider.getWidth();
|
||||
int height = provider.getHeight();
|
||||
int xl = 10;
|
||||
int yl = 10;
|
||||
int zl = 10;
|
||||
|
||||
// WARNING DOWN - UP reversed ( in 2D Y is oriented to lower, in 3D it is to upper ).
|
||||
stream.write(("solid " + name + "\n").getBytes());
|
||||
for (int x=0; x<width; x++)
|
||||
{
|
||||
short walls = provider.getWalls(x,0);
|
||||
if ( (walls & Brick.UP) != 0 )
|
||||
{
|
||||
stream.write(new Wall3d(South,x*xl,0,0).toString().getBytes());
|
||||
}
|
||||
if ( (walls & Brick.LEFT) != 0 )
|
||||
{
|
||||
stream.write(new Wall3d(West,x*xl,0,0).toString().getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
for (int y=0; y<height; y++)
|
||||
{
|
||||
short walls = provider.getWalls(0,y);
|
||||
if ( (walls & Brick.LEFT) != 0 )
|
||||
{
|
||||
stream.write(new Wall3d(West,0,y*yl,0).toString().getBytes());
|
||||
}
|
||||
for (int x=0; x<width; x++)
|
||||
{
|
||||
// south and east
|
||||
walls = provider.getWalls(x,y);
|
||||
if ( (walls & Brick.DOWN) != 0 )
|
||||
{
|
||||
stream.write(new Wall3d(North,x*xl,y*yl,0).toString().getBytes());
|
||||
}
|
||||
if ( (walls & Brick.RIGHT) != 0)
|
||||
{
|
||||
stream.write(new Wall3d(East,x*xl,y*yl,0).toString().getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
stream.write("endsolid wall\n\n".getBytes());
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
|
||||
Scanner console = new Scanner(System.in);
|
||||
int xl = console.nextInt();
|
||||
int yl = console.nextInt();
|
||||
int zl = console.nextInt();
|
||||
|
||||
int dx = console.nextInt();
|
||||
int dy = console.nextInt();
|
||||
int dz = console.nextInt();
|
||||
|
||||
String s="solid wall\n";
|
||||
|
||||
Wall3d instance=new Wall3d(xl,yl,zl, dx,dy,dz);
|
||||
|
||||
prepare();
|
||||
|
||||
s+="endsolid wall\n\n";
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
27
java/org/artisanlogiciel/games/WallsProvider.java
Normal file
27
java/org/artisanlogiciel/games/WallsProvider.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package org.artisanlogiciel.games;
|
||||
|
||||
/**
|
||||
WallsProvider provide a Walls representation
|
||||
**/
|
||||
public interface WallsProvider
|
||||
{
|
||||
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
|
||||
/**
|
||||
See Brick
|
||||
|
||||
Will set bits :
|
||||
3 2 1 0
|
||||
(8)(4)(2)(1)
|
||||
^ > v <
|
||||
U R D L
|
||||
p i o e
|
||||
g w f
|
||||
h n t
|
||||
t
|
||||
**/
|
||||
public short getWalls(int x, int y);
|
||||
}
|
||||
Reference in New Issue
Block a user