新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   >>中国XML论坛<<     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 讨论HTML、XHTML、Web2.0、Ajax、XUL, ExtJS, jQuery, JSON、Social Networking System(SNS)、Rich Internet Applications (RIA)、Tagging System、Taxonomy(tagsonomy,folkonomy)、XForms、XFrames、XInclude, XBL (XML Binding Language)等话题
    [返回] 中文XML论坛 - 专业的XML技术讨论区XML.ORG.CN讨论区 - XML技术『 HTML/XHTML/Ajax/Web 2.0/Web 3.0 』 → 使用 Xforms 创建您自己的数独游戏,第 2 部分: 创建游戏 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 3484 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 使用 Xforms 创建您自己的数独游戏,第 2 部分: 创建游戏 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     supremeweb 帅哥哟,离线,有人找我吗?
      
      
      等级:大三(要不要学学XML呢?)
      文章:87
      积分:661
      门派:XML.ORG.CN
      注册:2006/6/13

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给supremeweb发送一个短消息 把supremeweb加入好友 查看supremeweb的个人资料 搜索supremeweb在『 HTML/XHTML/Ajax/Web 2.0/Web 3.0 』的所有贴子 引用回复这个贴子 回复这个贴子 查看supremeweb的博客楼主
    发贴心情 使用 Xforms 创建您自己的数独游戏,第 2 部分: 创建游戏


    级别: 中级

    [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#author]Nicholas Chase[/URL] ([URL=mailto:ibmquestions@nicholaschase.com?subject=创建游戏&cc=dwxed@us.ibm.com]ibmquestions@nicholaschase.com[/URL]), 自由撰稿人, Backstop Media


    2007 年 5 月 14 日

    众所周知,数独(Sudoku)正在全球盛行。因为人们可以轻易地在计算机或纸上玩这个数字游戏,再加上使用 XPath 能很容易地在表单中分析数据,所以利用 XForms 创建能玩数独游戏的表单是可行的。[URL=http://www.ibm.com/developerworks/cn/views/xml/articles.jsp?view_by=search&search_by=%E4%BD%BF%E7%94%A8+XForms+%E5%88%9B%E5%BB%BA%E6%82%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E6%95%B0%E7%8B%AC%E6%B8%B8%E6%88%8F]本系列的两篇文章[/URL] 将介绍如何创建游戏客户机,该客户机能向服务器请求开始新游戏,检测合法和非法操作和游戏结束,保存当前游戏状态。同时还将介绍如何为用户生成新游戏。第 2 部分将探究载入和保存游戏。
    阅读本文需对 XForms 基础有一定的了解。要复习该内容,请参阅 [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#resources]参考资料[/URL] 部分的链接内容。代码是为 Mozilla Firefox XForms 扩展编写的,并且在该平台上已通过测试,不过其思想适用于任何实现。本文的代码是使用 Mozilla 和 Xforms 扩展编写的,因此要实现本文的代码,需要一个支持 Xforms 的浏览器和一个支持 PHP 的服务器。要生成新的数独迷题,还需要安装 Python 和 Python Sudoku 程序。

    Nick Chase 是一名 developerWork 播客

    在这个 [URL=http://www.ibm.com/developerworks/blogs/page/scott?entry=twodw_for_february_27_2007&S_TACT=105AGX52&S_CMP=cn-a-x]developerWork 播客[/URL] 中收听作者谈论他所着迷的数独游戏。


    回顾

    在 [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#part1]第 1 部分[/URL] 中,我们创建了基本的游戏,用户能够使用简单的下拉菜单玩数独游戏。只有当用户成功解答出了迷题时,Submit(提交)按钮才会出现。目前的 Xforms 文档结构如清单 1 所示。


    清单 1. 当前页面
                    
    <?xml version="1.0"?>
    <html xmlns="http://www.w3.org/1999/xhtml"       
          xmlns:xhtml="http://www.w3.org/1999/xhtml"
          xmlns:ev="http://www.w3.org/2001/xml-events"
          xmlns:xforms="http://www.w3.org/2002/xforms"
          xmlns:svg="http://www.w3.org/2000/svg"
          xmlns:s="http://www.example.com/sudoku"
          xmlns:b="http://www.example.com/board">

      <head>
        <title>Sudoku</title>

    <xforms:model>

      <xforms:instance id="content">
        <s:game>

          <s:row><s:box ro="yes">6</s:box><s:box></s:box>
    <s:box></s:box><s:box></s:box><s:box></s:box>
    <s:box ro="yes">9</s:box><s:box></s:box><s:box></s:box>
    <s:box ro="yes">1</s:box></s:row>
    ...
          
    <s:square><s:box>0</s:box><s:box>0</s:box><s:box>0</s:box>
    <s:box>0</s:box><s:box>0</s:box><s:box>0</s:box><s:box>0
    </s:box>
    <s:box>0</s:box><s:box>0</s:box></s:square>
    ...
          <s:submitButtonElement>Submit</s:submitButtonElement>
          <s:correctRows>no</s:correctRows>

        </s:game>
      </xforms:instance>

      <xforms:bind nodeset="//s:row//s:box[@ro='yes']" readonly="true()" />

      <xforms:bind nodeset="//s:submitButtonElement"  
                                 relevant="/s:game/s:correctRows = 27" />

      <xforms:bind nodeset="//s:correctRows" calculate=
         "count(/s:game/s:row[s:box = '1'][s:box = '2'][s:box = '3']
    [s:box = '4'][s:box = '5'][s:box = '6'][s:box = '7'][s:box = '8']
    [s:box = '9']) +
          count(/s:game[s:row[s:box[1]='1']][s:row[s:box[1]='2']]
    [s:row[s:box[1]='3']][s:row[s:box[1]='4']][s:row[s:box[1]='5']]
    [s:row[s:box[1]='6']][s:row[s:box[1]='7']][s:row[s:box[1]='8']]
    [s:row[s:box[1]='9']]) +
    ...
          count(/s:game/s:square[s:box = '1'][s:box = '2']
    [s:box = '3'][s:box = '4'][s:box = '5'][s:box = '6']
    [s:box = '7'][s:box = '8'][s:box = '9'])" />

      <xforms:instance id="templates">
        <b:template>
          <b:entry><b:sendvalue>0</b:sendvalue>
                   <b:display></b:display></b:entry>
          <b:entry><b:sendvalue>1</b:sendvalue>
                   <b:display>1</b:display></b:entry>
          <b:entry><b:sendvalue>2</b:sendvalue>
                   <b:display>2</b:display></b:entry>
    ...
        </b:template>
      </xforms:instance>

      <xforms:submission id="submitgame" action="" method="post"/>

    </xforms:model>

    <style type="text/css">

       div > * {display: inline;}

       *:read-only { color: red }

    </style>

    </head>
      <body>

        <img src="images/showlayout.gif" style="float:left;height: 64px; width: 64px;" />

        <h1 align="center">Sudoku</h1>

        <br clear="left" />

        <div>
          <xforms:repeat id="gamerow" nodeset="instance('content')/s:row">

            <xforms:repeat id="gamebox" nodeset="s:box">
            
              <span class="test"><xforms:select1 ref=".">
                 <xforms:itemset nodeset="instance('templates')/b:entry">
                    <xforms:label ref="b:display"/>
                    <xforms:value ref="b:sendvalue"/>
                 </xforms:itemset>
              </xforms:select1></span>
            </xforms:repeat>
          </xforms:repeat>
        </div>

        Correct Rows: <xforms:output ref="//s:correctRows" /><br />

        <xforms:trigger style="display:block">
              <xforms:label>Check it!</xforms:label>
              <xforms:action ev:event="DOMActivate">

              <xforms:setvalue ref="/s:game/s:square[1]/s:box[1]"
                                    value="/s:game/s:row[1]/s:box[1]" />
              <xforms:setvalue ref="/s:game/s:square[1]/s:box[2]"
                                     value="/s:game/s:row[1]/s:box[2]" />
    ...
              </xforms:action>
          </xforms:trigger>

          <xforms:submit ref="/s:game/s:submitButtonElement"
                         submission="submitgame">
             <xforms:label>Submit</xforms:label> 
          </xforms:submit>

      </body>
    </html>


    回顾一下,实例为表格中的每一行都提供了一个 row 元素,另外还包含一个 square 元素用于为计算表格中的 3x3 方块模拟行数据。(要复习规则请参阅 [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#part1]第 1 部分[/URL]。)将 correctRows 元素与一个计算绑定在一起,它可以计算出成功解答出的行数、列数和方格数。当总数达到 27 时 Submit 按钮就会出现。

    要创建表格,需要循环遍历每一个 row 元素,通过遍历 templates 实例中的每个 entry 元素为每个 box 元素创建一个下拉列表。如果 box 元素具有一个值,这个值是默认选定的。同样,如果原始实例提供了数值,那么表格上的方框将是只读属性的。

    面板如图 1 所示。


    图 1. 当前的游戏
    按此在新窗口浏览图片

    现在让我们继续创建数独游戏。


      

    增强界面

    玩了一段时间以后,可能会感觉到使用下拉菜单太累了,而直接填入正确的数字会更轻松一点。要达到这个目的,不仅需要重新构造表单,同时还需要避免输入无效值。

    先从去除下拉菜单开始(参见清单 2)。


    清单 2. 使用文本框替代下拉菜单
                    
    ...
    <xforms:model>

      <xforms:instance id="content">
        <s:game xmlns:s="http://www.example.com/sudoku">
          <s:row><s:box s:ro="yes">6</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box s:ro="yes">9</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box s:ro="yes">1</s:box></s:row>
    ...
          
    <s:square><s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box><s:box>.
    </s:box>
    <s:box>.</s:box><s:box>.</s:box></s:square>
    ...
          <s:submitButtonElement>Submit</s:submitButtonElement>
          <s:correctRows>no</s:correctRows>

        </s:game>
      </xforms:instance>

    ...
    <style type="text/css">


       @namespace xforms url(http://www.w3.org/2002/xforms);

       div > * {display: inline;}

       *:read-only { color: red }

       xforms|input .xf-value, .input-value {width: 30px;
                                                            background-color: white;}

    </style>

    </head>
      <body>

        <img src="images/showlayout.gif" style="float:left;height: 64px; width: 64px;" />

        <h1 align="center">Sudoku</h1>

        <br clear="left" />

        <div>
          <xforms:repeat id="gamerow" nodeset="instance('content')/s:row">
            <xforms:repeat id="gamebox" nodeset="s:box">
                <span>
                    <xforms:input ref="." />
                </span>
            </xforms:repeat>
          </xforms:repeat>
        </div>
    ...


    首先注意到代码的底部,select1 元素被一个简单的 input 元素替代了,该元素把 box 元素的内容作为它的值。通常来说,该元素值设定的宽度比我们需要的宽度要宽很多,所以还需使用级联样式表来设置该元素值的宽度。注意,在这之前必须先声明 xforms 的名称空间别名和名称空间。

    最后,还要修改现行的数据。之前,我们使用 0 表示用户需要填入的方框,但因为现在是直接在方框中输入当前值(不用像原来一样使用标签),我们把它改成用句点(. )表示,这样也显示地更加清楚。最后显示的结果如图 2 所示。


    图 2. 使用文本输入
    按此在新窗口浏览图片

    现在,还有一个问题就是不能防止用户输入无效的值,例如 “42” 或者 “bleh”。幸运的是,我们可以改进一下。


      

    强制限制

    Xforms 内建有模式确认(schema validation),因此我们可以轻松地限制用户能输入文本框的值。比如说,我们可以指定输入必须为整数(如清单 3 所示)。


    清单 3. 限制输入为整数
                    
    ...
      <xforms:instance id="content">
        <s:game xmlns:s="http://www.example.com/sudoku"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <s:row><s:box xsi:type="xsd:int"  
    s:ro="yes">6</s:box><s:box xsi:type="xsd:int"
    >.</s:box><s:box xsi:type="xsd:int" >.</s:box>
    <s:box xsi:type="xsd:int" >.</s:box><s:box
    xsi:type="xsd:int"
    >.</s:box><s:box
    xsi:type="xsd:int"
    s:ro="yes">9</s:box><s:box xsi:type="xsd:int" >.</s:box>
    <s:box xsi:type="xsd:int"
    >.</s:box><s:box
    xsi:type="xsd:int"  
    s:ro="yes">1</s:box></s:row>
    ...
        </s:game>
      </xforms:instance>
    ...
        <div>
          <xforms:repeat id="gamerow" nodeset="instance('content')/s:row">
            <xforms:repeat id="gamebox" nodeset="s:box">
                <span>
                    <xforms:input ref=".">
                                       <xforms:action ev:event="xforms-invalid">
                                           <xforms:setvalue ref=".">.</xforms:setvalue>
                                           <xforms:message level="modal">Please
                                                     choose an integer from 1 to
                                                     9.</xforms:message>
                                       </xforms:action>
                                    </xforms:input>
                </span>
            </xforms:repeat>
          </xforms:repeat>
        </div>
    ...


    首先,将实例与 XML Schema 名称空间连接起来,并指定 box 元素必须为整数。但是如果表单对不符合类型的数据置之不理的话,这样的指定是没有意义的。

    要使表单有所举动,可以指定当输入元素遇到 xforms-invalid 事件时表单采取的动作。当事件发生时,表单将把数值重新设置为句点并显示提示信息。

    可以添加一个非整数值测试一下,如图 3 所示。


    图 3. 输入无效的值
    按此在新窗口浏览图片

    此时,当您测试时您可能会发现消息框实际上出现了两次。这是因为您把值设置成了非整数,而非整数本身就是无效的输入。

    幸运的是,还有另一种选择。我们可以创建一个模式,让它指定所有允许输入的值(如清单 4 所示)。


    清单 4. 模式
                    
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       targetNamespace="http://www.example.com/sudoku"
       xmlns="http://www.example.com/sudoku">

      <xsd:element name="game" type="GameType"/>
      <xsd:element name="row" type="RowType"/>
      <xsd:element name="square" type="RowType"/>

      <xsd:element name="box" type="BoxType"/>
      
      <xsd:element name="submitButtonElement" type="ButtonType" />
      <xsd:element name="correctRows" type="CorrectRowsType" />

      <xsd:simpleType name="ButtonType">
         <xsd:restriction base="xsd:string" />
      </xsd:simpleType>
      <xsd:simpleType name="CorrectRowsType">
         <xsd:restriction base="xsd:int" />
      </xsd:simpleType>

    <xsd:simpleType name='BoxType'>
                       <xsd:restriction base="xsd:string">
                           <xsd:enumeration value = "."/>
                           <xsd:enumeration value = "1"/>
                            <xsd:enumeration value = "2"/>
                           <xsd:enumeration value = "3"/>
                           <xsd:enumeration value = "4"/>
                           <xsd:enumeration value = "5"/>
                           <xsd:enumeration value = "6"/>
                            <xsd:enumeration value = "7"/>
                           <xsd:enumeration value = "8"/>
                           <xsd:enumeration value = "9"/>
                        </xsd:restriction>
                    </xsd:simpleType>

      <xsd:complexType name="RowType">
        <xsd:sequence>
          <xsd:element ref="box" minOccurs="9" maxOccurs="9" />
        </xsd:sequence>
      </xsd:complexType>

      <xsd:complexType name="GameType">
        <xsd:sequence>
          <xsd:element ref="row" minOccurs = "9" maxOccurs="9" />
          <xsd:element ref="square" minOccurs = "9" maxOccurs="9" />
          <xsd:element ref="submitButtonElement" minOccurs="1"
                                                 maxOccurs="1"  />
          <xsd:element ref="correctRows" minOccurs="1" maxOccurs="1" />
        </xsd:sequence>
      </xsd:complexType>

    </xsd:schema>


    我们明确地指定了 box 元素只能为 1-9 的整数或者为句点。然后把这个模式保存为文件 sudoku.xsd,再从表单中引用它(如清单 5 所示)。


    清单 5. 引用模式文件
                    
    ...
      <head>
        <title>Sudoku</title>

    <xforms:model schema="./sudoku.xsd">

      <xforms:instance id="content">
        <s:game xmlns:s="http://www.example.com/sudoku"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
          <s:row><s:box s:ro="yes">6</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box s:ro="yes">9</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box s:ro="yes">1</s:box></s:row>
    ...


    这时再运行表单,我们仍然会看到警示框,不过它只会出现一次,因为根据模式新值是允许输入的。


      

    保存当前游戏

    现在已经调整了界面,接下来我们再讨论一下游戏的管理。

    第一步是允许用户保存当前游戏。在传统的 HTML 表单中,可以使用复杂的脚本接收数据并保存数据,然后更多的脚本再从中取回。幸运的是,在 Xforms中有更简单的方法

    Xforms 允许使用 HTTP 的 “PUT” 方法把实例数据保存到特定的位置。如果 Web 服务器经过正确配置,可以把实例保存在服务器上,但是把数据保存在本地磁盘上是更常用的方法(如清单 6 如示)。


    清单 6. 保存到本地文件
                    
    ...
      <xforms:submission id="submitgame" action="" method="post"/>

      <xforms:submission id="savegame" action="file:///c:/sudoku.txt"
                           replace="instance" instance="content" method="put"/>

    </xforms:model>
    ...
          <xforms:submit ref="/s:game/s:submitButtonElement" submission="submitgame">
             <xforms:label>Submit</xforms:label> 
          </xforms:submit>

          <xforms:submit submission="savegame">
                             <xforms:label>Save current game</xforms:label> 
                         </xforms:submit>

      </body>
    </html>


    此处我们创建了一个新的 submission 元素,它指定了 content 实例并通知表单使用返回的数据替代实例,而不是页面。然而在本例中,并没有任何返回的数据,因为它还指定了 PUT 方法和存放文件的位置。这样的话当您单击该按钮,它便会把实例数据保存在指定位置下的 XML 文件中。

    如果需要保存和载入表单,可以使用这个新按钮(如图 4 所示)。


    图 4. 保存按钮
    按此在新窗口浏览图片

    更改一些值并单击 Save(保存)按钮。在 C 盘根目录下将会出现一个 XML 文件,其中包含了刚才保存的实例文档。接下来看看如何将其取回。


      

    载入保存的游戏

    一旦我们保存了一个游戏,载入它非常简单。我们要做的就是让表单发送一个 HTTP 请求,然后把数据放入实例中去。这可以通过再创建一个 submission 元素来实现(如清单 7 所示)。


    清单 7. 载入数据
                    
    ...
      <xforms:submission id="savegame" action="file:///c:/sudoku.txt"
            replace="instance" instance="content" method="put"/>

      <xforms:submission id="loadgame" action="file:///c:/sudoku.txt"
                            replace="instance" instance="content" method="get"/>

    </xforms:model>

    <style type="text/css">
    ...
          <xforms:submit submission="savegame">
             <xforms:label>Save current game</xforms:label> 
          </xforms:submit>

          <xforms:submit submission="loadgame">
                            <xforms:label>Load saved game</xforms:label> 
                          </xforms:submit>

      </body>
    </html>


    在这种情况下,我们通过发送 GET 请求取回数据,浏览器就是使用它请求新 Web 页面的。然后再用取回的数据替代 content 实例中的内容。要查看是否起作用,先保存然后再载入表单,然后改变一些值。保存游戏,然后重新载入表单使游戏回到初始状态。单击 Load saved game(载入保存游戏) 按钮,可以看到我们改变的值又出现了。


      

    提交游戏

    现在这个游戏已经非常吸引人了,但不能总是玩这一个游戏吧?当然不会了,我们应该使用户能够向服务器提交当前游戏并获得一个新游戏。稍后您将看到真正的 submission 元素,但是在这之前我们需要调整一下浏览器的设置。

    出于安全性考虑,Xforms 只能在最初下载的服务器中载入和保存数据。将表单上传到请求数据的服务器可以解决部分问题。但是问题并没有全部解决。

    难点在于事实上我们把数据保存在本地文件中,而不是初始服务器上。要解决这个问题,我们需要在 Xforms 的 “信任服务器” 列表中添加服务器。

    为此,选择 Tools->Options 并确保复选框中选择了 “Allow XForms to access other domains”。下一步,单击 Allowed Sites 按钮。添加您所需的服务器名称并选中 Load and Save 复选框。(参见图 5)单击 Add 按钮然后关闭对话框。重启浏览器使修改生效。


    图 5. 受信任站点
    按此在新窗口浏览图片

    现在可以开始创建真正的 submission 元素了。从根本上说,我们使用了一个 convertGame.php PHP 脚本用于获得新游戏。稍后我们将看到该脚本。现在还是先更新一下 submission 元素。(如清单 8 所示)。


    清单 8. 完整的 submission 元素
                    
    ...
      </xforms:instance>

      <xforms:submission id="submitgame"
            action="http://www.backstopmedia.com/sudoku/convertGame.php"
                      replace="instance" instance="content" method="post"/>

      <xforms:submission id="savegame" action="file:///c:/sudoku.txt"
            replace="instance" instance="content" method="put"/>
    ...


    和之前一样,我们指定只替代实例而不是整个页面,以及需要替代的实例。同时还添加了将为我们提供新游戏的脚本的 URL。


      

    获取新游戏

    除非您是一个数学能手(或者有太多空闲的时间),否则您是不可能独自生成这些迷题的。幸运的是,您也没必要这样做。

    Python Sudoku 是一个开放源码的应用程序,能够生成和解答数独迷题。(查看 [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#resources]参考资料[/URL] 获得下载 URL) 它用于生成迷题,可供纸上解答或供其它应用程序使用。不过我们还需要进行一些调整(以及一个支持 Python 脚本的主机)使它能直接向表单输出迷题。

    我们将在线下生成许多的迷题,然后随机地把它们返回给表单。要创建这些迷题,解压 Python Sudoku 压缩包并在刚解压的目录下执行如下命令(参见清单 9)。


    清单 9. 创建新的迷题
                    
    >>>>>python pysdk.py -c game11.sdk
    Creating sudoku... success!
    1  _  _    _  _  _    5  _  _
    _  _  _    6  _  _    9  _  _
    _  _  _    3  4  _    _  _  _

    _  _  _    _  _  _    _  1  _
    _  8  _    _  _  2    _  _  9
    7  9  2    _  _  5    _  _  _

    _  _  8    _  3  _    _  6  _
    _  _  _    _  _  _    _  _  _
    _  2  4    1  _  8    _  3  _


    在本例中,我们创建了一个 game11.sdk 文件。创建一系列这样的迷题并把它们保存为 game1.sdk、game2.sdk、game3.sdk 等等。

    这些文件都使用相同的格式(如清单 10 所示)。


    清单 10. 生成的游戏
                    
    # boardsize 3 x 3
      1  0  0    0  0  0    5  0  0
      0  0  0    6  0  0    9  0  0
      0  0  0    3  4  0    0  0  0

      0  0  0    0  0  0    0  1  0
      0  8  0    0  0  2    0  0  9
      7  9  2    0  0  5    0  0  0

      0  0  8    0  3  0    0  6  0
      0  0  0    0  0  0    0  0  0
      0  2  4    1  0  8    0  3  0


    生成游戏后,把它们移到能执行 PHP 的服务器上面去。这时再创建一个 convertGame.php PHP 脚本,用于随机地选取文件并读取数据,然后创建一个返回给表单的实例。

    该脚本如清单 11. 所示。


    清单 11. convertGame.php 脚本
                    
    <?php

    $nextGame = rand(1, 10);

    $lines = file('game'.$nextGame.'.sdk');

    echo '<s:game xmlns:s="http://www.example.com/sudoku">';

    foreach ($lines as $line_num => $line) {

        $line = str_replace(" ", "", $line);
        $line = str_replace("\n", "", $line);

        if ($line_num > 0 && $line != '') {

           echo "<s:row>";

           for ($x = 0; $x < 9; $x++){
                $thisBox = substr($line, $x, 1);
                if ($thisBox == "0") {
                    echo "<s:box>.</s:box>";
                } else {
                    echo "<s:box s:ro='yes'>".$thisBox."</s:box>";
                }
           }

           echo "</s:row>";

        }


    }

    echo "      <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:square><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box><s:box>.</s:box><s:box>.</s:box>
    <s:box>.</s:box></s:square>
          <s:submitButtonElement>Submit</s:submitButtonElement>
          <s:correctRows>no</s:correctRows>";
    echo '</s:game>';

    ?>


    要开始,需要选择下一个游戏。这里,我们随机地选择 1-10(包含 1 和 10)的整数。然后可以使用这个整数创建用于返回游戏的文件名。然后,使用 file() 函数解压文件中各行中的一组数据。

    然后便可以开始输出实例,从根元素 game 打开标记开始。对于每一行,首先解压所有的空格和行末的换行符。完成这步这后,我们能够分辨各行之间的不同,哪些行真正包含了数据而哪些行没有。对这样的每一行,打开一个新的 row 元素然后遍历其中的的每个数字并创建一个 box 元素。如果数字为 0,则把它替换成句点,如果不为 0,则设置为只读属性(ro)。遍历到每一行的末尾,则关闭 row 元素。

    如果您是在游戏文件中处理数据,那么将需要一些额外的数据,例如 square 元素、submitButtonElement 元素和 correctRows 元素。最后,关闭 game 元素。

    如果您把表单、模式和 convertGame.php 脚本装载在服务器中,并在浏览器中调用它们,可以对其进行测试。(为避免在每次提交之前都必须把迷题解答出来,隐藏在 Submit 按钮之后的 bind 元素被注释掉了。)重复点击 Submit 按钮查看迷题的变化。

    就这么简单!

      
    结束语

    在 [URL=http://www.ibm.com/developerworks/cn/views/xml/articles.jsp?view_by=search&search_by=%E4%BD%BF%E7%94%A8+XForms+%E5%88%9B%E5%BB%BA%E6%82%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E6%95%B0%E7%8B%AC%E6%B8%B8%E6%88%8F]本系列的两篇文章[/URL] 中,我们创建了一个模拟数独游戏的 Xforms 表单。在 [URL=http://www.ibm.com/developerworks/cn/xml/x-xformssudoku2/index.html#part1]第 1 部分[/URL] 中,我们创建了基本的表单,使用户能够使用下拉菜单玩数独游戏。表单计算迷题是否被解答出来,并根据相应情况做出反应。在第 2 部分中,我们把表单修改成使用文本输入,并且添加了模式约束使用户不能输入无效数据。同时使用户能够在本地保存现有游戏,并能将保存的游戏载入到当前实例。最后,我们探讨了创建新游戏以及如何将它们提供给表单的方法。


       收藏   分享  
    顶(0)
      




    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/5/16 16:25:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 HTML/XHTML/Ajax/Web 2.0/Web 3.0 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/26 5:30:15

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    125.000ms