Tải bản đầy đủ (.pdf) (14 trang)

CÔNG NGHỆ PHẦN MỀM ĐỀ TÀI GAMES TRÒ CHƠI CỜ VUA PHẦN I: GIỚI THIỆU TRÒ CHƠI_phần 1 doc

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (566.15 KB, 14 trang )

CÔNG NGHỆ PHẦN MỀM -
ĐỀ TÀI GAMES TRÒ CHƠI
CỜ VUA

PHẦN I: GIỚI THIỆU TRÒ CHƠI CỜ VUA
- Cờ vua, trước kia còn được gọi là cờ quốc tế, là một trò chơi trên bàn và là một
môn thể thao trí tuệ cho 2 người chơi. Ngày nay, cờ vua là một trong những trò
chơi phổ biến nhất thế giới với hàng triệu người tại nhà riêng, trong câu lạc bộ,
trực tuyến, từ xa và trong các giải đấu.
- Trò chơi này diễn ra trên một bảng hình vuông, gọi là bàn cờ, gồm 8 hàng
(đánh số từ 1 đến 8) và 8 cột (đánh số từ a đến h), tạo ra 64 ô hình vuông với các
màu đậm và nhạt xen kẽ nhau, với mỗi người chơi sẽ có ô màu nhạt ở hàng cuối
cùng bên tay phải của mình khi ngồi vào bàn chơi cờ. Mỗi người sẽ bắt đầu ván cờ
với 16 quân cờ và sẽ lần lượt đi các quân của mình sau khi đối phương đã đi xong
một nước (hoàn thành nước đi).
- Quân cờ
Vua
Hậu
Xe
Tượng

Tốt
-Cách xếp cờ

-Quy tắc chơi
Khi một ván cờ vua bắt đầu, một người chơi sẽ cầm quân đen và người chơi còn
lại cầm quân trắng. Việc chọn lựa ai sẽ cầm quân đen hay trắng phụ thuộc vào thể
thức chơi là giải trí hay thi đấu trong hệ thống có tổ chức. Nó có thể là do hai
người thỏa thuận (giải trí) hoặc do quyết định của trọng tài trong giải đấu . Bên
cầm quân trắng luôn luôn được đi trước và do đó có một ưu thế nhỏ so với bên cầm
quân đen. Các quân cờ cần phải xếp trên bàn cờ tiêu chuẩn với ô nằm ở hàng cuối


cùng bên tay phải người chơi bao giờ cũng có màu nhạt.
-Các quân cờ có nước đi khác nhau:
+ Xe (ký hiệu quốc tế R) di chuyển theo các đường thẳng dọc theo cột hay hàng
tới ô còn trống mà không có quân nào cản trên đường đi hay tới ô bị quân đối
phương chiếm giữ (ăn quân) nhưng không thể vượt qua quân đang đứng ở ô đó.
Ngoại lệ duy nhất là trường hợp nhập thành. Khi đó nó có thể nhảy qua quân Vua
của mình để đứng cạnh nó. Chỉ có Xe mới có nước đi như thế.
+ Tượng (ký hiệu quốc tế B) di chuyển theo đường chéo tới ô có cùng màu với
nguyên lý tương tự như Xe tới ô còn trống hay ô bị quân đối phương chiếm giữ
(ăn quân).
+ Hậu (ký hiệu quốc tế Q) có nước đi là tổ hợp đơn giản của chuyển động của
Xe và Tượng. Trong một nước đi nó có thể di chuyển theo đường chéo hoặc
đường thẳng dọc theo cột hay hàng, với nguyên lý đi và ăn quân giống như
Tượng và Xe.
+ Mã (ký hiệu quốc tế N) có thể di chuyển tới ô còn trống hay ô bị quân đối
phương chiếm giữ (ăn quân) theo dạng hình chữ L. Quân Mã không bị cản như
trong cờ tướng.
+ Tốt (không cần ký hiệu) có thể di chuyển thẳng về phía trước chỉ một ô một
lần tới ô còn trống (đi mà không ăn quân), nhưng khi di chuyển quân để ăn quân
đối phương thì đi chéo. Ví dụ, Tốt trắng tại ô c4 có quyền ăn quân đối phương tại
b5 hoặc d5 nếu một trong hai ô này có quân đối phương chiếm hoặc di chuyển
xuống ô c5 nếu ô này còn trống, trừ hai trường hợp sau:
* Nó có thể di chuyển 1 hoặc 2 ô nếu nó đi từ vị trí xuất phát ban đầu tới ô
chưa bị chiếm giữ, nhưng không thể nhảy qua một quân khác để tới ô đó. Ví dụ
Tốt trắng tại g2 có thể đi tới g3 hoặc g4 nếu đây là nước đi đầu tiên của nó và
các ô này chưa bị chiếm giữ, nhưng nó không thể đi tới g4 nếu ô g3 đã có một
quân nào đó chiếm giữ.
* Trong trường hợp khi một quân Tốt nào đó của bên trắng đạt tới hàng 5 (ví
dụ tới ô e5) và quân Tốt thuộc một trong hai cột của bên đen nằm ngay bên cạnh
cột mà Tốt trắng này đang chiếm giữ (trong trường hợp đã cho là cột d và cột f)

