Nếu bạn thấy Diễn đàn có ích, hãy cùng chia sẻ trên các mạng Xã hội nhé!
Kết quả 1 đến 5 của 5

Chủ đề mới: Lập trình phần mềm Cờ Tướng (tài liệu sưu tầm).

  1. #1
    Ngày tham gia
    Dec 2012
    Thành viên thứ
    3
    Bài viết
    74
    Cảm ơn 19 lần / 7 bài

    Lập trình phần mềm Cờ Tướng (tài liệu sưu tầm).

    I.Giới thiệu


    Trò chơi Cờ Tướng (tên phiên âm Trung Quốc XiangQi, tên tiếng Anh Chinese Chess) là một minh hoạ rất tốt cho bài toán tìm kiếm trên cây trò chơi và áp dụng thuật toán AlphaBeta trên cây này như thế nào. Đây là một trò chơi thú vị và tương đối phổ biến ở Việt nam, châu Á cũng như trên toàn thế giới. Nó tạo cảm giác dường như máy tính có thể suy nghĩ và đọ sức với con người (thực tế cho đến nay nó vẫn chỉ tính toán mà thôi). Cờ Tướng là loại cờ có độ phức tạp và rất nhiều mặt tương đương với cờ Vua.
    Trong phần này, chúng tôi sẽ giới thiệu với bạn những kiến thức cơ bản nhất về một chương trình chơi cờ phải như thế nào. Các chương trình mẫu VSCCP (Very Simple Chinese Chess Program - Chương trình Cờ Tướng rất đơn giản) cũng hết sức đơn giản và có đầy đủ trong các phụ lục.
    404 Not Found

    II. Viết chương trình chơi cờ VSCCP 1.0

    1. Biểu diễn bàn cờ và quân cờ

    Bàn cờ trong trò chơi cờ Tướng là một bảng chữ nhật bao gồm 9 đường dọc và 10 đường ngang. Các quân cờ chia làm hai bên đứng tại các giao điểm của các đường. Bàn cờ và vị trí khởi đầu các quân cờ như hình 2.1. Cách đơn giản nhất để biểu diễn một bàn cờ trong máy tính là ta dùng một mảng hai chiều, kích thước 9 x 10:
    int piece[1..10, 1..9] ;
    Mảng trên hoạt động tốt nhưng có cái bất tiện là ta phải dùng tới hai chỉ số để truy cập vào mảng (ví dụ vị trí quân Pháo góc trên bên trái (cột 2, dòng 3) là piece[3, 2]). Một cải tiến nhỏ là ta dùng mảng một chiều như sau:
    int piece[1..90];
    Truy nhập đến vị trí quân Pháo góc trên bên trái lúc này là piece[20].

    404 Not Found

    Các ô của mảng sẽ chứa những giá trị khác nhau cho biết đó là quân cờ gì. Mỗi quân cờ sẽ được gán một mã số khác nhau như bảng dưới đây. Các chỗ trống (không có quân cờ) sẽ được điền kí hiệu trống (EMPTY):



    Quân cờ ------Kí hiệu ------- Giá trị
    Tốt (Chốt)----PAWN----------0
    Sĩ -----------BISHOP---------1
    Tượng ------ELEPHANT -------2
    Mã ----------KNIGHT --------3
    Pháo --------CANNON --------4
    Xe -----------ROOK----------5
    Tướng --------KING----------6
    Trống--------EMPTY---------7


    Ngoài mục đích gán mỗi quân cờ một mã số để phân biệt, mã này còn giúp ta ước lượng sơ bộ tầm quan trọng của quân cờ đó.
    Như vậy, lúc khởi đầu, các ô trong mảng sẽ được gán các giá trị quân cờ nhờ khai báo const (trong Java) như dưới, trong đó BOARD_SIZE (kích thước bàn cờ = 90) là một hằng số đã được định nghĩa trước đó:

    char piece= {
    5,3,2,1,6,1,2,3,5,
    7,7,7,7,7,7,7,7,7,
    7,4,7,7,7,7,7,4,7,
    0,7,0,7,0,7,0,7,0,
    7,7,7,7,7,7,7,7,7,
    7,7,7,7,7,7,7,7,7,
    0,7,0,7,0,7,0,7,0,
    7,4,7,7,7,7,7,4,7,
    7,7,7,7,7,7,7,7,7,
    5,3,2,1,6,1,2,3,5};

    Đến đây, bàn cờ còn chưa có thông tin để phân biệt một quân cờ là của bên nào. Ta có thể cải tiến thay cho kiểu byte của mảng piece là một bản ghi nhằm lưu thêm các thông tin này. Chúng tôi xin giới thiệu một phương pháp đơn giản là dùng thêm một mảng nữa - mảng color, để lưu các thông tin về bên. Hai bên được gán kí hiệu và mã như bảng dưới. Những chỗ trống sẽ dùng cùng kí hiệu trống EMPTY.

    Bên-------------Đen----------Trắng---------Trống---
    Kí hiệu---------DARK---------LIGHT----------EMPTY---
    Giá trị-----------0-------------1--------------7-----

    Ta lại có thông tin về bên được khai báo khởi đầu tương tự:

    char color= {
    0, 0, 0, 0, 0, 0, 0, 0, 0,
    7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 0, 7, 7, 7, 7, 7, 0, 7,
    0, 7, 0, 7, 0, 7, 0, 7, 0,
    7, 7, 7, 7, 7, 7, 7, 7, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7,
    1, 7, 1, 7, 1, 7, 1, 7, 1,
    7, 1, 7, 7, 7, 7, 7, 1, 7,
    7, 7, 7, 7, 7, 7, 7, 7, 7,
    1, 1, 1, 1, 1, 1, 1, 1, 1};
    Để biết bên nào tới lượt đi, ta dùng một biến toàn cục side chứa một trong hai giá trị LIGHT và DARK. Một biến toàn cục khác xside sẽ có sẵn giá trị ngược với side để tiện tính toán (ví dụ nếu side = LIGHT thì xside = DARK). Khi tới phiên đối phương đi, ta cần đảo ngược giá trị trong cả side và xside bằng các lệnh như sau (chú ý là LIGHT+DARK = 1):
    side := xside; xside := 1 - xside;
    Ngoài ra, ta còn khai báo biến computerside cũng chỉ có một trong hai giá trị LIGHT và DARK nhằm cho biết bên nào là máy. Để hiện bàn cờ, phương pháp đơn giản nhất là hiện ở chế độ text (văn bản). Tuy cách này trông xấu và thường không dùng trong các chương trình có trên thị trường nhưng nó có các ưu điểm nổi trội sau:
    Vẫn hiện được bàn cờ rất đầy đủ, trực quan, dễ hiểu, cho phép theo dõi và thi đấu bình thường.
    Rất đơn giản và tin cậy. Bạn sẽ đỡ nhiều thời gian tìm hiểu và phát triển giao diện, dồn sức cho việc quan trọng hơn - làm chương trình chơi hay hơn. Giao diện đồ hoạ chỉ cần thiết lúc hoàn chỉnh - lúc bạn "đóng gói" chương trình.
    Việc hiện thêm các thông tin để kiểm tra, tìm lỗi rất dễ dàng. Rõ ràng việc dùng hai thủ tục có sẵn của Pascal là gotoxy và write thì dễ, nhanh và đảm bảo hơn các hàm đồ hoạ.
    Dễ chuyển đổi hệ máy và hệ điều hành. Có thể bạn sẽ muốn thử chạy trên những máy tính có nền tảng khác như máy mini, macintosh, hệ điều hành Windows 3.1, Win95, Win98, WinNT, System7, UNIX...
    Bạn có thể tự phát triển giao diện đồ hoạ và cài chuột theo ý mình.Quân cờ được biểu diễn bằng một chữ cái viết hoa đứng đầu tên của nó. Quân hai bên sẽ có mầu khác nhau. Do quân Tướng và Tượng có cùng chữ cái đầu T nên để tránh nhầm lẫn ta dùng chữ V (Voi) biểu diễn quân Tượng. Tuy quân Tốt và Tướng cũng có cùng chữ cái đầu nhưng ta không sợ nhầm do Tốt không thể nhập cung bên mình được. Nó chỉ có thể "tiếp chuyện" Tướng đối phương, nhưng lúc này hai bên lại phân biệt được nhờ mầu (các phương pháp khác là dùng chữ cái đầu tên tiếng Anh: P-Tốt, E-Tượng, N-Mã, B-Sĩ, R-Xe, C-Pháo, K-Tướng; hoặc theo qui định của Liên đoàn cờ Việt Nam: Tg-Tướng, S-Sĩ, T-Tượng, X-Xe, P-Pháo, M-Mã, C-Chốt).
    Ta sẽ hiện bàn cờ ở dạng như hình 2.3. Chú ý cách đánh kí hiệu các vị trí trong bàn cờ bằng chữ và số giống như bàn cờ Vua.
    Để hiện một quân cờ, ta viết một thủ tục DrawCell với tham số là vị trí bàn cờ. Ngoài ra, nó còn một tham số nữa cho biết sẽ hiện mầu nền của quân cờ với mầu bình thường NORMAL (sẽ có nền đen) hay mầu khác SELECT (sẽ có nền xanh sẫm) để thể hiện quân cờ đó được chọn (phục vụ cho chọn và đi quân của người chơi).
    Class void DrawCell(int pos,int mode);
    Như vậy, để hiện toàn bộ bàn cờ ta chỉ cần gọi một vòng lặp for là xong:
    for (int i = 1 ;i 404 Not Found
    Lần sửa cuối bởi PhuongAnh, ngày 01-08-2013 lúc 06:45 AM.

  2. 7 Thành viên cảm ơn PhuongAnh vì bài viết hữu ích.

    amorist (09-27-2014), caonguyen688 (09-27-2014), coghep (08-19-2014), cuquyen (12-13-2014), luctudida (10-02-2014), NhatTonDaiSu (12-11-2014), onthandauoan (07-06-2016)

  3. #2
    Ngày tham gia
    Dec 2012
    Thành viên thứ
    3
    Bài viết
    74
    Cảm ơn 19 lần / 7 bài
    2. Sinh nước đi

    Một trong những việc quan trọng nhất để máy tính có thể chơi được cờ là phải chỉ cho nó biết mọi nước đi có thể đi được từ một thế cờ. Máy sẽ tính toán để chọn nước đi có lợi nhất cho nó. Các yêu cầu chính đối với một thủ tục sinh nước đi là:
    Chính xác (rất quan trọng). Một nước đi sai sẽ làm hỏng mọi tính toán. Đồng thời chương trình có thể bị trọng tài xử thua luôn. Do số lượng nước đi sinh ra lớn, luật đi quân nhiều và phức tạp nên việc kiểm tra tính đúng đắn tương đối khó.
    Đầy đủ (rất quan trọng). Sinh được mọi nước đi có thể có từ một thế cờ.
    Nhanh. Do chức năng này phải sinh được hàng triệu nước đi mỗi khi máy đến lượt nên giảm thời gian sinh nước đi có ý nghĩa rất lớn.Sinh nước đi là một thuật toán vét cạn. Máy sẽ tìm mọi nước đi hợp lệ có thể có. Máy phải sinh được từ những nước đi rất hay cho đến những nước đi rất ngớ ngẩn (như đẩy Tướng vào vị trí khống chế của đối phương). Ta hình dung ngay thủ tục sinh nước đi Gen sẽ có đầy những vòng lặp for, các câu lệnh kiểm tra if và rẽ nhánh case, trong đó các phép tính kiểm tra giới hạn chiếm một phần đáng kể. Thủ tục này luôn sinh nước cho bên đang tới lượt chơi căn cứ vào nội dung của biến side. Đây là một trong những thủ tục phức tạp và dễ sai nhất.
    Một nước đi có hai giá trị cần quan tâm. Đó là điểm xuất phát (from) và điểm đến (dest). Ta sẽ khai báo một cấu trúc move như sau để dùng những nơi cần đến dữ liệu nước đi.

    type
    move = record { Định nghĩa cấu trúc nước đi }
    from, dest: byte;
    end; 404 Not Found


    Kiểm tra giới hạn bàn cờ
    Ví dụ có một quân Xe nằm ở ô số 84 (trong mảng piece). Bây giờ ta sẽ sinh thử một nước đi sang trái một ô cho nó. Nước đi sang trái một ô được chuyển thành ô số 83 là một vị trí cùng hàng với ô xuất phát nên được chấp nhận. Một nước đi khác cần phải xem xét là sang trái ba ô - ô 81. Ô 81 tuy có trong bàn cờ nhưng khác hàng nên không được chấp nhận. Như vậy, muốn biết ô của nước đi sang trái có được phép không ta phải kiểm tra xem nó có cùng hàng với ô xuất phát không. Việc kiểm tra thực hiện bằng cách chia cho 9 (kích thước của một dòng) và lấy phần nguyên (trước đó lại phải chuyển thứ tự ô về gốc là 0 bằng cách trừ đi 1). Ta thấy ((83-1) div 9) = ((84-1) div 9) nên ô 83 được chấp nhận; trong khi đó do ((81-1) div 9) <> ((84-1) div 9) nên kết luận là nước đi đến ô 81 không hợp lệ

    Các nước đi vừa sinh ra sẽ được đưa vào danh sách nước đi nhờ gọi thủ tục Gen_push. Thủ tục này có hai tham số là vị trí xuất phát của quân cờ sẽ đi và nơi đến dest của quân cờ đó.
    Dưới đây là đoạn chương trình dùng để sinh những nước đi sang trái của một quân Xe, trong đó x là vị trí của quân Xe này .



    i = x - 1; //Nước sang trái đầu tiên
    while ((i-1) / 9) = ((x-1) / 9) {
    if (ô thứ i là trống) or (ô thứ i có quân đối phương)
    gen_push(vị trí của Xe, vị trí ô đang xét);
    if ô thứ i không trống
    break; // Kết thúc quá trình sinh nước đi sang trái
    i = i - 1; // Xét tiếp vị trí bên trái

    }

    Việc sinh những nước đi theo chiều khác cũng tương tự (ví dụ để sinh nước đi theo chiều đứng ta chỉ cần cộng hoặc trừ một bội số của 9) nhưng điều kiện kiểm tra sẽ khác nhau. Như vậy, chương trình sinh nước đi Gen có dạng như sau:
    for ( Xét lần lượt từng quân cờ bên hiện tại )
    case quâncờ of
    Xe: while ( Xét lần lượt tất cả các ô từ bên phải Xe cho đến lề trái bàn cờ ) {
    if (ô đang xét là ô trống) or (ô đang xét chứa quân đối phương) gen_push(vị trí của Xe, vị trí ô đang xét)
    if (ô đang xét không trống) break;
    }
    while (Xét lần lượt tất cả các ô từ bên trái Xe cho đến lề phải bàn cờ ) {
    ...}
    while (Xét lần lượt tất cả các ô từ bên trên Xe cho đến lề trên bàn cờ) {
    ... }
    while Xét lần lượt tất cả các ô từ bên dưới Xe cho đến lề dưới bàn cờ {
    ...}
    Break;


    Pháo:
    ...

    Phương pháp này có nhược điểm là chương trình phải viết phức tạp, cồng kềnh, khó tìm lỗi nhưng khá nhanh.
    Trong chương trình mẫu VSCCP, chúng tôi giới thiệu một kĩ thuật khác có tên gọi là "hộp thư" (mail box - do các bảng của nó có dạng các hộp phân thư). Mục đích chính của kĩ thuật này là nhằm giảm bớt các phép kiểm tra vượt giới hạn bàn cờ và làm đơn giản chương trình. Mấu chốt là thay cho bàn cờ có kích thước bình thường 9x10 = 90, ta dùng một bàn cờ mở rộng, mỗi chiều có thêm 2 đường nữa (bàn cờ mới có kích thước 13x14 = 182). Các ô ứng với các đường bao mở rộng đều có giá trị -1, tức là các giá trị báo vượt biên. Các nước đi trên bàn cờ 9x10 được chuyển tương ứng sang bàn cờ này. Nếu một nước đi được sinh ra lại rơi vào một trong hai đường bao thì có nghĩa nó đã rơi ra ngoài bàn cờ rồi, phải bỏ đi và ngừng sinh nước về phía đó. Sở dĩ có đến hai đường biên (chứ không phải một) do quân Mã và Tượng có thể nhẩy xa đến hai ô

    Việc chuyển đổi toạ độ thực hiện nhờ hai mảng. Mảng mailbox90 dùng để chuyển từ toạ độ bàn cờ thường sang toạ độ bàn cờ mới. Mảng ứng với bàn cờ mới - mailbox182 dùng để kiểm tra các nước đi vượt quá đường biên và dữ liệu để chuyển trở lại toạ độ bình thường.
    Ví dụ, nếu vị trí quân Xe nằm ở ô số 84 (trong mảng piece) như hình 2.5, thì khi đổi sang bàn cờ mở rộng sẽ thành vị trí mailbox90[84] = 148. Có nghĩa là nó ứng với ô thứ 148 của mảng mailbox182. Bây giờ ta sẽ sinh thử một nước đi sang trái một ô cho quân Xe này. Việc sinh và kiểm tra sẽ được thực hiện trong bàn cờ mở rộng, nước đi mới là ô số 148 - 1 = 147. Do mailbox182[147] = 83 ¹ -1 nên nước đi này được chấp nhận. Số 83 cho biết kết quả sang trái một ô là vị trí 83 trong bàn cờ bình thường. Tuy nhiên, nước đi sang trái ba ô, có số 148 - 3 = 145 và mailbox182[145] = -1 cho biết đó là một nước đi không hợp lệ.
    Chương trình cũng cần kiểm tra số nước đi tối đa theo một hướng của quân cờ đang xét. Chỉ có quân Pháo và Xe có thể đi đến 9 nước đi, còn các quân khác có nhiều nhất là 1.
    Việc đi một quân sang vị trí mới thực chất là ta đã thay đổi toạ độ của nó bằng cách cộng với một hằng số (dương hoặc âm). Ở trên ta đã thấy để quân Xe sang trái một nước ta đã phải cộng vị trí hiện tại với -1. Để sinh một ô mới theo hàng dọc, ta phải cộng với +13 hoặc -13 (chú ý, việc sinh nước và kiểm tra hợp lệ đều dựa vào mảng mailbox182 nên giá trị 13 là kích thước một dòng của mảng này). Để sinh các nước đi chéo ta phải cộng trừ với một hằng số khác. Ta nên lưu các hằng số này vào mảng offset có 2 chiều. Một chiều dựa vào loại quân cờ nên chỉ số được đánh từ 1 đến 7. Chiều còn lại là số hướng đi tối đa của một quân cờ. Quân cờ có nhiều hướng nhất là quân Mã có tới 8 hướng nên chiều này được khai báo chỉ số từ 1 đến 8. Các quân cờ có số hướng ít hơn sẽ được điền 0 vào phần thừa. Chú ý là nước đi quân Tốt của hai bên khác nhau hướng tiến. Để tiết kiệm ta chỉ lưu nước tiến của Tốt đen, còn nước tiến của Tốt trắng chỉ đơn giản lấy ngược dấu.

    Kiểm tra vị trí được phép đến
    Việc chuyển toạ độ từ bàn cờ thường sang bàn cờ mở rộng chỉ giúp ta loại bỏ được các nước vượt quá biên. Ta còn phải kiểm tra một số giới hạn khác. Ví dụ như Tướng và Sĩ không thể đi ra ngoài cung, Tượng chỉ được phép ở 7 điểm cố định phía bên mình, Tốt chỉ được phép tung hoành trên đất đối phương, còn phía bên mình cũng bị giới hạn ngặt nghèo một số ô... Để thực hiện những phép kiểm tra này, ta dùng một mảng là legalmove ứng với từng ô trên bàn cờ sẽ cung cấp các thông tin này. Để kiểm tra một quân cờ có được phép ở đó không, ta dùng một mặt nạ bít Maskpiece mà tuỳ theo từng quân sẽ có giá trị khác nhau. Nếu ở ô cần kiểm tra có bit trùng với mặt nạ này được đặt là 1 thì quân cờ đó được phép đến ô đấy.
    404 Not Found

    Ví dụ, ô số 3 có giá trị legalmove[3] = 5 (chuyển thành số nhị phân là 00000101) cho biết các quân cờ được phép đi đến đó là Tượng, Xe, Pháo, Mã.
    Ngoài ra, ta còn phải kiểm tra nước bị cản (đối với Tượng và Mã) và xử lí cách ăn quân của quân Pháo như một trường hợp đặc biệt. Như vậy, tổng thể sinh các nước đi cho một quân cờ có dạng như sau:
    p = piece[i]; // Sinh nước đi cho quân cờ p ở vị trí i
    [b] for (int j = 1 ;j< 8 ; j++) { //Số hướng đi tối đa
    if (offset[p,j] = 0) break;
    x=mailbox90; // Chuyển sang bàn cờ mở rộng
    if ((p [b]== ROOK)||(p== CANNON])) n = 9 ;
    else n = 1;
    for (t=1 ; t if ((p==PAWN)&& (side==LIGHT)) x = x - offset[p, j];
    else x = x + offset[p, j]; // Nước đi mới
    y = mailbox182[x]; // Chuyển về toạ độ bình thường
    if (side == DARK) t = y;
    else t = 91-y;
    if ((y==-1) || /*Ra ngoài lề ? */ ((legalmove[t] || maskpiece[p])==0)) // Được phép ở vị trí này không ?
    break; // Thoát nếu nước đi không hợp lệ
    }
    // Kiểm tra nước cản với Tượng, Mã và xử lí Pháo ở đây
    ...

    Một vấn đề nữa là luật hai Tướng không được đối mặt trực tiếp với nhau. Việc kiểm tra được thực hiện nhờ hàm kingface. Hàm sẽ trả lại giá trị true nếu nước vừa đi gây hở mặt Tướng. Hàm này có thể được đặt trong thủ tục sinh nước Gen. Tuy nhiên đơn giản hơn, ta đặt nó trong thủ tục gen_push, nếu hở mặt Tướng thủ tục này sẽ không đưa nước đi đó vào danh sách các nước đi.

    3. Đánh giá một thế cờ

    Đánh giá một thế cờ là một trong những nhiệm vụ quyết định chương trình chơi cờ của bạn có là "cao thủ" hay không. Căn cứ vào một thế cờ máy sẽ gán cho nó một điểm số (lượng giá tĩnh) để đánh giá độ tốt - xấu. Nhờ điểm này máy mới có thể so sánh các thế cờ với nhau và biết chọn nước đi tốt nhất. Đây là một nhiệm vụ rất khó khăn và phức tạp do không tồn tại một thuật toán tổng quát và thống nhất nào để tính điểm cả. Điểm của một thế cờ dựa trên rất nhiều yếu tố mà khó có thể số hoá hết được như phụ thuộc vào số lượng và giá trị các quân cờ hiện tại, phụ thuộc vào tính hãm, tính biến, thế công, thế thủ của từng quân cờ cũng như cả cục diện trận đấu. Ví dụ, một cặp Mã giao chân, có thể sát cánh tiến quân và tựa lưng phòng thủ thường có giá hơn hai Mã đứng rời. Nhưng cũng có lúc hai Mã đứng rời lại tốt hơn hai Mã giao chân khi Mã này lại cản Mã kia trong một thế trận nào đó. Ta cũng biết rằng, "lạc nước hai Xe đành bỏ phí, gặp thời một Tốt cũng thành công", thế nhưng số hoá điều này qua hàm lượng giá quả là một điều khó quá sức.
    Chúng ta bắt đầu với việc công nhận các giả thuyết sau:
    Ta có thể biểu diễn chất lượng một thế cờ bằng một con số. Ví dụ, con số đó có thể là đánh giá của ta về xác suất chiến thắng, nhưng đối với đa số chương trình thì con số đó không có gì đặc biệt, nó chỉ là con số mà mục đích chính là so sánh được với nhau.
    Chúng ta nên đo chất lượng của một thế cờ tương tự như phép đo của đối phương (do đó, nếu ta coi là đạt được một thế tốt thì đối phương của ta phải thấy đó là thế xấu đối với họ và ngược lại). Điều này tuy không thật đúng lắm, nhưng nó giúp cho thuật toán tìm kiếm của ta làm việc tốt và trong thực tế cũng khá gần với sự thật.Trong chương này chúng ta chỉ cài đặt phương pháp đơn giản nhưng cơ bản nhất: lượng giá dựa trên cơ sở giá trị của từng quân cờ. Cách tính này sẽ lấy tổng giá trị các quân cờ hiện có của bên mình trừ đi tổng giá trị các quân cờ hiện có của đối phương. Do đó, một thế cờ này hơn thế cờ kia ở chỗ nó còn nhiều quân bên mình hơn, nhiều quân giá trị cao hơn cũng như có bắt được nhiều quân và quân giá trị cao của đối phương hơn không.
    Cách làm này đã bỏ qua mất những nghệ thuật, chiến lược chơi cờ (mà đó là những điểm để đánh giá một người là giỏi cờ hay không). Các quân cờ được triển khai không theo một chiến lược chung nào hết (vô định). Nó còn tạo cảm giác như cờ "vồ", nghĩa là chỉ nhằm nhằm sơ hở của đối phương là "ăn" ngay mà không cần biết đến hậu quả (điều này không hẳn đúng, lí do sẽ trình bầy dưới). Tuy nhiên phương pháp tính điểm này có những ưu điểm sau:
    Là cách tính điểm cơ bản nhất, đóng vai trò chủ đạo trong điểm của một thế cờ. Nó là cơ sở của đa số hàm đánh giá. Ta cũng có thể nhận thấy trong phần lớn thời gian diễn ra trận đấu, hai bên đều tìm cách tiêu diệt quân của nhau. Các phương án, chiến lược thường chỉ được tính như những điểm cộng thêm vào và đóng góp một tỷ lệ nhỏ trong tổng số điểm của một thế cờ. Việc chỉ nhằm "vồ" quân của đối phương nhưng sau khi suy nghĩ sâu nhiều nước cũng đã trở thành "cao cờ" rồi đấy. Nói cho cùng, mục đích chính của chúng ta cũng là "vồ" bằng được quân có giá trị cao nhất - Tướng đối phương.
    Là cách tính đơn giản nhất và nhanh nhất. Do tính nhanh, ta có thể tăng thêm độ sâu tìm kiếm. Việc tăng thêm độ sâu lại giúp máy có cái nhìn xa hơn, "cao cờ" hơn và nhiều khi khắc phục được nhược điểm của cách tính đơn giản.Điểm các quân cờ được đánh giá theo kinh nghiệm và cho biết sự tương quan giữa các quân cờ. Sau đây là điểm từng quân mà mọi người thường chấp nhận:


    [i] Quân cờ Kí hiệu Điểm
    Tốt-------PAWN-----1 (2 nếu đã qua sông)
    Sĩ--------BISHOP----2
    Tượng---ELEPHANT--2
    Mã-------KNIGHT----4
    Pháo-----CANNON---4.5
    Xe--------ROOK-----9

    Bạn cũng có thể theo bất kì thang điểm nào khác tuỳ theo hiểu biết và sở thích của mình. Ví dụ như trong làng cờ Việt nam thường cho điểm các quân hơi khác (xem bài đọc dưới): Tốt - 1 (2 nếu đã qua sông), Sĩ - 2, Tượng - 2.5, Mã - 4.5, Pháo - 5, Xe - 10.
    Trong chương trình cờ của chúng ta, điểm cụ thể của từng quân cờ là các số nguyên 10, 20, 20, 40, 45 và 90. Ta dùng một mảng piecevalue để lưu điểm từng quân cờ. Cho điểm như vậy không những vẫn giữ nguyên được tương quan và tránh dùng số thực (tính chậm) mà ta còn có một khoảng cách hợp lí giữa các điểm để sau này dễ dàng thêm những điểm bổ xung "thưởng" hoặc "phạt", tức là những điểm căn cứ vào những yếu tố khác (ví dụ cùng là Pháo nhưng lúc chỉ được 40 điểm do ở vị trí "bí", lúc khác lại có thể đến 85 do ở vị trí Pháo trống và đang đe doạ Pháo lồng).
    Trong bàn cờ, quân Tướng là quân quan trọng nhất, dù mất mọi quân hoặc đạt được thế cờ nào đi nữa đều không được mất Tướng vì nó dẫn đến thua cờ. Do đó, Tướng thường được cho một điểm rất cao, cách biệt nhiều lần so với các quân khác, đảm bảo điểm tổng của các quân còn lại cùng đủ mọi loại "thưởng", "thêm" đều không bằng được Tướng. Trong chương trình, ta cho nó 1000 điểm.
    Hàm lượng giá thật đơn giản như sau (chú ý là ta chưa tăng điểm cho Tốt đã qua sông):
    public class int Eval() {
    int piecevalue[7]={10,20,20,40,45,90,1000};
    int s = 0;
    for (int i=1;i< BOARD_SIZE ; i++ ){
    if (color[i] == side) s = s + piecevalue[piece[i]]
    else if (color[i] == xside) s = s - piecevalue[piece[i]];
    }
    return s;
    }

  4. 7 Thành viên cảm ơn PhuongAnh vì bài viết hữu ích.

    amorist (09-27-2014), caonguyen688 (09-27-2014), cccttt12345 (09-27-2014), coghep (08-19-2014), cuquyen (12-13-2014), luctudida (10-02-2014), NhatTonDaiSu (12-11-2014)

  5. #3
    Ngày tham gia
    Jan 2014
    Thành viên thứ
    9355
    Bài viết
    94
    Cảm ơn 122 lần / 52 bài
    Hay wa.thank

  6. Các thành viên đã cảm ơn daohoadaochu vì bài viết hữu ích này:

    luctudida (10-02-2014)

  7. #4
    Ngày tham gia
    May 2014
    Thành viên thứ
    11278
    Bài viết
    13
    Cảm ơn 9 lần / 4 bài
    Trích dẫn Gửi bởi daohoadaochu Xem bài viết
    Hay wa.thank
    qua hay qua hay..cam on ban nhieu!

  8. #5
    Ngày tham gia
    Jul 2013
    Thành viên thứ
    5616
    Bài viết
    88
    Cảm ơn 58 lần / 23 bài
    Thanks bạn! Rất hay!

Thông tin về chủ đề này

Users Browsing this Thread

Có 1 người đang xem chủ đề. (0 thành viên và 1 khách)

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •