12/1/11

Sử dụng XForms để tạo trò chơi Sudoku riêng của bạn, Phần 2: Tạo trò chơi

Tóm tắt:  Chẳng có gì bí mật khi nói Sudoku là một trong những xu hướng mới nóng nhất được lưu hành. Có thể dễ dàng chơi trò chơi số này trên máy tính hoặc trên giấy, và vì bạn có thể dễ dàng phân tích dữ liệu theo một biểu mẫu bằng cách sử dụng XPath, nên với bạn việc sử dụng XForms để tạo một biểu mẫu cho phép bạn chơi Sudoku là rất có lợi. Loạt hai bài viết này cho bạn thấy cách tạo một máy khách trò chơi đòi hỏi các trò chơi mới từ máy chủ, phát hiện các di chuyển hợp pháp và bất hợp pháp và kết thúc trò chơi, và lưu lại trò chơi hiện tại cho lần chơi sau. Nó cũng cho bạn thấy cách tạo các trò chơi mới cho người chơi chơi. Phần 2 sẽ tải và lưu trữ các trò chơi.

Bài viết này giả định rằng bạn đã hiểu rõ những điều cơ bản của XForms. Để ôn luyện, hãy xem phần Tài nguyên để có các liên kết đến nội dung giúp bạn bắt đầu. Mã này đã được viết và thử nghiệm trên các phần mở rộng XForms của Mozilla Firefox, nhưng các khái niệm này áp dụng cho bất kỳ các công cụ nào. Để làm theo cùng với bài viết này, bạn sẽ cần một trình duyệt có hỗ trợ XForms -- bài viết này được viết bằng cách sử dụng phần mở rộng Mozilla và XForms -- và một máy chủ có hỗ trợ PHP. Để tạo ra các trò chơi câu đố Sudoku mới, bạn cũng sẽ cần có Python đã cài đặt, và chương trình Python Sudoku.

Làm thế nào bạn nhận được như ở đây
Trong Phần 1, bạn tạo ra trò chơi cơ bản, cho phép người chơi chơi Sudoku bằng cách sử dụng các trình đơn thả xuống đơn giản. Các nút Submit (Trình lên) đã không xuất hiện cho đến khi người chơi đã thành công trong việc giải trò chơi câu đố này. Cấu trúc của tài liệu XForms thực tế trông như Liệt kê 1.

Liệt kê 1. Trang hiện tại
<?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>

Tóm tắt, cá thể trò chơi này bao gồm một phần tử row cho mỗi hàng của mạng lưới ô vuông, và các phần tử square (ô vuông) để giúp mô phỏng các hàng cho việc tính toán các ô vuông 3x3 trên mạng lưới này. (Xem Phần 1 nếu bạn cần ôn lại về các quy tắc này). Liên kết phần tử correctRows với một tính toán cho phép bạn biết có bao nhiêu hàng, cột, và ô vuông đã được giải đúng. Khi tổng số lượt nhập là 27, nút Submit xuất hiện.
Để tạo mạng lưới ô vuông, hãy tạo vòng lặp qua mỗi row, và với mỗi box, tạo một danh sách thả xuống bằng cách tạo vòng lặp thông qua của các phần tử entry (nhập vào) trong cá thể templates (các khuôn mẫu). Nếu phần tử box có một giá trị, giá trị đó được chọn theo mặc định. Ngoài ra, nếu cá thể ban đầu cung cấp một số, ô vuông đó trên mạng lưới ô vuông là chỉ đọc.
Bảng trò chơi trông giống như Hình 1.

Hình 1. Trò chơi hiện tại
Trò chơi hiện tại
Bây giờ chúng ta hãy di chuyển lên.
Cải tiến giao diện
Bây giờ, sau khi bạn chơi trò chơi này một lúc, bạn có thể sẽ cảm thấy mệt mỏi vì sử dụng các trình đơn thả xuống. Thay vào đó, chỉ cần ghép vào số đúng còn dễ hơn. Để cho những người chơi làm điều đó, bạn không chỉ cơ cấu lại biểu mẫu này, mà còn tạo ra cách để giữ không cho họ nhập vào các giá trị không hợp lệ.
Hãy bắt đầu bằng cách gỡ bỏ các trình đơn thả xuống (xem Liệt kê 2).