đi từ vị trí xuất phát đầu tiên (d7 hay f7) nhảy liền 2 ô tới ô d5/f5 thì Tốt trắng
tại vị trí e5 ngay tại nước đi sau đó có quyền ăn Tốt đen tại ô d5/f5 và di chuyển
tiếp tới ô d6/f6. Quyền này sẽ tự động mất, nếu tại nước đi ngay sau đó quân
trắng di chuyển quân khác. Tương tự như vậy cho Tốt đen khi nó đã chiếm giữ
hàng 4. Đây là trường hợp mà trong cờ vua người ta gọi là bắt tốt qua đường (en
passant).
*Tốt còn một đặc điểm nữa là khi nó di chuyển đến hàng cuối cùng thì người
chơi có quyền phong cấp cho nó thành bất kỳ quân nặng hay nhẹ nào (Hậu, Xe,
Tượng, Mã).
+ Vua (ký hiệu quốc tế là K) là quân quan trọng nhất, nếu mất Vua thì người
chơi thua cuộc. Mỗi lần đi nó có thể ăn quân hoặc di chuyển sang các ô bao
quanh ô mà nó hiện tại đang chiếm giữ, nhưng không thể tới ô mà quân của mình
đang chiếm giữ hay các ô bị quân đối phương kiểm soát. Ngoại lệ duy nhất là
trường hợp nhập thành. Khi đó nó có thể di chuyển qua hai ô đồng thời với việc
di chuyển quân Xe của mình để quân Xe đó đứng bên cạnh nó về phía cột trung
tâm. Ký hiệu của nhập thành là 0-0 (nhập thành gần) và 0-0-0 (nhập thành xa).
*Lưu ý: Khi thực hiện nhập thành trên thực tế, theo luật của FIDE, bao giờ cũng
phải di chuyển Vua trước và thực hiện bằng một tay duy nhất.
+ Khi ăn quân đối phương, quân tấn công sẽ di chuyển tới ô đó và thay thế cho
quân đối phương tại vị trí này, bắt tốt qua đường (en passant) là ngoại lệ duy
nhất. Quân bị ăn được loại ra khỏi bàn cờ. Vua không thể không bảo vệ khỏi nước
chiếu, do đó khi bị chiếu thì người chơi phải thực hiện các biện pháp nhằm cứu
Vua (di chuyển Vua khỏi vị trí bị chiếu, ăn quân đang chiếu hay dùng quân khác
của mình cản đường chiếu nếu có thể). Nếu không thể có nước đi để cứu Vua thì
người chơi bị chiếu bí và thua cuộc.
+ Các ván cờ không phải bao giờ cũng kết thúc bằng chiếu bí. Có thể một bên
xin thua, có thể thua do hết giờ hoặc phạm luật chơi. Có thể xảy ra các ván cờ
hòa. Một ván cờ vua là hòa khi: do thỏa thuận của hai bên do không bên nào dám
mạo hiểm hay khi không đủ lực lượng để chiếu hết, rơi vào trạng thái hết nước đi
(stalemate), cả hai bên lặp lại nước đi ba lần hay luật 50 nước đi (perpetual

check).

