Răsfoiți Sursa

编程课加入while循环模块组件和逻辑

liyanbo 3 săptămâni în urmă
părinte
comite
c1c801155f
2 a modificat fișierele cu 86 adăugiri și 1 ștergeri
  1. 74 0
      src/api/blockly/blockly.js
  2. 12 1
      src/components/blockly/MapGame.vue

+ 74 - 0
src/api/blockly/blockly.js

@@ -360,6 +360,48 @@ const availableBlocks = {
     },
     isGeneral: true // 标记为通用积木
   },
+  // 循环积木 - while循环
+  controls_whileUntil: {
+    jsonConfig: {
+      "type": "controls_whileUntil",
+      "message0": "%1 %2 %3",
+      "args0": [
+        {
+          "type": "field_image",
+          "src": repeatImage,
+          "width": 25,
+          "height": 25,
+          "alt": "循环"
+        },
+        {
+          "type": "field_dropdown",
+          "name": "MODE",
+          "options": [
+            ["当", "WHILE"],
+            ["直到", "UNTIL"]
+          ]
+        },
+        {
+          "type": "input_value",
+          "name": "CONDITION",
+          "check": "Boolean"
+        }
+      ],
+      "message1": "执行 %1",
+      "args1": [
+        {
+          "type": "input_statement",
+          "name": "DO"
+        }
+      ],
+      "previousStatement": null,
+      "nextStatement": null,
+      "colour": "#5BA55B",
+      "tooltip": "当条件为真时重复执行内部代码",
+      "helpUrl": ""
+    },
+    isGeneral: true // 标记为通用积木
+  },
   // 当经过某个形状的积木(可作为参数使用的value类型)
   when_passed: {
     jsonConfig: {
@@ -387,6 +429,18 @@ const availableBlocks = {
     },
     isGeneral: true
   },
+  // 是否到达终点积木
+  is_at_end: {
+    jsonConfig: {
+      "type": "is_at_end",
+      "message0": "到达终点",
+      "output": "Boolean",
+      "colour": 10,
+      "tooltip": "检查角色是否到达终点位置",
+      "helpUrl": ""
+    },
+    isGeneral: true
+  },
   // 特殊积木 - 可根据配置动态加载
   pause: {
     jsonConfig: {
@@ -541,6 +595,9 @@ const availableGenerators = {
     const shape = block.getFieldValue('SHAPE');
     return [`whenPassed('${shape}')`, javascriptGenerator.ORDER_FUNCTION_CALL];
   },
+  is_at_end: function(block) {
+    return [`isAtEnd()`, javascriptGenerator.ORDER_FUNCTION_CALL];
+  },
   // 条件判断生成器 - 使用Blockly默认实现方式确保兼容性
   controls_if: function(block) {
     let code = '';
@@ -582,6 +639,13 @@ ${javascriptGenerator.prefixLines(elseCode, javascriptGenerator.INDENT)}}
     const code = `for (let i = 0; i < ${repeats}; i++) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}}\n`;
     return code;
   },
+  controls_whileUntil: function(block) {
+    const until = block.getFieldValue('MODE') === 'UNTIL';
+    const condition = javascriptGenerator.valueToCode(block, 'CONDITION', javascriptGenerator.ORDER_NONE) || 'false';
+    const branch = javascriptGenerator.statementToCode(block, 'DO');
+    const code = until ? `while (!((${condition})) && loopCount < 100) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}loopCount++;\n}` : `while ((${condition}) && loopCount < 100) {\n${javascriptGenerator.prefixLines(branch, javascriptGenerator.INDENT)}loopCount++;\n}`;
+    return code;
+  },
   // 特殊生成器 - 可根据配置动态加载
   pause: function(block) {
     const seconds = block.getFieldValue('SECONDS');
@@ -640,6 +704,9 @@ const availablePythonGenerators = {
     const shape = block.getFieldValue('SHAPE');
     return [`when_passed('${shape}')`, pythonGenerator.ORDER_FUNCTION_CALL];
   },
+  is_at_end: function(block) {
+    return [`is_at_end()`, pythonGenerator.ORDER_FUNCTION_CALL];
+  },
   // 条件判断生成器
   controls_if: function(block) {
     const n = block.elseifCount_;
@@ -679,6 +746,13 @@ ${pythonGenerator.prefixLines(elseCode, pythonGenerator.INDENT)}
     const code = `for i in range(${repeats}):\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}\n`;
     return code;
   },
+  controls_whileUntil: function(block) {
+    const until = block.getFieldValue('MODE') === 'UNTIL';
+    const condition = pythonGenerator.valueToCode(block, 'CONDITION', pythonGenerator.ORDER_NONE) || 'False';
+    const branch = pythonGenerator.statementToCode(block, 'DO');
+    const code = until ? `while not (${condition}) and loop_count < 100:\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}loop_count += 1\n` : `while (${condition}) and loop_count < 100:\n${pythonGenerator.prefixLines(branch, pythonGenerator.INDENT)}loop_count += 1\n`;
+    return code;
+  },
   // 特殊生成器 - 可根据配置动态加载
   pause: function(block) {
     const seconds = block.getFieldValue('SECONDS');

+ 12 - 1
src/components/blockly/MapGame.vue

@@ -592,6 +592,7 @@ function generateToolboxXml() {
       <block type="pickup_item"></block>
       <block type="use_item"></block>
       <block type="when_passed"></block>
+      <block type="is_at_end"></block>
   `;
 
   // 确保blocklySpecialBlocks是数组
@@ -615,6 +616,7 @@ function generateToolboxXml() {
     </category>
     <category name="循环" colour="160">
       <block type="controls_repeat_ext"></block>
+      <block type="controls_whileUntil"></block>
     </category>
     <category name="数学" colour="60">
       <block type="math_number"></block>
@@ -865,7 +867,7 @@ const runCode = async () => {
             reject(new Error('执行已取消'));
           });
 
-          const wrappedCode = `(async () => { ${code} })()`;
+          const wrappedCode = `(async () => { let loopCount = 0; ${code} })()`;
           await new Function(wrappedCode)();
           resolve();
         } catch (error) {
@@ -1233,6 +1235,15 @@ window.turnAround = async function() {
   await new Promise(resolve => setTimeout(resolve, CONFIG.DELAY.ACTION_DELAY));
 };
 
+// 检查是否到达终点
+window.isAtEnd = function() {
+  const playerX = Math.round(playerPosition.value.x);
+  const playerY = Math.round(playerPosition.value.y);
+  const endX = endPoint.value.x;
+  const endY = endPoint.value.y;
+  return playerX === endX && playerY === endY;
+};
+
 // 拾取物品函数
 window.pickupItem = async function()  {
   if (shouldStopExecution || isColliding.value || isSliding.value) {