Liệt kê 2. Thay thế các trình đơn thả xuống bằng các ô vuông văn bản
...
<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>
...

Bắt đầu ở phía dưới cùng, lưu ý rằng phần tử select1 đã được thay thế bằng một phần tử input (đầu vào) đơn giản, sẽ bao gồm các nội dung của phần tử box làm giá trị của nó. Thông thường, phần tử này sẽ diễn tả rộng hơn nhiều so với bạn cần nó, vì vậy sau đó bạn sẽ sử dụng các CSS (Bảng định kiểu xếp chồng) để thiết lập độ rộng của giá trị của nó. Lưu ý rằng trước tiên bạn phải khai báo bí danh vùng tên xforms và vùng tên.
Cuối cùng, một sự thay đổi dữ liệu thực tế đã được thực hiện. Trước đây, bạn sử dụng các số không để chỉ thị các ô vuông mà người chơi phải điền vào, nhưng vì bây giờ bạn đang đặt giá trị thực tế trong ô vuông đó -- bạn không còn thích một nhãn nữa, như trước đây -- bạn đã thay đổi nó thành một dấu chấm (.) để thấy rõ hơn những gì đang xảy ra. Bạn có thể xem kết quả trong Hình 2.

Hình 2. Sử dụng các đầu vào văn bản
Sử dụng các đầu vào văn bản
Bây giờ, vấn đề ở đây là không có gì ngăn cản không cho một người chơi nhập vào một giá trị vô nghĩa, ví dụ như "42" hoặc "bleh". May mắn thay, bạn có thể giải quyết điều đó.
Bắt tuân theo các ràng buộc
XForms có sẵn việc xác nhận hợp lệ lược đồ, vì vậy thật dễ dàng cho bạn đặt ra các ràng buộc về những gì mà người chơi có thể nhập vào trong các ô vuông văn bản đó. Ví dụ, bạn có thể quy định các phần tử đầu vào phải là các số nguyên (xem Liệt kê 3).

Liệt kê 3. Ràng buộc đầu vào theo các số nguyên
...
  <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>
...

Trước hết, bạn đang gõ cá thể này vào với vùng tên Lược đồ XML (XML Schema), và quy định rằng các phần tử box phải là các số nguyên. Nhưng không có điểm nào quy định điều đó trừ khi biểu mẫu hành động nếu dữ liệu không phù hợp.
Để nhận được biểu mẫu hành động, bạn có thể chỉ rõ một hành động được thực hiện nếu phần tử đầu vào xảy ra sự kiện xforms-invalid Khi nó xảy ra, biểu mẫu thiết lập giá trị của nó trở lại dấu chấm đơn giản và hiển thị một thông báo.
Bạn có thể kiểm tra điều này bằng cách thêm một giá trị không phải số nguyên, bạn có thể thấy trong Hình 3.

Hình 3. Nhập các giá trị không hợp lệ
Trang rỗng
Bây giờ, nếu bạn đã thử nghiệm điều này rồi, thì bạn có thể nhận thấy rằng thực sự bạn đã nhận được hộp thoại thông báo hai lần. Điều này là do bạn đang thiết lập giá trị cho một số không phải số nguyên, chính nó đã không hợp lệ.
May mắn thay, có một tùy chọn khác. Bạn có thể tạo một lược đồ quy định tất cả các giá trị được phép (xem Liệt kê 4).

Liệt kê 4. Lược đồ
<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>

Cụ thể, bạn quy định phần tử box phải là một trong các số nguyên từ 1 đến 9, hoặc dấu chấm. Sau đó, bạn có thể lưu trữ lược đồ này trong một tệp, sudoku.xsd, và tham khảo nó từ biểu mẫu (xem Liệt kê 5).