PHẦN II: CÁC LÝ THUYẾT LIÊN QUAN

Sau đây là quá trình tạo một ứng dụng mạng kiểu TCP
Server
* Tạo ServerSocket
* Gọi thực thi phương thức accept() để chấp nhận thiết lập kết nối với Client =>
nhận được Socket giao tiếp với Client.
* Lấy InputStream và OutputStream để nhận và gửi dữ liệu với Client.
* Gửi và nhận dữ liệu với Client, sử dụng các phương thức read() và write() của
các lớp đối tượng InputStream và OutputStream.
* Đóng Socket và ServerSocket
* Kết thúc chương trình
Client
* Tạo Socket kết nối đến Server
* Lấy InputStream và OutputStream để nhận và gửi dữ liệu với Server.
* Gửi và nhận dữ liệu với Server, sử dụng các phương thức read() và write() của
các lớp đối tượng InputStream và OutputStream.
* Đóng Socket
* Kết thúc chương trình

I/ SOCKET
Một socket có thể thực hiện bảy thao tác cơ bản:
• Kết nối với một máy ở xa (ví dụ, chuẩn bị để gửi và nhận dữ liệu
• Gửi dữ liệu
• Nhận dữ liệu
• Ngắt liên kết
• Gán cổng
• Nghe dữ liệu đến

• Chấp nhận liên kết từ các máy ở xa trên cổng đã được gán.
Có nhiều kiểu Socket khác nhau tương ứng với mỗi kiểu giao thức được sử dụng
để giao tiếp giữa hai máy trên mạng Internet. Đối với chồng giao thức TCP/IP, có
hai kiểu Socket chính được sử dụng là stream socket và datagram socket. Stream
socket sử dụng giao thức TCP để cung cấp dịch vụ gửi dữ liệu tin cậy. Datagram
socket sử dụng giao thức UD để cung cấp dịch vụ gởi gói tin đơn giản. Ngôn ngữ
lập trình Java hỗ trợ lớp Socket và ServerSocket cho kiểu stream socket và lớp
DatagramPacket và DatagramSocket cho kiểu datagram socket. Đối với kiểu
stream socket, lớp Socket được sử dụng bởi cả client và server. Lớp Socket này có
các phương thức tương ứng với bốn thao tác đầu tiên của thao tác cơ bản của
socket trình bày ở trên. Ba thao tác cuối được hỗ trợ bởi server để chờ các client
liên kết tới. Các thao tác này được cài đặt bởi lớp ServerSocket.

II/ TCP SOCKET
Client thiết lập giao tiếp với server và đợi sự đáp trả từ Server. Các socket cho
client thường được sử dụng theo các bước sau:
• Tạo ra một Socket mới sử dụng hàm khởi tạo với địa chỉ IP và số hiệu cổng
dịch vụ của máy đích. Socket cố gắng liên kết với socket server của máy đích.
• Sau khi liên kết được thiết lập, lấy luồng nhập và luồng xuất được tạo ra
giữa socket ở máy gửi - client và socket ở máy đích – server. Các luồng này được
sử dụng để gửi dữ liệu cho nhau. Kiểu liên kết này được gọi là song công (full-
duplex) các host có thể nhận và gửi dữ liệu đồng thời. Ý nghĩa của dữ liệu phụ
thuộc vào giao thức.
• Khi việc truyền dữ liệu hoàn thành, một hoặc cả hai phía ngắt liên kết. Một
số giao thức, như HTTP, đòi hỏi mỗi liên kết phải bị đóng sau mỗi khi yêu cầu
được phục vụ. Các giao thức khác, chẳng hạn FTP, cho phép nhiều yêu cầu được
xử lý trong một liên kết đơn.


III/ INPUT, OUTPUT STREAM

Luồng đơn giản là một lộ trình mà dữ liệu sẽ di chuyển giữa chương trình và các
thiết bị nhập xuất, nó là một sự biểu diễn trừu tượng (cấu trúc dữ liệu, lớp) để dữ
liệu có thể trao đổi giữa chương trình và các thiết bị vật lý.

Trong java, luồng được thiết kế thành nhiều lớp những tất cả chúng được dẫn
xuất ra từ hai lớp trừu tượng đó là InputStream và OutputStream trong gói java.io.
Có hai loại luồng trong java đó là luồng ký tự và luồng bytes. Tất cả các task liên
quan đến các lớp nhập xuất trong java nếu có lỗi sẽ quăng ra một IOException.
1)Những lớp Ouput stream
-OutputStream là lớp trừu tượng và cơ bản nhất để tất cả các lớp xử lý luồng
xuất byte kế thừa.Nó có 3 phương thức chính là:
• Write ghi những byte dữ liệu tới luồng xuất
• Flush xả luồng để tất cả các vùng nhớ (buffer) của luồng trong trạng thái
trống sẵn sàng cho việc ghi
• Close đóng luồng xuất và giải phóng tất cả tài nguyên hệ thống liên quan đến
luồng xuất này
Dưới đây là các lớp kế thừa từ lớp OutputStream:
- ObjectOutputStream: được dùng để chuyển đối tượng thành dãy byte và ghi.
- ByteArrayOutputStream là một lớp kế thừa từ lớp OutputStream, nó được
dùng để ghi dữ liệu trong một mảng byte, vùng nhớ (buffer) dữ liệu sẽ tự động
tăng khi chúng ta ghi dữ liệu vào.
- FileOutputStream là lớp kế thừa từ lớp OutputStream, được dùng để ghi dữ
liệu tới tập tin.
- BufferedOutputStream kế thừa từ lớp FilterOutputStream, nó dùng để hỗ trợ
việc ghi dữ liệu trong vùng đệm nhằm cải tiến performance khi ghi dữ liệu.
- DataOutputStream giúp ứng dụng ghi những kiểu dữ liệu cơ bản (primitive
types) như boolean, int, float,… tới stream. Lớp này sinh ra nhằm giúp dễ dàng
hơn trong việc ghi dữ liệu có nhiều kiểu như số nguyên, số thực, ký tự…
2)Những lớp Input stream
InputStream là một lớp trừu tượng dùng để các lớp xử lý nhập byte dữ liệu kế

