TapTap最近推荐的一款游戏《同一个世界》,感觉挺好玩的,就是有点难,尝试着写代码找个解决方案!
定义:
1(Point).一个点有true,false,null三种状态,每个点都有一个坐标;
2(OneWorld).一张图由一个二维数组组成;
3(OneWorld).当图中的点状态除null外,只有true或者false时,认为图是完美的(isPerfact);
4(OneStep).图从起点开始行走,走一步,形成一张新的图和行走的路径steps;
解决方案:(递归)
图从起点开始走一步,判断图是否完美(isPerfact);如果完美返回当前的路径(OneStep),否则接着走下一步;直到perfact或者不能走下一步!
ps:能用,但是效率感人!!!(代码中的测试用例,在调用i5 25%的cpu,700M的内存,跑了700秒!);
pps:欢迎交流!
Point.java
/**
* 每个点都有一个值,默认为null;<br>
* 每个点都有一个坐标,默认为[0,0]
*/
public class Point {
// 对于一个点:有ture,false null 三种状态
// null表示不存在
private Boolean value = null;
// 每一个点都有一个坐标
private int x = 0;
private int y = 0;
public Point() {
}
public Point(Boolean value) {
this.value = value;
}
public Point(Boolean value, int x, int y) {
super();
this.value = value;
this.x = x;
this.y = y;
}
public Point copy() {
return new Point(this.value, this.x, this.y);
}
// 改变值;
public Boolean changeValue() {
value = value == null ? null : !value;
return value;
}
public Boolean getValue() {
return value;
}
public void setValue(Boolean value) {
this.value = value;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}
OneWorld.java
package world;
import java.util.ArrayList;
import java.util.List;
/**
* 特性从起点的顺序和走的步骤无关,每一个起点走的步骤固定;每个步骤没有先后联系
*/
public class OneWorld {
private Point[][] oneWorld;
private Point[] start;
private int num = Constant.X * Constant.Y;// 点的值为非null的数据,默认为全部
private int trueNum = 0;// 点中值为true的数目
public int getTrueNum() {
return trueNum;
}
public int getNum() {
return num;
}
public OneWorld(Point[][] oneWorld, Point... start) {
this.oneWorld = oneWorld;
this.start = start;
perDeal();
}
private OneWorld() {
}
// 处理num和trueNum字段
public void perDeal() {
for (int i = 0; i < Constant.X; i++) {
for (int j = 0; j < Constant.Y; j++) {
if (oneWorld[i][j].getValue() == null) {
num--;
} else if (oneWorld[i][j].getValue() == true) {
trueNum++;
}
}
}
}
// 获取point
public Point getPoint(int x, int y) {
return oneWorld[x][y];
}
// 获取point的复制
public Point getPointCopy(int x, int y) {
return oneWorld[x][y].copy();
}
// 改变point的值
public void ChangePoint(int x, int y) {
Point point = oneWorld[x][y];
point.changeValue();
if (point.getValue() == true) {
trueNum++;
} else {
trueNum--;
}
}
/**
* 当图中的点,值只有null和另外一种的时候,图就是完美的!
*/
public Boolean isPerfact1() {
Boolean tag = null;
int x = Constant.X;
int y = Constant.Y;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
Boolean value = oneWorld[i][j].getValue();
if (value == null) {
continue;
}
tag = tag == null ? value : tag;
if (tag != value) {
return false;
}
}
}
return true;
}
/**
* 另一个判断图是否完美的方式,需要维护num和trueNum两个字段
*/
public Boolean isPerfact() {
return trueNum == 0 || trueNum == num ? true : false;
}
/**
* 复制自身
*/
public OneWorld copy() {
Point[][] points = new Point[Constant.X][Constant.Y];
for (int i = 0; i < Constant.X; i++) {
for (int j = 0; j < Constant.Y; j++) {
points[i][j] = oneWorld[i][j].copy();
}
}
Point[] starts = new Point[Constant.NUMBER];
for (int i = 0; i < Constant.NUMBER; i++) {
starts[i] = start[i].copy();
}
OneWorld copyOne = new OneWorld();
// copyOne.setOneWorld(points);
// copyOne.setStart(starts);
// copyOne.setNum(num);
// copyOne.setTrueNum(trueNum);
copyOne.oneWorld = points;
copyOne.start = starts;
copyOne.num = num;
copyOne.trueNum = trueNum;
return copyOne;
}
public Point[] getStart() {
return start;
}
public Point[][] getOneWorld() {
return oneWorld;
}
}
OneStep.java
package world;
import java.util.ArrayList;
import java.util.List;
/**
* 存储走一步之后的图;以及行走的步骤
*/
public class OneStep {
private OneWorld oneWrold;
// 步骤中为行走之前的值;steps为null,表示一步都没有走
private List<Point>[] steps = new ArrayList[Constant.NUMBER];
public OneStep(OneWorld oneWrold, List<Point>[] steps) {
this.oneWrold = oneWrold;
this.steps = steps;
}
public OneStep(OneWorld oneWrold) {
super();
this.oneWrold = oneWrold;
}
public OneWorld getOneWrold() {
return oneWrold;
}
public void setOneWrold(OneWorld oneWrold) {
this.oneWrold = oneWrold;
}
public List<Point>[] getSteps() {
return steps;
}
public void setSteps(List<Point>[] steps) {
this.steps = steps;
}
public List<Point>[] copySteps() {
List<Point>[] lists = new ArrayList[Constant.NUMBER];
for (int i = 0; i < Constant.NUMBER; i++) {
List<Point> step = steps[i];
if (step != null) {
List<Point> list = new ArrayList<Point>();
for (int j = 0; j < step.size(); j++) {
list.add(step.get(j).copy());
}
lists[i] = list;
}
}
return lists;
}
}
Constant.java
package world;
public class Constant {
// 图中的行
public static int X = 5;
// 图中的列
public static int Y = 4;
// 图中的起点个数
public static int NUMBER = 2;
}
Demo.java
package world;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
public class Demo {
private static Logger logger = Logger.getLogger(Demo.class);
public static void main(String[] args) {
// 初始化
Point[][] oneWorld = new Point[Constant.X][Constant.Y];
oneWorld[0] = new Point[] { new Point(null, 0, 0), new Point(false, 0, 1), new Point(true, 0, 2),new Point(null, 0, 3) };
oneWorld[1] = new Point[] { new Point(false, 1, 0), new Point(false, 1, 1), new Point(true, 1, 2),new Point(false, 1, 3) };
oneWorld[2] = new Point[] { new Point(true, 2, 0), new Point(true, 2, 1), new Point(false, 2, 2),new Point(null, 2, 3) };
oneWorld[3] = new Point[] { new Point(false, 3, 0), new Point(true, 3, 1), new Point(true, 3, 2),new Point(true, 3, 3) };
oneWorld[4] = new Point[] { new Point(null, 4, 0), new Point(true, 4, 1), new Point(true, 4, 2),new Point(null, 4, 3) };
OneWorld world = new OneWorld(oneWorld, new Point(false, 1, 3), new Point(true, 3, 3));
OneStep oneStep = new OneStep(world);
Date begin = new Date();
OneStep one = new Demo().run(oneStep);
Date end = new Date();
logger.info("**********************************************");
logger.info(end.getTime() - begin.getTime());
printsteps(one);
logger.info("**********************************************");
}
public static void printsteps(OneStep one){
if (one == null) {
logger.info("没有结果!");
return;
}
List<Point>[] steps = one.getSteps();
for (int i = 0; i < Constant.NUMBER; i++) {
List<Point> list = steps[i];
StringBuffer sb=new StringBuffer();
sb.append("第"+i+"步:");
if (list == null) {
continue;
}
for (Point p : list) {
sb.append("(" + p.getX() + "," + p.getY() + ") ");
}
logger.info(sb.toString());
}
}
/**
* 返回非null表示图是perfact,否则返回null;
*/
public OneStep run(OneStep oneStep) {
// 当图是perfact时,返回;
if (oneStep.getOneWrold().isPerfact()) {
return oneStep;
}
OneWorld oneWrold = oneStep.getOneWrold();
List<Point>[] steps = oneStep.getSteps();
// 当图中的某个步骤已经走完所有的点时,直接返回null;
for (int i = 0; i < Constant.NUMBER; i++) {
List<Point> step = steps[i];// 第i个起点行走的步骤
if (step != null && step.size() == oneWrold.getNum()) {
return null;
}
}
List<OneStep> lists = new ArrayList<OneStep>();
for (int i = 0; i < Constant.NUMBER; i++) {
List<Point> step = steps[i];// 第i个起点行走的步骤
// 上
if (step == null) {
// 没有走过,则先反转自身,在反转自身上一个点
OneWorld up = oneWrold.copy();
List<Point>[] upSteps = oneStep.copySteps();
// 没有走过,则对应的步骤应该为null,声明步骤
List<Point> upStep = new ArrayList<Point>();
// 该步骤的起点;
Point start = up.getStart()[i];
// 反转起点
Point p = up.getPointCopy(start.getX(), start.getY());
upStep.add(p);
up.ChangePoint(start.getX(), start.getY());
// 反转上一个点
if ((start.getX() - 1) >= 0) {
p = up.getPointCopy(start.getX() - 1, start.getY());
if (p.getValue() != null) {
upStep.add(p);
up.ChangePoint(start.getX() - 1, start.getY());
// 处理成功,添加到集合中
upSteps[i] = upStep;
lists.add(new OneStep(up, upSteps));
}
}
} else {
OneWorld up = oneWrold.copy();
List<Point>[] upSteps = oneStep.copySteps();
List<Point> upStep = upSteps[i];
Point start = upStep.get(upStep.size() - 1);
// 反转上一个点
if ((start.getX() - 1) >= 0) {
Point p = up.getPointCopy(start.getX() - 1, start.getY());
// 上一个点不能为null
if (p.getValue() != null) {
// 上一个点不能走过
int upStepLength = upStep.size();
int j = 0;
for (; j < upStepLength; j++) {
if (p.getX() == upStep.get(j).getX() && p.getY() == upStep.get(j).getY()) {
break;
}
}
if (j == upStepLength) {
upStep.add(p);
up.ChangePoint(start.getX() - 1, start.getY());
// 处理成功,添加到集合中
upSteps[i] = upStep;
lists.add(new OneStep(up, upSteps));
}
}
}
}
// 下
if (step == null) {
// 没有走过,则先反转自身,在反转自身下一个点
OneWorld down = oneWrold.copy();
List<Point>[] downSteps = oneStep.copySteps();
// 没有走过,则对应的步骤应该为null,声明步骤
List<Point> downStep = new ArrayList<Point>();
// 该步骤的起点;
Point start = down.getStart()[i];
// 反转起点
Point p = down.getPointCopy(start.getX(), start.getY());
downStep.add(p);
down.ChangePoint(start.getX(), start.getY());
// 反转下一个点
if ((start.getX() + 1) < Constant.X) {
p = down.getPointCopy(start.getX() + 1, start.getY());
if (p.getValue() != null) {
downStep.add(p);
down.ChangePoint(start.getX() + 1, start.getY());
// 处理成功,添加到集合中
downSteps[i] = downStep;
lists.add(new OneStep(down, downSteps));
}
}
} else {
OneWorld down = oneWrold.copy();
List<Point>[] downSteps = oneStep.copySteps();
List<Point> downStep = downSteps[i];
Point start = downStep.get(downStep.size() - 1);
// 反转下一个点
if ((start.getX() + 1) < Constant.X) {
Point p = down.getPointCopy(start.getX() + 1, start.getY());
// 下一个点不能为null
if (p.getValue() != null) {
// 下一个点不能走过
int downStepLength = downStep.size();
int j = 0;
for (; j < downStepLength; j++) {
if (p.getX() == downStep.get(j).getX() && p.getY() == downStep.get(j).getY()) {
break;
}
}
if (j == downStepLength) {
downStep.add(p);
down.ChangePoint(start.getX() + 1, start.getY());
// 处理成功,添加到集合中
downSteps[i] = downStep;
lists.add(new OneStep(down, downSteps));
}
}
}
}
// 左
if (step == null) {
// 没有走过,则先反转自身,在反转自身下一个点
OneWorld left = oneWrold.copy();
List<Point>[] leftSteps = oneStep.copySteps();
// 没有走过,则对应的步骤应该为null,声明步骤
List<Point> leftStep = new ArrayList<Point>();
// 该步骤的起点;
Point start = left.getStart()[i];
// 反转起点
Point p = left.getPointCopy(start.getX(), start.getY());
leftStep.add(p);
left.ChangePoint(start.getX(), start.getY());
// 反转左侧一个点
if ((start.getY() - 1) >= 0) {
p = left.getPointCopy(start.getX(), start.getY() - 1);
if (p.getValue() != null) {
leftStep.add(p);
left.ChangePoint(start.getX(), start.getY() - 1);
// 处理成功,添加到集合中
leftSteps[i] = leftStep;
lists.add(new OneStep(left, leftSteps));
}
}
} else {
OneWorld left = oneWrold.copy();
List<Point>[] leftSteps = oneStep.copySteps();
List<Point> leftStep = leftSteps[i];
Point start = leftStep.get(leftStep.size() - 1);
// 反转左侧一个点
if ((start.getY() - 1) >= 0) {
Point p = left.getPointCopy(start.getX(), start.getY() - 1);
// 下一个点不能为null
if (p.getValue() != null) {
// 下一个点不能走过
int leftStepLength = leftStep.size();
int j = 0;
for (; j < leftStepLength; j++) {
if (p.getX() == leftStep.get(j).getX() && p.getY() == leftStep.get(j).getY()) {
break;
}
}
if (j == leftStepLength) {
leftStep.add(p);
left.ChangePoint(start.getX(), start.getY() - 1);
// 处理成功,添加到集合中
leftSteps[i] = leftStep;
lists.add(new OneStep(left, leftSteps));
}
}
}
}
// 右
if (step == null) {
// 没有走过,则先反转自身,在反转自身右侧的一个点
OneWorld right = oneWrold.copy();
List<Point>[] rightSteps = oneStep.copySteps();
// 没有走过,则对应的步骤应该为null,声明步骤
List<Point> rightStep = new ArrayList<Point>();
// 该步骤的起点;
Point start = right.getStart()[i];
// 反转起点
Point p = right.getPointCopy(start.getX(), start.getY());
rightStep.add(p);
right.ChangePoint(start.getX(), start.getY());
// 反转右侧侧一个点
if ((start.getY() + 1) < Constant.Y) {
p = right.getPointCopy(start.getX(), start.getY() + 1);
if (p.getValue() != null) {
rightStep.add(p);
right.ChangePoint(start.getX(), start.getY() + 1);
// 处理成功,添加到集合中
rightSteps[i] = rightStep;
lists.add(new OneStep(right, rightSteps));
}
}
} else {
OneWorld right = oneWrold.copy();
List<Point>[] rightSteps = oneStep.copySteps();
List<Point> rightStep = rightSteps[i];
Point start = rightStep.get(rightStep.size() - 1);
// 反转右侧一个点
if ((start.getY() + 1) < Constant.Y) {
Point p = right.getPointCopy(start.getX(), start.getY() + 1);
// 右一个点不能为null
if (p.getValue() != null) {
// 右一个点不能走过
int rightStepLength = rightStep.size();
int j = 0;
for (; j < rightStepLength; j++) {
if (p.getX() == rightStep.get(j).getX() && p.getY() == rightStep.get(j).getY()) {
break;
}
}
if (j == rightStepLength) {
rightStep.add(p);
right.ChangePoint(start.getX(), start.getY() + 1);
// 处理成功,添加到集合中
rightSteps[i] = rightStep;
lists.add(new OneStep(right, rightSteps));
}
}
}
}
}
// end
for (OneStep one : lists) {
OneStep temp = run(one);
if (null != temp) {
return temp;
}
}
return null;
}
}
优化思路:
1.对图进行预处理
2.优先处理步骤少的状态