Liệt kê 5. Đính kèm lược đồ
...
  <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>
...

Bây giờ, nếu bạn chạy biểu mẫu này, bạn vẫn sẽ thấy hộp thoại cảnh báo, nhưng chỉ có một lần, vì theo lược đồ này giá trị mới được phép.
Lưu lại trò chơi hiện tại
Chắc chắn, bây giờ bạn đã nhận được giao diện đã chỉnh sửa, chúng ta hãy nói về cách quản lý trò chơi mà bạn đang trình bày cho người chơi.
Bước đầu tiên là cho phép người chơi lưu trò chơi hiện tại. Trong một biểu mẫu HTML truyền thống, việc này có nghĩa là các kịch bản lệnh phức tạp chấp nhận dữ liệu và lưu nó, sau đó thêm nhiều kịch bản lệnh hơn để lại lấy ra nó. May mắn thay, XForms làm cho việc này trở nên đơn giản hơn nhiều.
XForms cho phép bạn sử dụng phương thức "PUT" của HTTP để lưu dữ liệu cá thể vào một vị trí cụ thể. Nếu máy chủ Web của bạn được cấu hình đúng, bạn có thể lưu cá thể đó ở đó, nhưng thường lưu dữ liệu vào ổ đĩa cứng cục bộ (xem Liệt kê 6).

Liệt kê 6. Lưu vào một tệp cục bộ
...
  <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>

Ở đây bạn đã tạo ra một phần tử submission (trình lên) mới để chỉ rõ cá thể content (nội dung), và ra lệnh cho biểu mẫu không thay thế trang này, mà chỉ thay thế cá thể, với bất kỳ dữ liệu được trả về nào. Tuy nhiên, trong trường hợp này, không có bất kỳ dữ liệu được trả về, vì nó cũng chỉ rõ phương thức PUT và vị trí cho tệp đó. Điều này có nghĩa rằng khi bạn nhấn chuột vào nút đó, nó chỉ đơn giản lưu dữ liệu cá thể vào một tệp XML ở vị trí mà bạn đã chỉ định.
Nếu bạn lưu và tải biểu mẫu này, bạn sẽ thấy nút mới đó (xem Hình 4).