thừa. InputStream có các hàm sau:
• Available trả về số lượng byte có thể được đọc từ inputStream này
• Read đọc byte dữ liệu kế tiếp từ input stream
• Mark đánh dấu vị trí hiện tại trong input stream
• Skip không đọc n byte dữ liệu từ input stream
• Reset khởi động lại việc đọc từ vị trí trong phương thức mark
• Close đóng input stream là giải phóng toàn bộ tài nguyên hệ thống liên quan
đến stream này
Dưới đây là các lớp kế thừa từ lớp InputStream:
- ObjectInputStream: là lớp đọc dãy byte và chuyển thành đối tượng phù hợp.
- ByteArrayInputStream là lớp dùng để chứa những byte có thể được đọc bởi
các stream khác, chúng ta có thể đọc từng ký tự hoặc nhiều ký tự từ stream này.
Còn nếu đọc tư ByteArrayOutputStream chúng ta chỉ có thể lấy ra một mảng
byte, việc đọc dữ liệu trong vùng đệm nhằm cải tiến performance khi đọc dữ liệu.
- DataInputStream là lớp kế thừa từ filterInputStream, nó giúp ứng dụng đọc
dữ liệu có kiểu là các kiểu nguyên thủy (primitive types) như int, float, boolean,


3)Những lớp Reader và Writer
Những lớp thuộc nhóm Reader và Writer dùng để giúp việc nhập xuất các
luồng ký tự (character) giữa ứng dụng và các thiết bị vật lý.
Các lớp Reader: Reader, BufferedReader, CharArrayReader, FilterReader,
InputStreamReader, StringReader, PipedReader, FileReader, LineNumberReader,
PushBackReader
Các lớp Writer: Writer, BufferedWriter, CharArrayWriter, FilterWriter,
OutputStreamWriter, FileWriter, PipedWriter, PrinterWriter, StringWriter, File,
RandomAccessFile, FileDescriptor, FilePermission, StreamTokenizer
Reader và Writer là hai lớp trừu tượng được dùng để các lớp nhập xuất luồng
ký tự kế thừa. Reader cho việc đọc, còn Writer cho việc ghi.


