import java.util.ArrayList;
import java.util.List;
enum Track {
ONE_HUMAN, TWO_HUMAN, ONE_HUMAN_ONE_GHOST, ONE_GHOST, TWO_GHOST, ERROR;
@Override
public String toString() {
return this.name();
}
public Track next() {
if (this.equals(ONE_HUMAN)) {
return TWO_HUMAN;
}
if (this.equals(TWO_HUMAN)) {
return ONE_HUMAN_ONE_GHOST;
}
if (this.equals(ONE_HUMAN_ONE_GHOST)) {
return ONE_GHOST;
}
if (this.equals(ONE_GHOST)) {
return TWO_GHOST;
}
if (this.equals(TWO_GHOST)) {
return ERROR;
}
return ERROR;
}
}
enum Direction {
GO, BACK;
@Override
public String toString() {
return this.name();
}
}
class History {
Track t = Track.ONE_HUMAN;
Direction d = Direction.BACK;
public static int COUNT = 3;
int srcHuman = COUNT;
int srcGhost = COUNT;
int aimHuman = 0;
int aimGhost = 0;
public static List history = new ArrayList();
public static List error_history = new ArrayList();
public static void init(int c) {
COUNT = c;
history.clear();
history.add(new History());
}
public History() {
}
public History(int sh, int sg, int ah, int ag) {
this.srcHuman = sh;
this.srcGhost = sg;
this.aimHuman = ah;
this.aimGhost = ag;
}
public History(int sh, int sg, int ah, int ag, Direction d, Track t) {
this.srcHuman = sh;
this.srcGhost = sg;
this.aimHuman = ah;
this.aimGhost = ag;
this.d = d;
this.t = t;
}
public History(int sh, int sg, int ah, int ag, Direction d) {
this.srcHuman = sh;
this.srcGhost = sg;
this.aimHuman = ah;
this.aimGhost = ag;
this.d = d;
}
@Override
public String toString() {
return t
+ (t.toString().length() > 10 ? "/t"
: t.toString().length() < 9 ? "/t/t/t" : "/t/t") + d
+ "/t/t" + srcHuman + "/t/t" + srcGhost + "/t/t" + aimHuman
+ "/t/t" + aimGhost;
}
private void printHistory() {
System.out.println("Track" + "/t/t/t" + "Direct" + "/t/t" + "srcHuman"
+ "/t" + "srcGhost" + "/t" + "aimHuman" + "/t" + "aimGhost");
int i = 0;
for (History h : history) {
if (i != 0)
System.out.println(h);
i++;
}
// System.out.println("********************");
//
// for (History h : error_history) {
// if (!(h.srcGhost == 3 && h.srcHuman == 3))
// System.out.println(h);
// }
}
@Override
public boolean equals(Object o) {
if (o instanceof History && o != null) {
History h = (History) o;
return h.srcHuman == srcHuman && h.srcGhost == srcGhost
&& h.aimGhost == aimGhost && h.aimHuman == aimHuman
&& h.d.equals(d);
}
return false;
}
private boolean checkRecercle(History h) {
return history.contains(h);
}
public void go(Track begin, Direction dir) {
if (srcHuman == 0 && srcGhost == 0) {
printHistory();
return;
}
d = dir;
Direction back = dir.equals(Direction.GO) ? Direction.BACK
: Direction.GO;
if (begin.equals(Track.ONE_HUMAN)) {
if (oneHuman(dir)) {
History h = new History(srcHuman, srcGhost, aimHuman, aimGhost,
dir, begin);
history.add(h);
error_history.add(h);
go(Track.ONE_HUMAN, back);
return;
}
begin = Track.TWO_HUMAN;
}
if (begin.equals(Track.TWO_HUMAN)) {
if (twoHuman(dir)) {
History h = new History(srcHuman, srcGhost, aimHuman, aimGhost,
dir, begin);
history.add(h);
error_history.add(h);
go(Track.ONE_HUMAN, back);
return;
}
begin = Track.ONE_HUMAN_ONE_GHOST;
}
if (begin.equals(Track.ONE_HUMAN_ONE_GHOST)) {
if (oneHumanOneGhost(dir)) {
History h = new History(srcHuman, srcGhost, aimHuman, aimGhost,
dir, begin);
history.add(h);
error_history.add(h);
go(Track.ONE_HUMAN, back);
return;
}
begin = Track.ONE_GHOST;
}
if (begin.equals(Track.ONE_GHOST)) {
if (oneGhost(dir)) {
History h = new History(srcHuman, srcGhost, aimHuman, aimGhost,
dir, begin);
history.add(h);
error_history.add(h);
go(Track.ONE_HUMAN, back);
return;
}
begin = Track.TWO_GHOST;
}
if (begin.equals(Track.TWO_GHOST)) {
if (twoGhost(dir)) {
History h = new History(srcHuman, srcGhost, aimHuman, aimGhost,
dir, begin);
history.add(h);
error_history.add(h);
go(Track.ONE_HUMAN, back);
return;
}
begin = Track.ERROR;
}
if (begin.equals(Track.ERROR)) {
revert();
}
}
private void renew(History h) {
this.d = h.d;
this.t = h.t;
this.srcGhost = h.srcGhost;
this.aimGhost = h.aimGhost;
this.srcHuman = h.srcHuman;
this.aimHuman = h.aimHuman;
}
private void revert() {
// error_history.add(history.get(history.size() - 1));
Track tb = history.get(history.size() - 1).t.next();
Direction db = history.get(history.size() - 1).d;
error_history.add(new History(history.get(history.size() - 1).srcHuman,
history.get(history.size() - 1).srcGhost, history.get(history
.size() - 1).aimHuman,
history.get(history.size() - 1).aimGhost, history.get(history
.size() - 1).d, Track.ERROR));
if (history.size() == 1) {
System.out.println("Failed, ");
return;
}
history.remove(history.size() - 1);
renew(history.get(history.size() - 1));
go(tb, db);
}
private boolean twoGhost(Direction d) {
switch (d) {
case GO:
if (srcGhost < 2) {
return false;
} else {
if (aimGhost + 2 > aimHuman && aimHuman > 0) {
return false;
} else {
if (checkRecercle(new History(srcHuman, srcGhost - 2,
aimHuman, aimGhost + 2, d))) {
return false;
}
srcGhost = srcGhost - 2;
aimGhost = aimGhost + 2;
return true;
}
}
case BACK:
if (aimGhost < 2) {
return false;
} else {
if (srcGhost + 2 > srcHuman && srcHuman > 0) {
return false;
} else {
if (checkRecercle(new History(srcHuman, srcGhost + 2,
aimHuman, aimGhost - 2, d))) {
return false;
}
srcGhost = srcGhost + 2;
aimGhost = aimGhost - 2;
return true;
}
}
}
return false;
}
private boolean oneGhost(Direction d) {
switch (d) {
case GO:
if (srcGhost < 1) {
return false;
} else {
if (aimGhost + 1 > aimHuman && aimHuman > 0) {
return false;
} else {
if (checkRecercle(new History(srcHuman, srcGhost - 1,
aimHuman, aimGhost + 1, d))) {
return false;
}
srcGhost--;
aimGhost++;
return true;
}
}
case BACK:
if (aimGhost < 1) {
return false;
} else {
if (srcGhost + 1 > srcHuman && srcHuman > 0) {
return false;
} else {
if (checkRecercle(new History(srcHuman, srcGhost + 1,
aimHuman, aimGhost - 1, d))) {
return false;
}
srcGhost++;
aimGhost--;
return true;
}
}
}
return false;
}
private boolean oneHumanOneGhost(Direction d) {
switch (d) {
case GO:
if (srcHuman < 1 || srcGhost < 1) {
return false;
} else {
if (aimHuman < aimGhost) {
return false;
}
if (checkRecercle(new History(srcHuman - 1, srcGhost - 1,
aimHuman + 1, aimGhost + 1, d))) {
return false;
}
srcHuman--;
srcGhost--;
aimHuman++;
aimGhost++;
return true;
}
case BACK:
if (aimHuman < 1 || aimGhost < 1) {
return false;
} else {
if (checkRecercle(new History(srcHuman + 1, srcGhost + 1,
aimHuman - 1, aimGhost - 1, d))) {
return false;
}
if (srcHuman < srcGhost) {
return false;
}
aimHuman--;
aimGhost--;
srcHuman++;
srcGhost++;
return true;
}
}
return false;
}
private boolean twoHuman(Direction d) {
switch (d) {
case GO:
if (srcHuman < 2) {
return false;
} else {
if (srcHuman - 2 < srcGhost && srcHuman - 2 > 0
|| (aimHuman + 2 < aimGhost)) {
return false;
} else {
if (checkRecercle(new History(srcHuman - 2, srcGhost,
aimHuman + 2, aimGhost, d))) {
return false;
}
srcHuman = srcHuman - 2;
aimHuman = aimHuman + 2;
return true;
}
}
case BACK:
if (aimHuman < 2) {
return false;
} else {
if (aimHuman - 2 < aimGhost && aimHuman - 2 > 0
|| (srcHuman + 2 < srcGhost)) {
return false;
} else {
if (checkRecercle(new History(srcHuman + 2, srcGhost,
aimHuman - 2, aimGhost, d))) {
return false;
}
srcHuman = srcHuman + 2;
aimHuman = aimHuman - 2;
return true;
}
}
}
return false;
}
private boolean oneHuman(Direction d) {
switch (d) {
case GO:
if (srcHuman < 1) {
return false;
} else {
if (srcHuman - 1 < srcGhost && srcHuman - 1 > 0
|| (aimHuman + 1 < aimGhost)) {
return false;
} else {
if (checkRecercle(new History(srcHuman - 1, srcGhost,
aimHuman + 1, aimGhost, d))) {
return false;
}
srcHuman--;
aimHuman++;
return true;
}
}
case BACK:
if (aimHuman < 1) {
return false;
} else {
if (aimHuman - 1 < aimGhost && aimHuman - 1 > 0
|| (srcHuman + 1 < srcGhost)) {
return false;
} else {
if (checkRecercle(new History(srcHuman + 1, srcGhost,
aimHuman - 1, aimGhost, d))) {
return false;
}
srcHuman++;
aimHuman--;
return true;
}
}
}
return false;
}
}
public class Demo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
History.init(6);
History h = new History();
h.go(Track.ONE_HUMAN, Direction.GO);
}
}