在具有多个父项的树结构中显示平面列表



我是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)

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

显然,我做错了什么。 选择是"未定义的"

你能纠正我吗??我想不通。我最好保留自己的代码以从错误中吸取教训,但如果您有其他建议,请随意。

非常感谢

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

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

您的应用程序中唯一不清楚的部分是"谜语"问题。所以这可能不像你想要的那样。但这应该不难修改。

请看下面的演示或这个小提琴。

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();*/
}
<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>

最新更新