IV/ THREAD
Mỗi khi chạy một ứng dụng trong Java thì bạn đã có một Thread. Đây là
Thread chính, nó thực thi các dòng lệnh trong phương thức: public static void
main . Đây là một điểm nhập bắt buộc cho mọi ứng dụng độc lập.
Để tạo ra một Thread khác ngoài Thread chính trên, Java cung cấp cho chúng
ta hai cách :
- Tạo ra một lớp con của lớp Thread (java.lang.Thread)
- Tạo ra một lớp hiện thực interface Runnable
Chúng ta sẽ tìm hiểu lần lược hai cách trên.
1) Tạo một lớp con của lớp java.lang.Thread
Bạn khai báo như sau :
class A extends Thread {
public void run() {
// code for the new thread to execute
}
}

A a = new A(); // create the thread object
a.start(); // start the new thread executing
- Với cách này các dòng lệnh của bạn sẽ được đặt trong method run(). Method
này được override method nguyên thuỷ của lớp Thread.Sau đó bạn sẽ tạo ra một
đối tượng từ lớp của bạn.Bạn gọi phương thức start() từ đối tượng đó. Lúc này
Thread của bạn chính thức được tạo ra và phương thức start sẽ tự gọi method run
của bạn và thực thi các dòng lệnh mà bạn đã đặc tả.
- Chú ý rằng : method start() là method của hệ thống, nó có nhiệu vụ cấp phát
bộ nhớ, tạo ra một Thread và gọi hàm run() của bạn. Vì thế bạn không nên
override phương thức này. Điều này có thể dẫn đến không tạo được Thread.
2) Hiện thực interface Runnable
Bạn khai báo như sau :
class B extends … implements Runnable {

public void run() {
// code for the new thread to execute
}
}

B b = new B(); // create the Runnable object
Thread t = new Thread(b); // create a thread object
t.start(); // start the new thread
- Cũng giống như cách trên, dòng lệnh của bạn đặt trong method run() (có thể
gọi đến các phương thức khác, nhưng phải bắt đầu trong phương thức này). Sau
đó bạn tạo một đối tượng B từ lớp đã hiện thực interface Runnable, tạo thêm một
đối tượng t của lớp Thread với thông số cho constructor là đối tượng B.
Sau đó khi bạn gọi phương thức t.start() thì chính thức Thread được tạo ra và
phương thức run() của bạn sẽ được triệu gọi một cách tự động.
Bạn sẽ hỏi tại cách thứ hai vẫn phải tạo ra một đối tượng Thread. Vậy tại sao lại
đưa ra hai cách hiện thực làm gì ?
Câu trả lời là :
- Bản thân ngôn ngữ Java không hỗ trợ đa thừa kế . Bạn chỉ có thể extends từ
một lớp duy nhất. Nhưng bạn lại có thể implements cùng lúc nhiều interface. Khi
mà lớp của bạn đã [extends] một lớp nào đó rồi (vd : Applet), thì bạn chỉ có thể
implements Runnable để tạo ra Thread.
- Việc extends lớp Thread có thể dẫn đến rủi ro là bạn override các method
start(), stop(), thì có thể làm cho việc tạo Thread là không thể. Một lời khuyên
là nên tạo ra một lớp hiện thực interface Runnable (cách thứ hai) khi muốn tạo ra
một Thread. Chương trình của bạn sẽ trong sáng và dễ tìm lỗi hơn.

×