Hình 4. Nút Save
Nút Save
Thay đổi một vài giá trị và nhấn chuột vào nút Save (Lưu). Bạn sẽ thấy một tệp XML mới trong thư mục gốc của ổ đĩa C: của bạn đang chứa tài liệu cá thể như nó đã có khi bạn đã lưu nó. Bây giờ chúng ta hãy xem xét nó lại.
Tải một trò chơi đã lưu
Một khi bạn đã lưu một trò chơi, việc tải nó lại là khá đơn giản. Việc bạn muốn làm là có biểu mẫu đưa ra một yêu cầu HTTP và đặt dữ liệu vào trong cá thể. Bạn có thể làm điều đó bằng cách tạo phần tử submission khác (xem Liệt kê 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>

Trong trường hợp này, bạn đang đưa ra một yêu cầu GET đó là điều mà trình duyệt của bạn làm bất cứ khi nào bạn yêu cầu một trang Web mới. Khi nhận lại dữ liệu, nó chỉ thay thế các nội dung của cá thể nội dung. Để thấy yêu cầu này đang hoạt động, hãy lưu và tải biểu mẫu, sau đó thay đổi một vài giá trị. Lưu trò chơi, rồi tải lại biểu mẫu để đưa nó trở lại trạng thái ban đầu của nó. Nhấn vào nút Load saved game (Tải trò chơi đã lưu) để thấy các thay đổi của bạn xuất hiện lại.
Trình lên một trò chơi
Chắc chắn, bây giờ đây là một trò chơi thú vị và hơn nữa, nhưng bạn có thể chơi bao lâu? Không, bạn cần một cách để cho phép người chơi trình lên trò chơi hiện tại cho máy chủ và nhận được một trò chơi mới. Bạn sẽ xem xét việc trình lên thực tế tại một thời điểm, nhưng trước tiên bạn cần chỉnh sửa các thiết lập trình duyệt của bạn một chút.
Vì lý do an toàn, XForms chỉ có thể tải và lưu dữ liệu từ máy chủ mà từ đó nó đã được tải về ban đầu. Bây giờ, bạn có thể giải quyết một phần vấn đề bằng cách tải biểu mẫu lên máy chủ mà bạn sẽ yêu cầu dữ liệu từ đó. Nhưng nó không giải quyết tất cả các vấn đề của bạn.
Khó khăn thực sự là bạn đang lưu dữ liệu vào một tệp cục bộ, có nghĩa là nó không phải là máy chủ gốc. Để giải quyết vấn đề đó, bạn cần phải thêm máy chủ vào danh sách "các máy chủ tin cậy" có liên quan đến XForms.
Để làm điều đó, chọn Tools->Options và chắc chắn đánh dấu chọn hộp kiểm tra "Allow XForms to access other domains" (Cho phép XForms truy cập các miền khác). Tiếp theo, nhấn vào nút Allowed Sites (Các trang được phép). Thêm tên của máy chủ mà bạn đang làm việc với nó và đánh dấu chọn hộp kiểm tra Load and Save (Tải và Lưu). (Xem Hình 5.) Nhấn vào nút Add (Thêm) và đóng các hộp thoại lại. Khởi động lại trình duyệt để nhận được các thay đổi có hiệu lực.

Hình 5. Các trang tin cậy
Các trang tin cậy
Bây giờ bạn đã tạo ra việc trình lên thực tế. Cuối cùng, bạn sẽ bắt đầu các trò chơi mới của mình từ kích bản lệnh convertGame.php -- bạn cần xem xét kịch bản lệnh đó một chút -- vì thế hãy tiến lên và cập nhật phần tử submission này (xem Liệt kê 8).

Liệt kê 8. Trình lên toàn bộ
...
  </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"/>
...

Cũng như trước đây, bạn đã quy định rằng bạn chỉ muốn thay thế cá thể, chứ không phải toàn bộ trang, và đã chỉ rõ cá thể mà bạn muốn thay thế. Bạn cũng đã thêm vào địa chỉ URL cho kịch bản lệnh sẽ cung cấp các trò chơi mới của bạn.
Bắt đầu một trò chơi mới
Trừ khi bạn là một tay cừ khôi về toán học (hoặc muốn có nhiều thời gian thực hành), bạn sẽ không muốn tự mình tạo ra các trò chơi câu đố này. May mắn thay, bạn không phải làm.
Python Sudoku là một ứng dụng mã nguồn mở vừa tạo ra và vừa giải các trò chơi câu đố Sudoku. (Xem phần Tài nguyên để biết địa chỉ URL tải về). Nó được dự định để tạo ra các trò chơi câu đố trên báo và các ứng dụng khác, nhưng bạn sẽ cần thực hiện tinh chỉnh nhỏ -- và một máy chủ có hỗ trợ tạo kịch bản Python -- để làm cho nó tạo ra các câu đố trực tiếp theo dạng mẫu của bạn.
Thay vào đó, bạn sẽ tạo ra một số trò chơi câu đố không nối mạng (offline) và trả về chúng một cách ngẫu nhiên theo biểu mẫu. Để tạo ra các trò chơi câu đố này, hãy giải nén gói Python Sudoku và thực hiện lệnh sau từ thư mục mới được trích xuất (xem Liệt kê 9).

Liệt kê 9. Tạo một trò chơi câu đố mới
>>>>>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  _

Trong trường hợp này, tôi đã tạo ra một tệp gọi là game11.sdk. Hãy tạo ra một loạt các trò chơi câu đố này và đặt tên chúng là game1.sdk, game2.sdk, game3.sdk, và v.v.
Tất cả các tệp đều sử dụng cùng định dạng (xem Liệt kê 10).

Liệt kê 10. Trò chơi được tạo ra
# 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

Một khi bạn đã tạo ra các trò chơi, hãy di chuyển chúng đến một máy chủ mà trên đó bạn có thể thực thi PHP. Bạn sẽ tạo ra một kịch bản lệnh PHP, convertGame.php, chọn một tệp ngẫu nhiên và đọc dữ liệu để tạo ra một cá thể trả về theo dạng mẫu.
Kịch bản lệnh này trông giống như Liệt kê 11.

Listing 11. The convertGame.php script
<?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>';

?>

Để bắt đầu, bạn cần chọn trò chơi tiếp theo. Tại đây, bạn sẽ chọn một số nguyên ngẫu nhiên giữa 1 và 10 (gồm cả 10). Sau đó, bạn có thể sử dụng số nguyên đó để tạo ra tên tệp trả về cho trò chơi này. Từ đó, bạn có thể sử dụng hàm file() để trích xuất một mảng của từng dòng trong tệp.
Sau đó, bạn có thể bắt đầu xuất ra cá thể, bắt đầu với thẻ mở cho phần tử gốc, game. Với mỗi dòng, đầu tiên trích xuất tất cả các khoảng trống và báo hiệu xuống dòng ở cuối dòng. Một khi bạn đã làm xong, bạn có thể nói ra sự khác biệt giữa các dòng thực sự chứa dữ liệu và các dòng không chứa dữ liệu. Với mỗi dòng có chứa dữ liệu, bạn mở một phần tử row mới và tạo vòng lặp qua mỗi chữ số để tạo ra một phần tử box. Nếu chữ số đó là số không (0), bạn thay thế nó bằng một dấu chấm, nhưng nếu nó khác không, bạn cũng bao gồm thuộc tính chỉ đọc (ro) cho nó. Ở cuối mỗi dòng, bạn đóng phần tử row lại.
Một khi bạn đã giải quyết dữ liệu trong tệp trò chơi, bạn cần dữ liệu bổ sung, ví dụ như các phần tử square và các phần tử submitButtonElementcorrectRows. Cuối cùng, đóng phần tử game lại.
Nếu bạn tải biểu mẫu, lược đồ, và kịch bản lệnh convertGame.php lên máy chủ và gọi trò chơi trong trình duyệt, bạn có thể kiểm tra trò chơi. (Để tránh phải giải quyết từng trò chơi câu đố trước khi trình lên, hãy đưa ra nhận xét về phần tử bind ẩn dấu nút Submit). Nhấn nút Submit nhiều lần để thấy sự thay đổi trò chơi câu đố đó.
Đó chính là trò chơi!
Tóm tắt
Trong loạt hai bài viết này, bạn đã tạo ra một biểu mẫu XForms mô phỏng một trò chơi Sudoku. Trong Phần 1, bạn tạo ra biểu mẫu cơ bản, cho phép người chơi chơi trò này bằng cách sử dụng các trình đơn thả xuống. Biểu mẫu này tính toán xem trò chơi câu đố này đã được giải hay chưa và phản ứng sao cho phù hợp. Trong Phần 2, bạn đã thay đổi biểu mẫu để sử dụng các đầu vào văn bản, thêm các ràng buộc lược đồ để chắc chắn rằng người chơi không thể nhập vào dữ liệu không hợp lệ. Bạn cũng đã cung cấp cho người chơi khả năng lưu một trò chơi hiện cục bộ, và tải trò chơi đã lưu trở lại vào trong cá thể hiện tại. Cuối cùng, bạn xem xét một cách để tạo ra các trò chơi mới và cung cấp chúng theo biểu mẫu.

Tải tại đây: http://www.mediafire.com/?kl42232t3ovdpyo

Nguồn IBM
Bookmark and Share

0 comments:

Post a Comment

Next previous home

Cộng đồng yêu thiết kế Việt Nam Thiet ke website, danang