在前文中文编程语言之Z语言初尝试: ZLOGO 4与相关讨论后, 萌生了用JavaScript编写类似语言以便在线编程的想法. 于是使用 @TKT2016 (知乎账号)的ZLOGO语法设计, 在编程语言试验之Antlr4+JavaScript实现"圈4"基础上, 通过p5js的绘图功能, 实现了基本的两个ZLOGO功能. 如图(动态效果看起来更爽一点, 当然要耐心等它画完, 请自行尝试):

源码库: program-in-chinese/quan3, 导出代码到本地后, 在浏览器中打开"圈3.html"即可在本地实践编程.

在线演示: 地址.

由于还不支持循环, 实现这个五角星的代码很重影:

  1. 开始
  2. 前进200
  3. 左转144
  4. 前进200
  5. 左转144
  6. 前进200
  7. 左转144
  8. 前进200
  9. 左转144
  10. 前进200
  11. 结束

下面是编程语言试验之Antlr4+JavaScript实现"圈4"之后添加的主要部分:

语法文件(圈3.g4):

  1. 声明 : 前进 | 转向;
  2. 前进 : '前进' T ;
  3. 转向 : T转向 '转' T '度' ;
  4. T转向 : '左' | '右' ;

主要修改在"定制监听器.js":

命名还比较粗糙, 一些用语最好更加一致(比如"长度","距离","前进量"虽在不同上下文, 实际指的是一个东西), 需要改进. 当然算法肯定也可以改进, 暂时是实现功能优先.

  1. var 常量_指令名_前进 = "前进";
  2. var 常量_指令名_转向 = "转向";
  3. var 序号 = 0;
  4. var 画布尺寸 = {x: 1000, y: 800};
  5. var 原点 = {x: 画布尺寸.x/2, y: 画布尺寸.y/2};
  6. var 前进角度 = 90; // 默认向上, 对应弧度: 90 * Math.PI / 180
  7. // 指令格式: 名称 (转向, 前进, 笔色等等); 参数 (转向角度--右为负,左为正; 前进长度-像素数等等);
  8. var 指令序列 = [];
  9. 定制监听器.prototype.enter程序 = function(ctx) {
  10. 重置状态();
  11. // 只需调用一次
  12. // https://p5js.org/reference/#/p5/setup
  13. 构图 = function() {
  14. 新画布(画布尺寸.x, 画布尺寸.y);
  15. }
  16. };
  17. function 重置状态() {
  18. 序号 = 0;
  19. 原点 = {x: 画布尺寸.x/2, y: 画布尺寸.y/2};
  20. 前进角度 = 90;
  21. 指令序列 = [];
  22. }
  23. // 根据指令序列, 生成路径分段描述(段起止点坐标, 颜色等等)
  24. // 如: 前进50, 左转90度, 前进50 应返回(假设起点为{x: 200, y: 200}):
  25. // {起点: {x: 200, y: 200}, 终点: {x: 200, y: 150}, 长度: 50},
  26. // {起点: {x: 200, y: 150}, 终点: {x: 150, y: 150}, 长度: 50}
  27. function 生成路径表(指令序列) {
  28. // 段: {起点: {x, y}, 终点: {x, y}, 长度, 颜色}
  29. var 路径表 = [];
  30. var 起点 = 原点;
  31. for(var i = 0; i < 指令序列.length; i++ ){
  32. var 指令 = 指令序列[i];
  33. var 指令名 = 指令.名称;
  34. var = {起点: 起点};
  35. if (指令名 === 常量_指令名_前进) {
  36. var 距离 = 指令.参数;
  37. var x增量 = Math.cos(前进角度 * Math.PI / 180);
  38. var y增量 = Math.sin(前进角度 * Math.PI / 180);
  39. 段.终点 = {x: 起点.x + x增量 * 距离, y: 起点.y - y增量 * 距离};
  40. 段.长度 = 距离;
  41. 路径表.push(段);
  42. 起点 = 段.终点;
  43. } else if (指令名 === 常量_指令名_转向) {
  44. 前进角度 += 指令.参数;
  45. }
  46. }
  47. return 路径表;
  48. }
  49. 定制监听器.prototype.exit程序 = function(ctx) {
  50. var 路径表 = 生成路径表(指令序列);
  51. 绘制 = function() {
  52. var 当前序号 = 序号;
  53. background(255, 255, 255);
  54. for (var i = 0; i < 路径表.length; i++ ) {
  55. var = 路径表[i];
  56. var 起点 = 段.起点;
  57. var 终点 = 段.终点;
  58. var 距离 = 段.长度;
  59. if (当前序号 < 距离) {
  60. line(起点.x, 起点.y, 起点.x + (终点.x - 起点.x) * 当前序号 / 距离, 起点.y + (终点.y - 起点.y) * 当前序号 / 距离);
  61. break;
  62. } else {
  63. line(起点.x, 起点.y, 终点.x, 终点.y);
  64. 当前序号 = 当前序号 - 段.长度;
  65. }
  66. }
  67. 序号 ++;
  68. }
  69. };
  70. 定制监听器.prototype.exit前进 = function(上下文) {
  71. var 前进量 = 上下文.getChild(1).getText()
  72. 指令序列.push({名称: 常量_指令名_前进, 参数: parseInt(前进量)});
  73. };
  74. 定制监听器.prototype.exit转向 = function(上下文) {
  75. var 方向 = 上下文.getChild(0).getText();
  76. var 角度 = parseInt(上下文.getChild(2).getText());
  77. 角度 = 角度 * (方向 === "左" ? 1 : -1);
  78. 指令序列.push({名称: 常量_指令名_转向, 参数: 角度});
  79. };

