ここでは、ハノイの塔ゲームを実装するために、HT for Web に基づいて HTML5+JavaScript を構築します。
http://hightopo.com/demo/hanoi_20151106/index.html
ハノイの塔のゲームルールと再帰アルゴリズム分析については、http://en.wikipedia.org/wiki/Tower_of_Hanoiを参照してください。
ハノイの塔のルールとアルゴリズムがわかったので、要素の作成を始めてください。 HT for Web (http://www.hightopo.com) の既存の 3D テンプレートを使用してシャーシと 3 つの柱を作成するのは問題ありません。問題は、複数の中空ディスクを作成することです。最初のアイデアは、円柱を作成し、円柱の上端と下端を非表示にし、円盤の効果を実現するために円柱の幅を設定することでした。何度も試し、関連する API ドキュメントを調べた結果、円柱には次のような効果があることがわかりました。厚さがありません。方法を変更することは不可能です。
その後、私は Web カスタム 3D モデル用の HT の WebGL アプリケーション (http://www.hightopo.com/blog/381.html) にインスピレーションを受けました。これによると、ディスクの形状は xy 平面上の長方形になります。 y 軸 1 回転で生成されます。関連ドキュメントを参照した結果、最終的に ht.Default.createRingModel メソッドを使用してディスク モデルを作成し、ノードの作成時に作成したモデルをshape3d 属性を通じて参照することにしました。
ロジックの実装に関しては、スタックの先入れ後出しの原理が採用され、シリンダー上のディスクが順番に制御され、移動される各ディスクが最小のディスクになることが保証されます。
アルゴリズムに関しては、再帰アルゴリズムが使用され、再帰アルゴリズムを通じて再配置プロセスが段階的に記録され、ヒープ原理を使用して段階的に再配置が実行されます。
http://v.youku.com/v_show/id_XODcwMTk4MDI4.html
http://hightopo.com/demo/hanoi_20151106/index.html
var barNum = 5, // 圆盘个数 cylinderHeight = barNum * 20 + 40, // 圆柱高度 barrelMinORadius = 50, // 圆盘最大外半径 barrelIRadius = 10, // 圆盘内半径 poorRadius = 20, // 圆盘外半径差值 barrelMaxORadius = barrelMinORadius + barNum * poorRadius, barrelHeight = 20, // 圆盘高 barPadding = 20, // 柱体之间的间隙 floorX = barrelMaxORadius * 6 + barPadding * 4, // 底盘长 floorY = 20, // 底盘高 floorZ = 2 * barrelMaxORadius + barPadding * 2, // 底盘宽 // 柱体集 positions = [ { barrels: [], position: [-(2*barrelMaxORadius + barPadding), cylinderHeight / 2 + 1, 0] },{ barrels: [], position: [0, cylinderHeight / 2 + 1, 0] },{ barrels: [], position: [(2*barrelMaxORadius + barPadding), cylinderHeight / 2 + 1, 0] } ], runOrder = [], // 圆盘移动顺序集 // 动画参数 params = { delay: 10, duration: 500, easing: Easing['easeBoth'] };/** * 初始化程序 * */function init(){ dataModel = new ht.DataModel(); g3d = new ht.graph3d.Graph3dView(dataModel); view = g3d.getView(); view.className = 'main'; document.body.appendChild(view); window.addEventListener('resize', function (e) { g3d.invalidate(); }, false); g3d.setEye([0, cylinderHeight * 2, floorX * sin(2*PI/360*60)]); // 初始化节点 initNodes(); moveAnimation();}/** * 构造游戏移动队列 * diskQuantity:圆盘个数 * positionA:起点 * positionB:中转点 * positionC:终点 * */function buildRunOrder(diskQuantity, positionA, positionB, positionC){ if (diskQuantity == 1) { runOrder.push([positionA, positionC]); } else { buildRunOrder(diskQuantity - 1, positionA, positionC, positionB); buildRunOrder(1, positionA, positionB, positionC); buildRunOrder(diskQuantity - 1, positionB, positionA, positionC); }}/** * 移动动画 * positionA:起点 * positionC:终点 * */function moveAnimation(positionA, positionC){ if(!positionA){ var poses = runOrder.shift(); if(!poses){ setTimeout(reset, 500); }else{ moveAnimation(positions[poses[0]], positions[poses[1]]); } }else { var barrel = positionA.barrels.pop(); var position = positionC.cylinder.p3(), barPos = barrel.getPosition3d(); position[1] = position[1] + floorY + barrelHeight * positionC.barrels.length - cylinderHeight / 2; setPolylinePoints(polyline, barPos, position); params.action = function (v, t) { var length = g3d.getLineLength(polyline), offset = g3d.getLineOffset(polyline, length * v), point = offset.point, px = point.x, py = point.y, pz = point.z; barrel.p3(px, py, pz); }; params.finishFunc = function () { positionC.barrels.push(barrel); var poses = runOrder.shift(); if (!poses) { moveAnimation(); } else { moveAnimation(positions[poses[0]], positions[poses[1]]); } }; anim = ht.Default.startAnim(params); }}/** * 重置游戏 * */function reset(){ if(positions[0].barrels.length == 0){ positions[0].barrels = positions[2].barrels; } positions[2].barrels = []; for(var i = 0, len = positions[0].barrels.length; i 0; i--, j++){ pos[1] = barrelHeight * j + floorY; positions[0].barrels.push(createBarrel(pos, [1, barrelHeight, 1], barrelMinORadius + i*poorRadius, barrelIRadius, host).s({ 'shape3d.color': randomColor(), '3d.movable': false })); }}/** * 创建节点 * p3:节点位置 * s3:节点大小 * host:吸附节点 * */function createNode(p3, s3, host){ var node = new ht.Node(); node.p3(p3); node.s3(s3); node.setHost(host); node.s({ 'wf.visible': 'selected', 'wf.color': '#FF6B10', 'wf.width': 2, 'wf.short': true }); dataModel.add(node); return node;}/** * 创建空心圆柱 * p3:圆桶位置 * s3:圆桶大小 * oRadius:圆桶外径 * iRadius:圆桶内径 * host:吸附节点 * */function createBarrel(p3, s3, oRadius, iRadius, host){ return createNode(p3, s3, host).s({ 'shape3d': ht.Default.createRingModel([ oRadius, 1, oRadius, 0, iRadius, 0, iRadius, 1, oRadius, 1 ], null, 20, false, false, 70) });}
http://hightopo.com/demo/ hanoi_20151106/index.html