Welcome to HBH! If you have tried to register and didn't get a verification email, please using the following link to resend the verification email.
Tents puzzle solver - Java Code Bank
Tents puzzle solver
This program solves a so-called 'tents puzzle' using backtracking.
/***************
Main.java
***************/
package hbhtentspuzzle;
import java.io.IOException;
/**
* Welcome to my Java program to solve a classic "tents puzzle". I suppose you Google it if you don't know what it is. The program reads the puzzles from files and uses a backtracking algorithm to solve them. Everything is JavaDoc'ed extensively, merely out of a habit.
* @author GTADarkDude
*/
public class Main
{
/**
* Main method that loads a couple of puzzle files and calls placeTents to solve them.
* @param args Command line arguments (unused)
*/
public static void main(String[] args)
{
String cs [] = {"c1.txt", "c2.txt", "c3.txt"};
for(String s : cs)
{
try
{
CampSite c = new CampSite(s, false);
System.out.println(s + ":");
System.out.println(c);
c.placeTents();
}
catch(IOException ioe)
{
System.out.println("Oops, something went wrong while trying to read "
+ s + ": " + ioe.getMessage() );
}
}
}
}
/***************
Field.java
***************/
package hbhtentspuzzle;
/**
* Enumeration for the possible values of a single field on the campsite.
* @author GTADarkDude
*/
public enum Field
{
Tent, Tree, Grass;
@Override
public String toString()
{
switch (this)
{
case Tent: return "X";
case Tree: return "T";
case Grass: return ".";
default: return "";
}
}
}
/***************
CampSite.java
***************/
package hbhtentspuzzle;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
/**
* Representation of the campsite.
* @author GTADarkDude
*/
public class CampSite
{
private final boolean allSolutions;
private final int width, length;
private Field[][] grid;
private int[] numberH, numberV;
private boolean solved;
/**
* Constructor reads camping from given file. See the example files for the required format.
* @param fileName The name of the file to be read from.
* @param allSolutions True if you want all solutions, false if you think that one solution is sufficient.
* @throws java.io.IOException
*/
public CampSite(String fileName, boolean all) throws IOException
{
allSolutions = all;
solved = false;
FileReader file = new FileReader(fileName);
Scanner scan = new Scanner(file);
length = scan.nextInt();
width = scan.nextInt();
scan.nextLine();
grid = new Field[width][length];
numberV = new int[width];
numberH = new int[length];
for(int i = 0; i < length; ++i)
{
String line = scan.nextLine();
if(line.length() <= width)
throw new IOException ("Line " + i + " is too short.");
for(int j = 0; j < width; ++j)
switch(line.charAt(j))
{
case 'T': grid[j][i] = Field.Tree; break;
default: grid[j][i] = Field.Grass;
}
numberH[i] = Character.digit(line.charAt(width), 10);
}
String line = scan.nextLine();
if(line.length() < width)
throw new IOException("Last line is too short.");
for(int j = 0; j < width; ++j)
numberV[j] = Character.digit(line.charAt(j), 10);
file.close();
}
/**
* Extra constructor where allSolutions is defaulted to false.
* @param fileName The name of the file to be read from.
* @throws java.io.IOException
*/
public CampSite(String fileName) throws IOException
{
this(fileName, false);
}
/**
* Produces a multi-line string describing the CampSite
* @return the string
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
for(int i = 0; i < length; ++i)
{
for(int j = 0; j < width; ++j)
builder.append(grid[j][i]);
builder.append(numberH[i]).append("\n");
}
for(int j = 0; j < width; ++j)
builder.append(numberV[j]);
builder.append("\n");
return builder.toString();
}
/**
* Predicate to verify that a given position actually exists.
* @param x
* @param y
* @return True if the position lies within the CampSite.
*/
private boolean onCampSite(int x, int y)
{
return 0 <= x && x < width && 0 <= y && y < length;
}
/**
* Predicate to check if a given position lies next to a tree and is valid.
* @param x
* @param y
* @return True if the position lies within the CampSite and it lies next to a tree.
*/
private boolean nextToTree(int x, int y)
{
if(onCampSite(x + 1, y) && grid[x + 1][y] == Field.Tree)
return true;
if(onCampSite(x - 1, y) && grid[x - 1][y] == Field.Tree)
return true;
if(onCampSite(x, y + 1) && grid[x][y + 1] == Field.Tree)
return true;
if(onCampSite(x, y - 1) && grid[x][y - 1] == Field.Tree)
return true;
return false;
}
/**
* Predicate to check if there any tents next to a given position.
* @param x
* @param y
* @return True is the position doesn't have any adjacent tents.
*/
private boolean noNeighbours(int x, int y)
{
for(int i = y - 1; i <= y + 1; ++i)
for(int j = x - 1; j <= x + 1; ++j)
if(onCampSite(j, i) && grid[j][i] == Field.Tent && j != i)
return false;
return true;
}
/**
* Method that places the tents on the CampSite.
*/
public void placeTents()
{
placeTents(0, 0);
}
/**
* The real backtracking algorithm that solves the puzzle.
* @param x
* @param y
*/
private void placeTents(int x, int y)
{
if(solved && !allSolutions)
return;
if(done())
{
System.out.println("Found a solution!\n" + this.toString());
solved = true;
}
else if(!onCampSite(x, y))
{
if(x > width)
placeTents(0, y + 1);
}
else
{
final int xNext = (x + 1) % width;
final int yNext = y + (xNext == 0 ? 1 : 0);
if(nextToTree(x, y) && noNeighbours(x, y) && grid[x][y] == Field.Grass && numberH[y] > 0 && numberV[x] > 0)
{
grid[x][y] = Field.Tent;
--numberH[y];
--numberV[x];
placeTents(xNext, yNext);
grid[x][y] = Field.Grass;
++numberH[y];
++numberV[x];
}
placeTents(xNext, yNext);
}
}
/**
* Predicate to check if a certain solution is finished.
* @return True if all tents were placed.
*/
private boolean done()
{
for(int i : numberH)
if(i != 0)
return false;
for(int i : numberV)
if(i != 0)
return false;
return true;
}
}
/***************
c1.txt
***************/
5
5
..T..1
...T.1
...T.2
T...T0
..T..2
12102
/***************
c2.txt
***************/
10
10
..........2
T.T.T..T..2
..........2
.T.T......2
......T..T2
T...TT....3
..T.....T.0
...T....T.3
T....T.T..2
..T......T2
3231213032
/***************
c3.txt
***************/
7 14
.....T......T.4
.T...T..T...T.2
..............2
.T.TTT..T.TTT.4
..............2
....T......T..2
T......T......2
12112111211211
Comments
Sorry but there are no comments to display