2017-12-05 JavaScript实现ZLOGO子集: 前进+转向的更多相关文章

  1. 2017-12-09 JavaScript实现ZLOGO子集: 测试用例

    续前文JavaScript实现ZLOGO子集: 前进+转向. 在添加新功能之前, 先添加测试用例, 以应对日益复杂的代码. 选择使用QUnit编写运行测试用例. 暂时对比较复杂和I/O无关的部分进行测 ...

  2. 2017-12-06 JavaScript实现ZLOGO子集: 单层循环功能

    前文JavaScript实现ZLOGO子集: 前进+转向的示例代码很累赘, 因此尝试实现基本的循环功能, 使得前面的11行代码缩减为7行: 开始 循环4次 前进200 左转144度 到此为止 前进20 ...

  3. 【2017.12.05 智能驾驶/汽车电子】转载:如何成为一名无人驾驶工程师 By刘少山

    之前对无人驾驶的理解就是通过刘少山老师的书:第一本无人驾驶技术书 通读之后,对智能驾驶有了一个初步的认识,如感知.决策.控制都涉及哪些领域,有哪些可以利用的技术: 但经过一段时间的实践,发现即使是在我 ...

  4. 2018-12-14 JavaScript实现ZLOGO: 前进方向和速度

    系列前文: JavaScript实现ZLOGO子集: 前进+转向 JavaScript实现ZLOGO子集: 单层循环功能 JavaScript实现ZLOGO子集: 测试用例 JavaScript实现Z ...

  5. JavaScript实现ZLOGO: 用语法树实现多层循环

    原址: https://zhuanlan.zhihu.com/p/32571516 照例先上演示弱效果图. 演示地址照旧: 代码如下: 开始 循环4次 循环4次 前进50 左转90度 到此为止 右转9 ...

  6. 2018-01-02 JavaScript实现ZLOGO: 用语法树实现多层循环

    原址: https://zhuanlan.zhihu.com/p/32571516 照例先上演示弱效果图. 演示地址照旧: 代码如下: 开始 循环4次 循环4次 前进50 左转90度 到此为止 右转9 ...

  7. 【web开发 | 移动APP开发】 Web 移动开发指南(2017.01.05更新)

    版本记录 - 版本1.0 创建文章(2016.12.30) - 版本1.1 更正了hybird相关知识:增加了参考文章(2017.01.05): + Web APP更正为响应式移动站点与页面,简称响应 ...

  8. Gitlab一键端的安装汉化及问题解决(2017/12/14目前版本为10.2.4)

    Gitlab的安装汉化及问题解决 一.前言 Gitlab需要安装的包太TM多了,源码安装能愁死个人,一直出错,后来发现几行命令就装的真是遇到的新大陆一样... ... 装完之后感觉太简单,加了汉化补丁 ...

  9. app后端设计(11)-- 系统架构(2014.12.05更新)

    个人认为,在小型的创业团队中,特别是以应用产品为主,在架构后台的时候,需要集中精力解决自身业务上的问题,不是花时间解决第三方已经解决的问题,简单点来说,就是能用第三方服务就使用第三方的服务.基于这个原 ...

随机推荐

  1. JavaScrip继承图文总结

    JavaScript有多种继承模式,总结起来用到的方法有:原型链的传递.构造函数的借用.对象的复制.     这篇文章讲得很清晰,让我们明白:所有JS对象源于null,并通过原型指针和原型对象来实现继 ...

  2. Spring集合注入

    1.集合注入 上一篇博客讲了spring得属性注入,通过value属性来配置基本数据类型,通过<property>标签的 ref 属性来配置对象的引用.如果想注入多个数据,那我们就要用到集 ...

  3. Android 上传文件到 FTP 服务器

    实现背景 近期接触到一个需求,就是将文件从Android系统上传到FTP服务器,虽然之前接触过FTP服务器,了解基本的使用流程,但是将此流程从使用习惯转化为代码实现还是有一定难度的.但是基本的流程还是 ...

  4. [git] 本地仓库信息的查询

    本地仓库信息查询操作 1.1  git status 查看当前暂存区状态 git  status 显示当前分支信息: 提交的目的分支信息: git 管理的有修改的文件: 当前仓库未被 git 管理的文 ...

  5. mysql升级8.0后项目不能连接问题

    转载简书:https://www.jianshu.com/p/a164d582e5d9 主要是因为驱动配置变了driver中得用com.mysql.cj.jdbc.Driver,多了个cj: url后 ...

  6. Linux - 在当前系统内查找信息的方法

    查找文本 使用grep命令 grep命令 - 示例 grep命令 - 正则表达式 grep命令 - 统计匹配字符串的行数 grep命令 - 搜索多个单词 结合正则表达式使用grep命令 注意:在搜索指 ...

  7. Spark基础脚本入门实践1

    1.创建数据框架 Creating DataFrames val df = spark.read.json("file:///usr/local/spark/examples/src/mai ...

  8. Redis主从和集群

    主从概念 一个master可以拥有多个slave,一个slave又可以拥有多个slave.如此下去,形成了强大的多级服务器集群架构. master用写数据,经统计:网站的读写比率是10:1 通过主从分 ...

  9. PowerShell 连接远程服务器

    >>服务端Enable-PSRemoting winrm quickconfig ————这个可能不需要 >>客户端Set-Item wsman:\localhost\Clie ...

  10. Ubuntu编译安装最新的webkit

    好久都没更新webkit 源码在ubuntu上编译了,网上搜了一下,基本上都是早期编译的webkit版本.可能是大家都去搞高大上的谷歌浏览器了吧. 今天就以ubuntu14.04版本作为编译环境来讲讲 ...