Java 在骰子值上查找可能的节点
我想写一个递归算法,根据骰子值突出显示所有可能的节点 我该怎么做?不应从空节点移动 在您可以看到的图像中,我的当前节点为蓝色,例如,当骰子值为4时,我想突出显示红色位置。我写了一个这样的代码,但没有工作,谢谢提前Java 在骰子值上查找可能的节点,java,algorithm,Java,Algorithm,我想写一个递归算法,根据骰子值突出显示所有可能的节点 我该怎么做?不应从空节点移动 在您可以看到的图像中,我的当前节点为蓝色,例如,当骰子值为4时,我想突出显示红色位置。我写了一个这样的代码,但没有工作,谢谢提前 f(node n, dice d){ if(d == 0) n.setDest(); if(Up node != null) f(Up node , d-1); if(Down node !=null) f(Down node, d-1);
f(node n, dice d){
if(d == 0)
n.setDest();
if(Up node != null)
f(Up node , d-1);
if(Down node !=null)
f(Down node, d-1);
if(Right node != null)
f(Right node,d-1);
if(Left node != null)
f(Left node,d-1);
}
将已访问的布尔值添加到节点类。然后在每个if测试中,检查节点是否已被访问
if(Up node != null && node.visited != true)
f(Up node, d - 1)
每次启动骰子时不要忘记重置。这里有一个非递归解决方案
public class Move {
private List<Node> steps;
private int stepsRemaining;
private Node lastStep;
public Move(List<Node> steps, int stepsRemaining) {
this.steps = steps;
this.stepsRemaining = stepsRemaining;
this.lastStep = steps.get(steps.size() - 1);
}
// getters and setters
}
public List<Node> getOptions(Node node, int steps) {
LinkedList<Move> stack = new LinkedList<Move>();
stack.addFirst(new Move(Arrays.asList(node), steps);
List<Node> options = new ArrayList<Node>();
while (!stack.isEmpty()) {
Move currentMove = stack.removeFirst();
Node lastStep = currentMove.lastStep;
Node[] childNodes = new Node[] { lastStep.up, lastStep.down, lastStep.left, lastStep.right };
for (Node childNode : childNodes) {
// make sure we don't go back on ourselves
if (childNode != null && !currentMove.steps.contains(childNode)) {
if (currentMove.stepsRemaining == 1) {
options.add(childNode);
continue;
}
List<Node> childSteps = new ArrayList<Node>(currentNode.steps);
childSteps.add(childNode);
stack.addFirst(new Move(childSteps, currentMove.stepsRemaining - 1));
}
}
}
return options;
}
公共类移动{
私有列表步骤;
私人内部步骤维护;
私有节点最后一步;
公共移动(列出步骤,内部步骤保留){
这个步骤=步骤;
this.stepsRemaining=stepsRemaining;
this.lastStep=steps.get(steps.size()-1);
}
//接球手和接球手
}
公共列表getOptions(节点,int步骤){
LinkedList堆栈=新建LinkedList();
stack.addFirst(新移动(Arrays.asList(节点)),步骤);
列表选项=新建ArrayList();
而(!stack.isEmpty()){
Move currentMove=stack.removeFirst();
节点lastStep=currentMove.lastStep;
Node[]childNodes=新节点[]{lastStep.up,lastStep.down,lastStep.left,lastStep.right};
用于(节点childNode:childNodes){
//确保我们不会背叛自己
if(childNode!=null&&!currentMove.steps.contains(childNode)){
如果(currentMove.stepsRemaining==1){
添加(子节点);
继续;
}
List childSteps=newarraylist(currentNode.steps);
添加(childNode);
addFirst(新移动(childSteps,currentMove.stepsRemaining-1));
}
}
}
返回选项;
}
也许这个模具绘图代码会有所帮助
private void drawSpots(Graphics g, int w, int h, int count) {
g.setColor(Color.BLACK);
switch (count) {
case 1:
drawSpot(g, w / 2, h / 2);
break;
case 3:
drawSpot(g, w / 2, h / 2);
// Fall thru to next case
case 2:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
break;
case 5:
drawSpot(g, w / 2, h / 2);
// Fall thru to next case
case 4:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
break;
case 6:
drawSpot(g, w / 4, h / 4);
drawSpot(g, 3 * w / 4, 3 * h / 4);
drawSpot(g, 3 * w / 4, h / 4);
drawSpot(g, w / 4, 3 * h / 4);
drawSpot(g, w / 4, h / 2);
drawSpot(g, 3 * w / 4, h / 2);
break;
}
}
如您所见,图1和图6是独立的节点。图3是图2的特例。图5是图4的特例
可能会以不同的方式排列模具编号。图1、图3和图5相似。图2、图4和图6也相似。我不打算在这里编写任何代码,只需解释算法即可 首先,你不需要一个递归算法来解决这个问题。当然,你可以用递归的方式来实现它,但它不会带来任何好处 也就是说,为了解决问题,您只需要跟踪交叉点节点(如果只有一个交叉点)。之后,您只需计算当前节点(蓝色节点)与交叉点节点之间的距离,我们将其称为
d
。每当您掷骰子并获得一个数字时,我们将其称为c
,您可以计算O(1)中红色节点的位置时间。事实上,对于当前节点所在的分支,距离为d+c
,而对于其他分支,距离为c-d
。唯一的例外是当d>c
时,在这种情况下,当前节点的分支上只有两个红色节点,它们从int开始位于d-c
和d+c
位置部分节点
伪代码
下面的伪代码只考虑图中所示的情况(1个交叉点,2个非交叉点的方向,2个交叉点的方向)。请记住,代码并没有优化,只是为了说明这个想法
// currentNode - the node where you start from
// c - the number given by the die
GetNeighbouringNodes(Node currentNode, int c)
{
Node intersectionNode = null;
Direction intersectionNodeDirection = Direction.None;
if(currentNode.numberOfDirections > 2)
{
intersectionNode = currentNode;
}
else
{
intersectionNodeDirection = Direction.Up;
// the implementation of the getIntersectionNode is not included intentionally
intersectionNode = getIntersectionNode(currentNode, intersectionNodeDirection);
if(intersectionNode == null)
{
intersectionNodeDirection = Direction.Down;
intersectionNode = getIntersectionNode(currentNode, intersectionNodeDirection);
}
// check in other directions also
}
// at this point we have the intersection node
int d = getDistance(currentNode, intersectionNode);
List<Node> resultingNodes = new List<Node>();
if(d > c)
{
resultingNodes.add(getDistantNode(from: intersectionNode, distance: d - c, direction: inverseDirectionOf(intersectionNodeDirection)));
resultingNodes.add(getDistantNode(from: intersectionNode, distance: d + c, direction: inverseDirectionOf(intersectionNodeDirection)));
}
else
{
resultingNodes.add(getDistantNode(from: intersectionNode, distance: d + c, direction: inverseDirectionOf(intersectionNodeDirection)));
foreach(otherDirection)
{
resultingNodes.add(getDistantNode(from: intersectionNode, distance: c - d, direction: otherDirection)));
}
}
return resultingNodes;
}
//currentNode-从中开始的节点
//c-模具给定的编号
GetNeighbouringNodes(节点currentNode,int c)
{
Node intersectionNode=null;
方向相交节点方向=方向。无;
如果(currentNode.numberOfDirections>2)
{
intersectionNode=currentNode;
}
其他的
{
intersectionNodeDirection=方向向上;
//getIntersectionNode的实现不是有意包含的
intersectionNode=getIntersectionNode(currentNode,intersectionNodeDirection);
if(intersectionNode==null)
{
相交节点方向=方向。向下;
intersectionNode=getIntersectionNode(currentNode,intersectionNodeDirection);
}
//在其他方向也检查
}
//此时,我们有了交点节点
int d=getDistance(currentNode,intersectionNode);
列表结果节点=新列表();
如果(d>c)
{
add(getDistantNode(from:intersectionNode,距离:d-c,方向:inverseDirectionOf(intersectionNodeDirection));
添加(getDistantNode(from:intersectionNode,距离:d+c,方向:inverseDirectionOf(intersectionNodeDirection));
}
其他的
{
添加(getDistantNode(from:intersectionNode,距离:d+c,方向:inverseDirectionOf(intersectionNodeDirection));
foreach(其他方向)
{
add(getDistantNode(from:intersectionNode,distance:c-d,direction:otherDirection));
}
}
返回结果节点;
}
如果有任何不清楚的地方,请告诉我。如果
d==0
从子例程返回-使用d<0调用f
将不起作用。不起作用,因为在中不编译,不符合预期或两者都不符合?代码的输出是什么?不起作用,但没有正确答案。我认为它会计算额外的节点,应该忽略它出现的节点。例如,如果我们从上到下移动,就不应该再向上计算。它只是右,左,下!!!好啊然后保留一个访问节点列表,或者将它们标记为其他形式,或者将数据结构更改为单向链接。但是请遵循java命名约定