Báo cáo đồ án minh họa thuật toán anpha – beta bằng chương trình chơi cờ tướng

25 2.4K 4
Báo cáo đồ án  minh họa thuật toán anpha – beta bằng chương trình chơi cờ tướng

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

KHOA CÔNG NGHỆ THÔNG TIN BỘ MÔN KHOA HỌC MÁY TÍNH B O C O Á Á ĐỒ ÁN TRÍ TUỆ NHÂN TẠO Đề bài : Minh họa thuật toán Anpha Beta bằng chương trình chơi cờ tướng I. Giới thiệu Trò chơi Cờ Tướng 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 thể suy nghĩ và đọ sức với con người . Cờ Tướng là loại 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 những kiến thứ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 cũng hết sức đơn giản Hinh 2.1 II. Viết chương trình chơi cờ 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: BYTE piece[10,9]; Mảng trên hoạt động tốt nhưng 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: BYTE piece[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]. 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 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 Pascal) 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 đó: piece[BOARD_SIZE]= { 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 thông tin để phân biệt một quân cờ là của bên nào. Ta 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 Kí hiệu Giá trị Đen DARK 0 Trắng LIGHT 1 Trống EMPTY 7 Ta lại thông tin về bên được khai báo khởi đầu tương tự: BYTE color[BOARD_SIZE]= { 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 m_side chứa một trong hai giá trị LIGHT và DARK. Một biến toàn cục khác m_xside sẽ sẵn giá trị ngược với side để tiện tính toán (ví dụ nếu m_side = LIGHT thì m_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 = 3): m_side := m_xside; m_xside := 3 - m_xside; Ngoài ra, ta còn khai báo biến computerside cũng chỉ một trong hai giá trị LIGHT và DARK nhằm cho biết bên nào là máy. 2. Sinh nước đi Một trong những việc quan trọng nhất để máy tính thể chơi được cờ là phải chỉ cho nó biết mọi nước đi thể đi được từ một thế cờ. Máy sẽ tính toán để chọn nước đi 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 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 thể 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 ý 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ệ 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ẽ đầ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 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. Struct MOVE { short from,dest; }; Kiểm tra giới hạn bàn cờ Ví dụ 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 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 phép không ta phải kiểm tra xem nó 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ệ (hình 2.5). 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 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) div 9) = ((x-1) div 9) do begin if (ô thứ i là trống) or (ô thứ i quân đối phương) then gen_push(vị trí của Xe, vị trí ô đang xét); if ô thứ i không trống then 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 } end; 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 dạng như sau: for Xét lần lượt từng quân cờ bên hiện tại do case quâncờ of Xe: begin 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ờ do begin if (ô đang xét là ô trống) or (ô đang xét chứa quân đối phương) then gen_push(vị trí của Xe, vị trí ô đang xét) if ô đang xét không trống then break; end; 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ờ do 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ờ do 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ờ do end; { Xong quân Xe } Pháo: Phương pháp này 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, chúng tôi giới thiệu một kĩ thuật khác tên gọi là "hộp thư" (mail box - do các bảng của nó 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ờ 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 thêm 2 đường nữa (bàn cờ mới kích thước 13x14 = 182). Các ô ứng với các đường bao mở rộng đều 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ì 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ĩ đến hai đường biên (chứ không phải một) do quân Mã và Tượng thể nhẩy xa đến hai ô (hình 2.6). 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. 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 ô, 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ỉ quân Pháo và Xe thể đi đến 9 nước đi, còn các quân khá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 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ờ nhiều hướng nhất là quân Mã 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ờ 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 phép ở đó không, ta dùng một mặt nạ bít Maskpiece mà tuỳ theo từng quân sẽ giá trị khác nhau. Nếu ở ô cần kiểm tra bit trùng với mặt nạ này được đặt là 1 thì quân cờ đó được phép đến ô đấy. Ví dụ, ô số 3 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ờ dạng như sau: p := piece[i]; { Sinh nước đi cho quân cờ p ở vị trí i } for j := 1 to 8 do begin { Số hướng đi tối đa } if offset[p,j] = 0 then break; x:=mailbox90[i]; { Chuyển sang bàn cờ mở rộng} if p in [ROOK, CANNON] then n := 9 else n := 1; for t:=1 to n do { Số nước thể đi theo một hướng} begin if (p=PAWN) and (side=LIGHT) then 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 then t := y else t := 91-y; if (y=-1) or { Ra ngoài lề ? } ((legalmove[t] and maskpiece[p])=0) { Được phép ở vị trí này không ? } then 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 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 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 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ó 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, thể sát cánh tiến quân và tựa lưng phòng thủ thường giá hơn hai Mã đứng rời. Nhưng cũng 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: 1. Ta thể biểu diễn chất lượng một thế cờ bằng một con số. Ví dụ, con số đó 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 gì đặc biệt, nó chỉ là con số mà mục đích chính là so sánh được với nhau. 2. 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 bản nhất: lượng giá dựa trên 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ủa bên mình trừ đi tổng giá trị các quân cờ hiện 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ư bắt được nhiều quân và quân giá trị cao của đối phương hơn không. [...]... theo dõi quá trình tính toán là dùng các tham số alpha và beta để ghi lại các thông tin theo dõi cần thiết Thủ tục AlphaBeta được bắt đầu tại nút gốc với giá trị của alpha là -vôcùng và beta là +vôcùng Thủ tục sẽ tự gọi đệ quy chính nó với khoảng cách giữa các giá trị alpha và beta ngày càng hẹp hơn Viết chương trình cho thuật toán AlphaBeta Từ phát biểu trên ta sẽ xây dựng hàm AlphaBeta bằng ngôn ngữ... -AlphaBeta( -beta, -alpha, depth-1); bỏ thực hiện nước đi m; if value > best then best := value; end; AlphaBeta := best; end; end; Lời gọi thủ tục AlphaBeta đầu tiên với độ sâu tìm kiếm 4 và thế cờ hiện tại pos dạng như sau: AlphaBeta(-INFINITY, +INFINITY, 4); Cũng tương tự như thuật toán Minimax ta đã gộp hai mục 2 và 3 làm một nhờ việc đổi dấu thích hợp So với thuật toán Minimax thì trong thuật toán. .. người chơi cực đại thể thu được là 5 điểm nhờ chọn đi theo nhánh giữa Hướng cải thiện việc tỉa nhánh của thuật toán AlphaBeta Thuật toán AlphaBeta nói chung giúp chúng ta tiết kiệm nhiều thời gian so với Minimax mà vẫn đảm bảo kết quả tìm kiếm chính xác Tuy nhiên lượng tiết kiệm này không ổn định - phụ thuộc vào số nút mà nó cắt bỏ Trong trường hợp xấu nhất thuật toán không cắt được một nhánh nào... hợp Thuật toán AlphaBeta hoàn toàn không chống được bùng nổ tổ hợp mà chỉ làm giảm tốc độ bùng nổ Tuy trong thực tế số nút phải xét (lượng giá) thường nhiều hơn trong điều kiện lí tưởng nhưng nó vẫn đủ để tiết kiệm khá nhiều thời gian Trong cùng một khoảng thời gian, thuật toán AlphaBeta thể tìm đến độ sâu gấp hai lần độ sâu tìm kiếm bằng Minimax Hình 1.8 là đồ thị so sánh giữa hai thuật toán này... thức cờ Tướng GIÁ TRỊ CỦA CÁC QUÂN CỜ Khái niệm giá trị của các quân cờ không phải là mới đối với những người chơi cờ từ các thế kỷ trước Từ lâu, làng cờ đã câu nhận định sức mạnh của các quân chủ lực là "Xe 10, Pháo 7, Mã 3" hoặc đánh giá Xe là quân chủ lực mạnh nhất bằng câu "Nhất Xa sát vạn" hay đánh giá một Tốt qua hà, sức mạnh bằng nửa con Xe (nhất Tốt độ hà, bán Xa chi lực) Thế nhưng sự đánh... khoảng 3 nghìn nút) ít hơn thuật toán Minimax (hơn 2,5 triệu nút) là 2560000 / 3199 khoảng 800 lần Còn với b = 40 và d = 5 ta số nút phải xét là 40^3 + 40^(5/2) - 1 = 64000+10119-1 = 74118 Số nút phải xét nhờ AlphaBeta ít hơn thuật toán Minimax (hơn 102 triệu nút) là 102400000/74118 = 1382 lần Dưới đây là bảng so sánh số nút phải xét giữa hai thuật toán Minimax và AlphaBeta Ta thể nhận xét như... dạng khai báo như dưới, trong đó depth là độ sâu tìm kiếm, INFINITY là giá trị vô cùng, thuật toán tính toán dựa trên thế cờ hiện tại pos là các biến toàn cục: function AlphaBeta(alpha, beta, depth): integer; begin if depth = 0 then AlphaBeta := Eval { Tính giá trị thế cờ pos } else begin best := -INFINITY; Gen; { Sinh ra mọi nước đi từ vị trí pos } while (còn lấy được một nước đi m) and (best < beta) ... trị alpha - beta càng ngày càng thu hẹp và dẫn đến các nhánh cây giá trị nằm ngoài khoảng này nhanh chóng bị cắt bỏ (hình 1.7) Đánh giá thuật toán AlphaBeta Trong điều kiện lí tưởng, thuật toán AlphaBeta chỉ phải xét số nút theo công thức: = = với d chẵn với d lẻ Với b = 40 và d = 4 ta số nút phải xét là 2x40^2 - 1 = 3199 Như vậy trong điều kiện lí tưởng thì số nút phải xét nhờ AlphaBeta (chỉ khoảng... dụ: Ta sẽ xem xét thuật toán AlphaBeta hoạt động như thế nào đối với cây trò chơi như trong hình 1.9 Cây này độ sâu bằng 3 và hệ số phân nhánh bằng 3 Các thứ tự kết luận (các con số bên trái) được đưa ra như sau: [1-2] Tìm kiếm đi xuống dưới theo nhánh trái cho đến lá Ở đây giá trị tĩnh thu được là 8 Giá trị đầu tiên này do người chơi cực đại được phép chọn trong ba giá trị ở nhánh này đã đảm bảo... mọi nhánh cây đều trả về điểm -1000 Do đó máy sẽ chọn nhánh đầu tiên để đi Nước đi này thể không hay do chấp nhận thua quá sớm như minh hoạ trên hình 2.10 Máy nên chọn nước thua lâu nhất để hi vọng đối phương đi "nhầm" (còn nước còn tát) và đúng tinh thần chiến đấu hơn 5 Tìm kiếm AlphaBeta Thủ tục AlphaBeta Thủ tục AlphaBeta là một cải tiến thuật toán Minimax nhằm tỉa bớt nhánh của cây trò chơi, . Á ĐỒ ÁN TRÍ TUỆ NHÂN TẠO Đề bài : Minh họa thuật toán Anpha – Beta bằng chương trình chơi cờ tướng I. Giới thiệu Trò chơi Cờ Tướng 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. chơi cờ phải như thế nào. Các chương trình cũng hết sức đơn giản Hinh 2.1 II. Viết chương trình chơi cờ 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. dấu thích hợp. So với thuật toán Minimax thì trong thuật toán AlphaBeta đã đưa thêm hai biến alpha, beta làm hai mức ngưỡng. Ta thấy cứ mỗi khi best >= beta thì thuật toán không thực hiện

Ngày đăng: 23/05/2014, 14:17

Từ khóa liên quan

Mục lục

  • I. Giới thiệu

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

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

  • 2. Sinh nước đi

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

  • 4. Xử lí một nước đi "thử"

  • 5. Tìm kiếm AlphaBeta

  • 6. Cập nhật một nước đi

  • 7. Hiện thông tin

Tài liệu cùng người dùng

Tài liệu liên quan