在树结构中显示平面列表,其中孩子有多个父母?

时间:2016-06-11 22:33:39

标签: javascript angularjs algorithm debugging tree

我是Javascript的新手和编程初学者。我有一个"步骤"具有选择/解决方案字段的对象。此选项/解决方案字段引用列表中的另一个对象。我想基于此字段从此列表中创建树层次结构。

[这是我希望像树一样重组的数组文件:

$scope.nodes = {
  "story": {
    "step" : [
      {
        "title": "Begin",
        "id": "0",
        "type": "MultipleChoice",
        "description": "Yo, bro it's the start of the adventure !",
        "choice": [
          {
          "nextStepId": "1",
          "#text": "You was born as a troll, no luck in life. :'("
        }]
      },
      {
        "title": "Choice",
        "id": "1",
        "type": "MultipleChoice",
        "description": "It's time to take your life back, and choice what you should do !",
          "choice": [
        {
          "nextStepId": "1001",
          "#text": "Take an apple"
        },
        {
          "nextStepId": "4",
          "#text": "Suicide"
        },
        {
          "nextStepId": "1001",
          "#text": "You use a coin to know what to do"
        }
        ]
      },
      {
        "title": "Riddle",
        "id": "4",
        "type": "Riddle",
        "description": "What is the best way to suicide ?",
        "solution": {
        "nextStep": "1000",
          "#text": "think"
        }
      },
      {
        "title": "you are dead",
        "id": "1000",
        "type": "End",
        "win": "true",
        "description": "Nice, you are dead finally !"
      },
      {
        "title": "you are alive",
        "id": "1001",
        "type": "End",
        "win": "false",
        "description": "Damn, you are still alive !"

      }
    ]
}
}

这是我到目前为止所做的:

$scope.tree = function tree() {
  var map = {}, node, roots = [];
  for (var i = 0; i < nodes.length; i += 1) {
    node = nodes.story.step[i];
    map[node.id] = i;
    if (node.id !== "0") {
      switch (node.type) {
        case ("MultipleChoice"):
          for (var j = 0; i < node.choice.length; j += 1)
          nodes[map[node.id]].choice[j].nextStepId[j].push(node);
          break;
        case ("Riddle"):
          nodes[map[node.id]].solution.nextStep[j].push(node);
          break;
        case ("End"):
        //TO DO
      }
    }
    else {
      roots.push(node);
    }
  }
}(nodes)

(请注意,子项(选项/解决方案)可以包含多个父项,并且“选择”可以是数组或一个元素。)

显然,我做错了什么。选择是未定义的&#39;

你能纠正我吗?我无法弄明白。我最好保留自己的代码,以便从我的错误中吸取教训,但如果你有别的建议,我会感到自由。

非常感谢

1 个答案:

答案 0 :(得分:0)

我会以不同的方式编码。在这里使用ng-switch非常有用。然后,您可以将当前步骤存储在变量中,并在ng-switch中决定您要显示的内容(多个选项,Riddle或结束)。

如果您想阻止用户作弊,您必须在服务器端添加解决方案检查,因为您的模型在浏览器控制台中是可读的,用户可以在点击之前检查正确的答案。

你应用程序的唯一部分,我不清楚它的谜语&#39;题。所以这可能不像你想要的那样。但这不应该难以修改。

请查看下面的演示或fiddle

&#13;
&#13;
angular.module('demoApp', [])
    .controller('mainCtrl', MainCtrl);

function MainCtrl($scope) {
	var vm = this;
    
    var nodes = {
        "story": {
            "step": [{
                "title": "Begin",
                "id": "0",
                "type": "MultipleChoice",
                "description": "Yo, bro it's the start of the adventure !",
                "choice": [{
                    "nextStepId": "1",
                    "#text": "You was born as a troll, no luck in life. :'("
                }]
            }, {
                "title": "Choice",
                "id": "1",
                "type": "MultipleChoice",
                "description": "It's time to take your life back, and choice what you should do !",
                "choice": [{ // missing [ here
                    "nextStepId": "1001",
                    "#text": "Take an apple"
                }, {
                    "nextStepId": "4",
                    "#text": "Suicide"
                }, {
                    "nextStepId": "1001",
                    "#text": "You use a coin to know what to do"
                }]
            }, {
                "title": "Riddle",
                "id": "4",
                "type": "Riddle",
                "description": "What is the best way to suicide ?",
                "solution": {
                    "nextStepId": "1000",
                    "#text": "think"
                }
            }, {
                "title": "you are dead",
                "id": "1000",
                "type": "End",
                "win": true,
                "description": "Nice, you are dead finally !"
            }, {
                "title": "you are alive",
                "id": "1001",
                "type": "End",
                "win": false,
                "description": "Damn, you are still alive !"

            }]
        }
    };

	function getById(id) {
    	var node;
        for(var i=0; i<nodes.story.step.length; i++) {
        	node = nodes.story.step[i];
            if ( node.id === id ) {
            	return node;
            }
        }
    }
	angular.extend(vm, {
    	nodes: nodes,
        curStep: nodes.story.step[0],
        next: function(id) {
        	vm.curStep = getById(id);
        }
    });
    
	/*
    // too complicated
    $scope.tree = function tree() {
        var map = {},
            node, roots = [];
        for (var i = 0; i < nodes.story.step.length; i++) { // nodes is an object
            //console.log(nodes.story);
            node = nodes.story.step[i];
            console.log(node);
            node.choice.nextStepId = [];
            node.solution.nextStep = [];
            map[node.id] = i;
            if (node.id !== "0") {
                switch (node.type) {
                    case ("MultipleChoice"):
                        for (var j = 0; i < node.choice.length; j += 1)
                            nodes[map[node.choice[j].nextStepId]].choice[j].nextStepId.push(node);
                        break;
                    case ("Riddle"):
                        nodes[map[node.id]].solution.nextStep.push(node);
                }
            } else {
                roots.push(node);
            }
        }
        console.log(JSON.stringify(roots, null, 2));
    }

    $scope.tree();*/
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" ng-controller="mainCtrl as ctrl">
    <div>
        {{ctrl.curStep.description}}
        <div ng-switch="ctrl.curStep.type">
            <div ng-switch-when="MultipleChoice">
                <div ng-repeat="choice in ctrl.curStep.choice">
                <!--<label>{{choice['#text']}}</label>-->
                    <!--<input type="checkbox" ng-click="ctrl.next(choice.nextStepId)"/>-->
                    <button ng-click="ctrl.next(choice.nextStepId)">
                    {{choice['#text']}}
                    </button>
                </div>
            </div>
            <div ng-switch-when="Riddle">
                <a href="#" ng-click="ctrl.next(ctrl.curStep.solution.nextStepId)">{{ctrl.curStep.solution['#text']}}</a>
        </div>
        <div ng-switch-when="End">
            Game Over! <strong>{{ctrl.curStep.win ? 'You\'ve won!': 'You\'ve lost'}}</strong>
        </div>
    </div>
    <!-- just for debugging <pre>{{ctrl.nodes | json: 2}}</pre>-->
</div>
&#13;
&#13;
&#13;