dart dart2 区别
回到我使用BASIC在Apple II上学习编程时,有一个Animal Guess游戏。 该游戏是一个非常原始的AI游戏:计算机尝试询问一些“是/否”问题,并从用户那里收到答案。 根据答案,它可能会问更多的是/否问题,直到试图猜测动物为止。
在本教程中,我们将学习如何使用PHP作为后端以及Dart作为前端来重新激活该程序。 当然,将使用数据库来存储所有有关动物的问题和猜测。
完整的代码已上传到Github。 您可以从这里克隆它。
数据库设置
该程序的数据库结构很简单。 我们只需要一张桌子:
CREATE TABLE `animal` (
`id` int(11) NOT NULL,
`question` varchar(140) DEFAULT NULL,
`y_branch` int(11) DEFAULT NULL,
`n_branch` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
)
id
用于识别每个问题/猜测; question
是要问的问题或要提示的猜测; 当用户对问题回答是或否时, y_branch
和n_branch
标识问题ID。 特别是,如果这两个字段都为“ -1”,则意味着不再有其他问题要问(程序已经进入猜测阶段)。
SQL结构和初始数据(一个问题和两个动物)可以在animal.sql
文件中找到。
后端
由于后端相对简单,因此我将使用纯PHP(带有PDO)。 这些文件位于存储库中的server
目录下。 服务器基本上具有两个功能:
- 通过ID提出问题或提示猜测;
- 用用户的输入拆分一个带有新问题和新猜测的节点;
我们将看一下getquest函数:
<?php
require_once 'pdo.php';
$id=filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);
if(!$id)
$id=1;
$res=$cn->prepare('select * from animal where id = :id');
$res->bindParam(':id', $id);
$res->execute();
$r=$res->fetch();
$ret=array();
$ret['q']=$r[1];
$ret['y']=$r[2];
$ret['n']=$r[3];
setExtraHeader();
echo json_encode($ret);
?>
在此get.php
文件中,我们包括一个pdo.php
文件来设置数据库连接。 然后我们处理输入并进行查询。 最后,我们将结果输出到前端(在本例中为Dart应用)。
这里需要注意的几件事:
- 返回给Dart应用的所有结果均应为JSON格式。 因此,我们使用
json_encode
函数对数组进行编码。 - 在实际返回结果之前,我们设置了一些额外的HTTP标头以启用CORS 。 尽管我们所有文件实际上都是在同一台计算机上,但Dart应用程序和后端实际上是在两个不同的域上运行。 如果没有额外的头,则从前端到后端的调用将失败。
setExtraHeader
函数也在pdo.php
定义。
前端
通过HTML5,JavaScript和其他第三方库,非常方便(或复杂?)前端Web编程。 它只需要更加结构化即可。
在本教程中,我们将使用Google的Dart作为前端开发工具。
安装
要获取Dart IDE,请访问 https://www.dartlang.org并下载适合您平台的软件包。 安装非常简单。 或者, 下载Webstorm ,其中包含本机Dart支持,并且比基于Eclipse的Dart Editor更稳定,性能更高。
Dart刚刚发布了其稳定版本,并摘下了其长期使用的“ BETA”帽子,但它发展Swift。 在撰写本文时,我正在使用Dart编辑器和SDK版本1.0.0_r30188(STABLE)。
为了充分利用Dart提供的交互性,我们将使用新的Polymer库。
注意: Polymer取代了旧版Dart中的web_ui
库。 像Dart一样,Polymer也正在Swift发展。 我在该程序中使用的是0.9.0 + 1版。 某些语法和功能在将来的版本中可能会有所不同。
在开发前端时,Polymer提供了一些有用的功能,例如自定义HTML元素,双向数据绑定,条件模板,异步远程函数调用等。所有这些功能都将在此程序中使用。
创建一个聚合物应用程序
启动Dart IDE,然后选择“文件|新应用程序”。 确保选择“ Web应用程序(使用聚合物库)”作为应用程序类型。
![](https://i-blog.csdnimg.cn/blog_migrate/1e863417314c43af3ca0f02f69599241.png)
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
该向导将创建应用程序目录并设置所有必要的依赖项。 当我们选择“生成示例内容”时,它还将创建一些示例文件。 我们可以删除除pubspec.yaml
之外的所有这些示例文件。
右键单击pubspec.yaml
文件,然后从菜单中选择Pub Get
。 这将有助于安装Dart / Polymer应用程序的所有必需库。
一个典型的Polymer应用程序至少包含3个文件:
- 一个HTML文件作为应用程序入口点。 在这种情况下:
web/animalguess.html
。 通常,在此文件中,我们将为HTML文件设置基本结构,并必须实例化自定义HTML元素。 - 一个HTML文件,用于定义自定义HTML元素,布局,该元素的脚本等。在这种情况下:
web/animalguessclass.html
。 - 实现该自定义HTML元素功能的DART文件。
让我们讨论每个文件的关键点。
animalguess.html
animalguess.html
文件定义了应用程序的整体布局。 这是一个符合HTML5的文件,其中包含所有常规的HEAD,TITLE,LINK,SCRIPT,META元素以及自定义HTML元素标签。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome to Animal Guess Game!</title>
<link rel="stylesheet" href="css/bootstrap.css">
<link rel="stylesheet" href="css/animal.css">
<!-- import the underlying class -->
<link rel="import" href="animalguessclass.html">
<script type="application/dart">import 'package:polymer/init.dart';</script>
<script src="packages/browser/dart.js"></script>
</head>
<body>
<div class="container">
<h1>Welcome to the legacy Animal Guess Game!</h1>
<p><em>Revitalized with PHP and Dart!</em></p>
</div>
<hr>
<animal-guess></animal-guess>
</body>
</html>
在<head></head>
部分的大部分时间里,我们真的不需要进行任何更改。 对于此应用程序,我仅更改了两个CSS链接以链接到Bootstrap CSS和我进一步定制CSS。
在BODY部分中,我们包括了自定义HTML元素<animal-guess>
。 此元素在animalguessclass.html
定义,并通过<link rel="import" href="animalguessclass.html">
语句<link rel="import" href="animalguessclass.html">
。
animalguessclass.html和自定义元素
此文件定义自定义HTML元素的布局,模板,行为。 但是,用于实现该行为的实际代码通常是在单独的DART文件( animalguessclass.dart
)中定义的。
<polymer-element name="animal-guess">
<template>
<div class="container">
<template if="{{!gameinprogress}}">
<h3>Let's get started!</h3>
<button on-click="{{newGame}}">Click me</button>
</template>
...
<template if="{{gameinprogress}}">
<div class="row">
<div class="col-md-6">{{qid}}. {{question}}</div>
<template if="{{!reachedend}}">
<div class="col-md-6">
<a href="#" on-click="{{YBranch}}">Yes</a> <a href="#"
on-click="{{NBranch}}">No</a>
</div>
</template>
</div>
</template>
...
</template>
<script type="application/dart" src="animalguessclass.dart"></script>
</polymer-element>
上面的摘录显示了Polymer元素HTML文件的基本结构。
<polymer-element name="animal-guess"></polymer-element>
来定义元素。 请注意name
属性。 它具有与animalguess.html
( "animal-guess"
)中使用的值相同的值。
有条件模板实例化。 例如:
<template if="{{!gameinprogress}}">
<h3>Let's get started!</h3>
<button on-click="{{newGame}}">Click me</button>
</template>
除非gameinprocess
为false,否则不会呈现<template></template>
之间HTML代码。 gameinprogress
是一个变量,稍后将进行阐述。
另外,请注意,我们已经将按钮元素的click事件挂接到了事件处理程序( "newgame"
)上。 我们稍后还将讨论。
一般来说,此HTML文件与传统HTML文件或HTML模板没有什么不同。 我们可以在此文件中使用各种HTML元素。
注意:可以使用单选按钮。 但是,还有一些与值的绑定有关的问题。 因此,在此实现中,我们仅使用文本框进行输入。 可能存在与其他类型的表单控件的数据绑定有关的问题,但是我们不在此讨论。
此外,在此文件中,我们声明将使用animalguessclass.dart
作为此元素的脚本。
animalguessclass.html
可以在web
目录中找到animalguessclass.html
的完整代码。
动物猜测类
此文件是此应用程序的驱动程序。 它具有驱动程序行为的所有逻辑。 让我们看一些关键部分。
import 'package:polymer/polymer.dart';
import 'dart:html';
import 'dart:convert';
@CustomTag('animal-guess')
class AnimalGuess extends PolymerElement {
@published bool gameinprogress=false;
@published String question='';
@published String myguess='';
@published int qid=1;
int yBranch;
int nBranch;
...
AnimalGuess.created() : super.created() {
// The below 2 lines make sure the Bootstrap CSS will be applied
var root = getShadowRoot("animal-guess");
root.applyAuthorStyles = true;
}
void newGame() {
gameinprogress=true;
win=false;
lost=false;
reachedend=false;
qid=1;
getQuestionById(qid);
}
void getQuestionById(qid)
{
var path='http://animal/get.php?id=$qid';
var req=new HttpRequest();
req..open('GET', path)
..onLoadEnd.listen((e)=>requestComplete(req))
..send('');
}
void requestComplete(HttpRequest req)
{
if (req.status==200)
{
Map res=JSON.decode(req.responseText);
myguess=res['q'];
yBranch=res['y'];
nBranch=res['n'];
if (yBranch==-1 && nBranch==-1) // No more branches and we have reached the "guess"
{
question='Is it a/an $myguess?';
}
else
{
question=myguess;
}
}
}
}
前3个import
语句导入此脚本中使用的必要库。 使用Polymer和DOM时,前两个是必需的,而解码JSON时,我们也需要第三个。 要查看其他软件包和库,请参阅API参考和软件包存储库 。
@CustomTag('animal-guess')
定义了我们将使用的自定义标签。 它具有与animalguess.html
和animalguessclass.html
出现的名称相同的名称。
在类定义中,我们看到一些变量声明。 Polymer使用@published
关键字声明一个“公共”变量(例如gameinprogress
标志,该标志指示游戏是否已启动并用于确定要显示哪个模板),并且可以在脚本以及相关的html文件中进行访问( animalguessclass.html
)。 这样,我们创建了“双向”数据绑定。
其余的是函数声明。 大多数功能将是上述animalguess.html
“ on-click
”事件的“事件处理程序”。 其他类型的事件处理程序也可用。
注意事项:
- 在类构造函数中,我们做了一个技巧,以确保可以将Bootstrap CSS应用于我们的自定义HTML标记(“
animal-guess
”)。 本文中的问题在Stackoverflow上进行了阐述。 基本上,Bootstrap“不了解ShadowDOM,而是尝试使用全局选择器从DOM中获取节点。” 但是在Polymer中,几乎要强制我们使用自定义元素,并且存在Shadow DOM。 因此,“转变”只是为了确保我们创建的ShadowDOM可与Bootstrap配合使用并具有我们想要CSS样式。 - 回调函数(
requestComplete
)连接到HttpRequest对象。 使用的语法在Polymer中是新的,称为“链接”方法调用。 它不同于单点符号,并且使用两个点。 它等效于以下3条语句:
req.open(...);
req.onLoadEnd(...)...;
req.send(...);
- 在
requestComplete
函数中,我们首先测试HTTP状态代码(200表示一切正常),然后使用Map类型变量存储解码后的JSON对象。 该变量将具有一个精确的“键值”对,作为从我们的远程服务器返回的JSON结果。 在我们的案例中,后端“远程”服务器位于同一台计算机上(在80端口上运行),并且在Dart中启动时,该应用程序将在3030端口上运行。 因此,从这个意义上讲,它们位于两个不同的域中,并且必须在返回的HTTP响应中显示CORS标头。
下面是计算机耗尽问题但做出错误猜测时的屏幕截图。 然后它提示输入一个新问题,以区分其猜测和用户的动物:
至此,该应用程序已经可以运行:后端提供数据,前端提供应用程序逻辑和表示。 至少可以完成一项改进:使用单选按钮表单控件来接收新问题的答案并限制用户的输入。 我留给你。
部署成为独立应用程序
当前程序只能在Dart自己的浏览器中运行(高度定制的基于Chrome的浏览器,支持Dart解释器–下载Dart SDK时会自动下载)。 为了使应用程序独立,我们可以将Dart应用程序编译为JavaScript。
为此,请在项目根目录中单击“ build.dart
”文件,然后选择“ Tools | Pub Build
。经过一些处理后,新的“ build
”目录将出现在项目根目录中,其中包含运行所需的所有文件它可以作为一个独立的应用程序。我们只需将所有这些文件复制到一个站点中,它将可以正常运行。
结论
在本教程中,我们使用现代技术(数据库,Dart和PHP)重新激活了旧版的Guess Animal AI游戏。 本教程的目的是演示所有部分的无缝集成,并以结构化的方式制作有用的富Web应用程序。
如果您有任何反馈或疑问,请在下面的评论中留下,我会尽快解决。 如果您发现本文有趣,并希望扩展本文的范围,请与您的朋友和同事分享,以便我们评估您的兴趣并做出相应的计划。
翻译自: https://www.sitepoint.com/dart-php-legacy-animal-guess-game/
dart dart2 区别