Java 在骰子值上查找可能的节点

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);

我想写一个递归算法,根据骰子值突出显示所有可能的节点

我该怎么做?不应从空节点移动

在您可以看到的图像中,我的当前节点为蓝色,例如,当骰子值为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);

  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命名约定