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
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
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ệ
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
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
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ử submitButtonElement
và
correctRows
. 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
Tải tại đây: http://www.mediafire.com/?kl42232t3ovdpyo
Nguồn IBM
0 comments:
Post a Comment