báo cáo môn trí tuê nhân tạo áp dụng thuật toán tìm kiếm minmax và cắt tỉa alpha beta xây dựng trò chơi cờ cờ tướng trên ngôn ngữ java

26 1.9K 5
báo cáo môn trí tuê nhân tạo  áp dụng thuật toán tìm kiếm minmax và cắt tỉa alpha beta xây dựng trò chơi cờ cờ tướng trên ngôn ngữ java

Đ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

ĐẠI HỌC BÁCH KHOA HÀ NỘI VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG BÁO CÁO BÀI TẬP LỚN TRÍ TUỆ NHÂN TẠO Đề tài: Tìm hiểu và cài đặt thuật toán MinMax và AlphaBeta vào game Cờ Tướng Giảng viên: Phạm Văn Hải Sinh viên nhóm 18: 1. Phạm Toàn Thắng 20102749 2. Nguyễn Viết Hiện 20101536 3. Nguyễn Đình Tài 20102117 4. Tô Đông Hoàng 20081074 5. Đỗ Đức Huy 20081125 6. Đỗ Văn Tùng 20102471 MỤC LỤC I. Lời nói đầu Các chiến lược tìm kiếm cơ bản chỉ sử dụng các thông tin chung của bài toán, nó không phù hợp với nhiều bài toán thực tế trong cuộc sống vì chúng đòi hỏi quá nhiều về thời gian và bộ nhớ. Bên cạnh đó, chúng ta ngày càng đặt ra những bài toán trong thực tế, nhằm giải quyết được các vấn đề, nhu cầu của con người, với một lượng thông tin, dữ liệu khổng lồ, cần phải đưa ra những chiến lượng giải quyết tối ưu, thông mình để đạt hiệu quả hơn, vậy nên cần nghiên cứu, thiết lập và cải thiện những chiến lược tìm kiếm với tri thức bổ sung (informed search strategies) sử dụng các tri thức cụ thể của bài toán. Trong đồ án này, nhóm sinh viên chúng em đã chọn ra một trong các giải thuật tìm kiếm để mô phỏng vào một bài toán thực tế đó là chương trình “Cờ tướng”, một trò chơi rất quen thuộc với chúng ta. Với mục tiêu đặt là có thể hiểu và vận dụng được giải thuật tìm kiếm tri thức, và củng cố được kĩ năng lập trình để tạo nên bản demo hoàn chỉnh. Như đã nói ở báo cáo bài tập tuần, với thời lượng một tháng học, tuần đầu để định hướng đề tài bài tập tuần, với thời lượng 2 tuần và đề tài bài tập lớn với thời lượng 3 tuần. thời gian rất hạn hẹp, vậy nên nhóm chúng em đã họp và đi đến thống nhất cách chia công việc cho nhóm 6 người như sau. 1. Nhóm 1 gồm 3 thành viên: - Tô Đông Hoàng 20081074 - Đỗ Đức Huy 20081125 - Đỗ Văn Tùng 20102471 Có kĩ năng đọc hiểu tiếng anh tốt phụ trách chính việc nghiên cứu đề tài bài báo, tóm tắt và phổ biến đến các thành viên còn lại của nhóm 2. 2. Nhóm 2 gồm 3 thành viên: - Nguyễn Viết Hiện 20101536 - Phạm Toàn Thắng 20102749 - Nguyễn Đình Tài 20102117 Có kĩ năng lập trình tốt về ngôn ngữ Java, phụ trách chính về việc nghiên cứu giải thuật cắt tỉa Alpha Beta để cài đặt thành công bản Game Demo – Cờ tướng. Lời cuối chúng em xin gửi lời cám ơn đến Phạm Văn Hải đã trực tiếp hướng dẫn và giúp chúng em có những kiến thức về trí tuệ nhân tạo, để có thể hoàn thành tốt đồ án này. Tuy đã nỗ lực hết sức, nhưng đồ án vẫn còn những thiếu sót, chúng em rất mong được thầy cũng như các bạn sinh viên góp ý xây dựng. Chúng em xin chân thành cảm ơn. 3 II. Thuật toán MiniMax và AlphaBeta 1. Thuật toán MiniMax 1.1. Mô tả Giả sử chúng ta có một bộ phân tích thế cờ có thể áp dụng tất cả các luật, các phương pháp đánh cờ khác nhau vào từng thế cờ và chuyển đổi chúng thành một con số đại diện (cho điểm thế cờ). Mặt khác, ta giả sử con số đó là dương khi áp dụng cho thế cờ của một đấu thủ (được gọi là người chơi cực đại - maximizer), và là âm khi áp dụng cho đấu thủ bên kia (được gọi là người chơi cực tiểu - minimizer). Quá trình tính toán cho điểm thế cờ được gọi là lượng giá tĩnh (static evaluation). Hàm thực hiện việc tính toán được gọi là một bộ lượng giá tĩnh, và giá trị nhận được gọi là điểm lượng giá tĩnh. Cả hai đấu thủ đều cố gắng đi như thế nào đó để đạt được điểm tuyệt đối lớn nhất. Người chơi cực đại sẽ tìm những nước đi dẫn đến điểm của mình trở nên lớn hơn (hay cao nhất có thể được) hay điểm của đối thủ bớt âm hơn (nhỏ hơn về giá trị tuyệt đối). Còn đấu thủ của anh ta, người chơi cực tiểu, lại ra sức phản kháng lại, để dẫn tới điểm âm của anh ta âm hơn hay điểm dương của đối thủ nhỏ đi (hình 1). 4 Ví dụ một phần cây trò chơi trong hình 2 Người chơi cực đại hi vọng chọn nước đi bên phải để đạt được điểm 8. Thế nhưng nếu đi như vậy thì khi đến lượt đi của người chơi cực tiểu, anh ta sẽ cố gắng không cho người chơi cực đại đạt được điểm này bằng cách chọn nước đi nhánh bên trái và như vậy, người chơi cực đại chỉ được có 1 điểm thay vì 8. Ngược lại, nếu người chơi cực đại chọn nước đi bên trái, thì trong tình huống xấu nhất anh ta vẫn còn được 2 điểm, lớn hơn là chọn nước đi bên phải. Nói chung, người chơi cực đại sẽ phải tìm cách nhận ra các nước đi của đối phương tiếp theo làm cho điểm giảm xuống. Và tương tự như vậy, người chơi cực tiểu phải nhận biết được nước đi của người chơi cực đại cố gắng làm tăng điểm lên. Thủ tục tìm nước đi tốt nhất trên cây trò chơi như trên được gọi là thủ tục Minimax do điểm ở mỗi nút có thể là điểm cực đại hoặc có thể là điểm cực tiểu và có thuật toán như sau: 5 Thuật toán Minimax Nếu như đạt đến giới hạn tìm kiếm (đến tầng dưới cùng của cây tìm kiếm), tính giá trị tĩnh của thế cờ hiện tại ứng với người chơi ở đó. Ghi nhớ kết quả Nếu như mức đang xét là của người chơi cực tiểu, áp dụng thủ tục Minimax này cho các con của nó. Ghi nhớ kết quả nhỏ nhất Nếu như mức đang xét là của người chơi cực đại, áp dụng thủ tục Minimax này cho các con của nó. Ghi nhớ kết quả lớn nhất. 1.2. Xây dựng chương trình cho thuật toán Minimax Dựa vào phát biểu trên để viết chương trình cho thuật toán này bằng ngôn ngữ tựa Java. Đây là một phương thức có tên là Minimax và sẽ là loại đệ qui. Trước hết, để phương thức này biết đã đạt đến giới hạn tìm kiếm chưa, ta cần cung cấp cho nó một tham số về độ sâu tìm kiếm depth (để biết phải tìm đến đâu). Giá trị trả về của hàm chính là điểm của thế cờ (bàn cờ) pos . Mỗi khi Minmax được gọi, nó sẽ càng gần đến giới hạn tìm kiếm, do đó ta sẽ gọi hàm này với độ sâu bằng độ sâu cũ trừ đi một. Đạt đến độ sâu giới hạn chính là khi depth = 0. Khi đạt độ sâu này ta sẽ gọi phương thức lượng giá Eval để đánh giá chất lượng của thế cờ pos hiện tại (thực hiện điều một của thuật toán). Như vậy bước đầu phương này có dạng sau: Public int MinMax (int pos, int depth){ if (depth == 0) //Đã đạt đến giới hạn Return Eval (pos) //Tính giá trị thế cờ pos else{ MinMax (pos, depth - 1); //Gọi đệ qui với độ sâu giản dần } } Ở trên, Minmax được gọi với độ sâu giảm đi một. Đó là độ sâu của các thế cờ là con. Các thế cờ con pos ' đó là các thế cờ được tạo ra từ pos bằng cách đi một nước đi hợp lệ m nào đó. Do đó ta phải có các lệnh thực hiện đi quân để đến các thế cờ mới. Để biết từ thế cờ pos có thể đi được những nước nào, ta dùng một thủ tục Gen có tham số là thế cờ cha pos . Thủ tục này sẽ cất các thế cờ con pos' đó vào bộ nhớ (dạng danh sách). Việc tiếp theo là ta lấy từng thế cờ đó ra và áp dụng tiếp thủ tục Minimax cho nó để tính điểm value của nó. Vậy phương thức MinMax có dạng: 6 public int MinMax (int pos, int depth){ if (depth == 0) return Eval (pos) // Tính giá trị thế cờ pos else{ Gen (pos); //Sinh ra mọi nước đi từ thế cờ pos while (còn lấy được một nước đi m){ pos = Tính thế cờ mới nhờ đi m; value = Minimax (depth-1); //Tính điểm của pos } } } Theo phát biểu của thuật toán, ta thấy các điều 2 và 3 chỉ khác nhau ở cách chọn kết quả tốt nhất best phụ thuộc vào người chơi đang là người chơi cực đại hay cực tiểu. Cuối cùng thuật toán sẽ trả về điểm tốt nhất đạt được. Vậy hàm này được phát triển tiếp thành: public int MinMax (int pos, int depth){ if (depth == 0){ return Eval (pos) //Trả về giá trị thế cờ pos } else{ Gen (pos); //Sinh ra mọi nước đi từ thế cờ pos while (còn lấy được một nước đi m) { pos = Tính thế cờ mới nhờ đi m; value = Minimax (pos, depth-1); //Tính điểm của pos // Chọn điểm tốt nhất tuỳ thuộc theo người chơi if (người chơi là người cực đại) { if (value > best) best = value; } } return best; // Trả về giá trị tốt nhất } Thông thường để cho tiện (và cũng rất gần sự thực) ta coi cả hai người chơi (hai bên) có cùng cách đánh giá về một thế cờ. Có điều thế cờ này là tốt với một người thì phải được đánh giá là tồi với người kia và ngược lại. Trong máy tính cách thể hiện tốt nhất là ta cho điểm một thế cờ có thêm dấu âm dương: dấu dương dành cho người chơi cực đại và dấu âm cho người chơi cực tiểu. Với người chơi cực đại sẽ mong muốn điểm này càng dương càng tốt, còn người chơi cực tiểu lại mong muốn điểm này càng âm càng tốt. Do đó để dễ xử lí ta sẽ tuỳ theo mức người chơi mà đổi dấu giá trị đánh giá thế cờ pos . Chú ý rằng, thay đổi độ sâu là chuyển sang đối phương nên phải đổi dấu. Chương trình thực hiện đổi dấu như sau: 7 value = -Minimax (depth-1); // Tính điểm của pos Cũng do dùng cùng hàm lượng giá nên khi đến lượt người chơi cực đại và cực tiểu có cùng cái nhìn như nhau về một thế cờ. Điều này dẫn đến có thể dùng cùng cách chọn nước đi tốt nhất cho họ (gộp được điều 2 và 3 lại với nhau được). Giá trị best cần được khởi đầu rất nhỏ để đảm bảo không vượt mọi giá trị value, tốt nhất là giá trị - vô cùng: Public int MinMax (int pos, int depth){ if depth = 0 then return Eval (pos); //Trả về giá trị thế cờ pos else{ best = -INFINITY; Gen (pos); //Sinh ra mọi nước đi từ thế cờ pos while (còn lấy được một nước đi m) { pos = Tính thế cờ mới nhờ đi m; value = -MinMax (pos, depth - 1); if (value > best) best = value; } return best; } } Thông thường, bàn cờ được biểu diễn bằng các biến toàn cục. Do đó thay cho truyền tham số là một bàn cờ mới pos vào thủ thục Minimax thì người ta biến đổi luôn biến toàn cục này nhờ thực hiện nước đi "thử" (nước đi dẫn đến bàn cờ mới pos ). Sau khi Minimax thực hiện việc tính toán dựa vào bàn cờ lưu ở biến toàn cục thì thuật toán sẽ dùng một số thủ tục để loại bỏ nước đi này. Minimax bỏ các tham số pos và được xây dựng hoàn chỉnh như sau: public int MinMax(int depth) { if (!run) { return -1; } int best, i, value; if (depth == 0) { return Eval(); } else { best = -INFINITY; Gen(); i = gen_begin[ply]; 8 while (i < gen_end[ply]) { makeMove(gen_dat[i].m); value = MinMax(depth - 1); unMakeMove(); if (value > best) { best = value; if (ply == 0) { newMove = gen_dat[i].m; } } ++i; } return best; } } 1.3. Đánh giá Nếu hệ số nhánh trung bình của cây là b và ta thực hiện tìm kiếm đến độ sâu d thì số nút phải lượng giá ở đáy cây như ta đã biết là b d . Đây chính là số đo độ phức tạp của thuật toán. Nếu b = 40, d = 4 (các con số thường gặp trong trò chơi cờ) thì số nút phải lượng giá là 40 4 = 2560000 (trên 2 triệu rưỡi nút). Còn với b = 40, d = 5 thì số nút phải lượng giá sẽ tăng 40 lần nữa thành 40 5 = 102400000 (trên 102 triệu nút). Lưu ý: toàn bộ ý tưởng của thuật toán này là dựa trên việc chuyển đổi mỗi thế cờ thành một con số để đánh giá. Rất tiếc là các con số này thường không tốt và không đủ để đánh giá hết mọi điều. Mặt khác, thuật toán này có thể rất tốn kém (chạy chậm) do việc sinh các nước đi và lượng giá rất tốn thời gian tính toán, do vậy độ sâu của cây trò chơi cũng bị hạn chế nhiều. Ta cần có thêm những cải tiến để cải thiện tình hình. 2. Thuật toán cắt tỉa AlphaBeta 2.1. Mô tả 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, làm giảm số lượng nút phải sinh và lượng giá, do đó có thể tăng độ sâu của cây tìm kiếm. Giả sử hình 3 là một thế cờ mà hai nút đầu tiên đã được lượng giá. Nếu thực hiện thủ tục Minimax đối với các nút đó sẽ cho thấy người chơi cực đại đã được đảm bảo nếu đi nước bên trái sẽ được ít nhất là 2 điểm dù là các lượng giá của các nút khác cho kết quả như thế nào đi nữa. 9 Bây giờ, ta lại giả sử nút tiếp theo được lượng giá và cho kết quả là 1. Nếu đi vào nhánh này thì đối phương sẽ đảm bảo làm điểm của người chơi cực đại không thể vượt quá được giá trị 1 dù là các lượng giá của các nút khác cho kết quả như thế nào đi nữa. Do đó đến đây, nước đi tốt nhất là chọn nước đi bên trái với đảm bảo là ít nhất đạt được 2 điểm. Và do đó, hoàn toàn không cần thiết phải lượng giá nút còn lại. Nguyên tắc Alpha-Beta Nếu biết điều đó thật sự tồi thì đừng mất thời gian tìm hiểu nó sẽ tồi tệ đến đâu Ý tưởng này được gọi là nguyên tắc Alpha-Beta do nó dùng trong thủ tục AlphaBeta (ta sẽ xét dưới đây). Hai tham số của thủ tục này (theo các đặt tên truyền thống) được gọi là alpha và beta và dùng để theo dõi các triển vọng - chúng cho biết các giá trị nằm ngoài khoảng [alpha, beta] là các điểm "thật sự tồi" và không cần phải xem xét nữa. Khoảng [alpha, beta] còn được gọi là cửa sổ alpha, beta. Trong ngữ cảnh của các trò chơi, nguyên tắc Alpha-Beta nói rằng, mỗi khi xem xét một nút bất kì, nên kiểm tra các thông tin đã biết về các nút cha, ông của nó. Rất có thể do có đủ thông tin từ cha, ông nên không cần phải làm bất cứ việc gì nữa cho nút này. Cũng vậy, nguyên tắc này cũng giúp chỉnh sửa hoặc xác định chính xác giá trị tại nút cha, ông nó. Như trên nói, một cách để tiện 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. 10 [...]... trình cờ tướng áp dụng thuật toán Minimax 16 Trò chơi Cờ Tướng (tên phiên âm Trung Quốc XiangQi, têntiế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 Minimax và AlphaBeta trên cây này như thế nào Đây là một trò chơi thú vị và rất phổ biến ở Việtnam, 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à đọ... trị alpha, trị đó lớn hơn thì đặt alpha bằng giá trị m o Ghi nhớ lại alpha 11 Xây dựng chương trình cho thuật toán AlphaBeta 2.2 Từ phát biểu trên ta sẽ xây dựng hàm AlphaBeta bằng ngôn ngữ tựa Pascal Hàm này sẽ có 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: public int AlphaBeta(int alpha, ... đã áp dụng được thuật toán tìm kiếm Minimax và AlphaBeta vào để giải quyết được bài toán, tuy nhiên trong quá trình làm việc nhóm đã gặp rất nhiều khó 25 khăn; từ việc nghiên cứu và hiểu được giải thuật MiniMax, AlphaBeta đến việc ứng dụng vào bài toán cụ thể Ví dụ như xây dựng hàm định lượng Eval cũng rất khó khăn, vì thực tế để đánh giá được một thể cờ riêng rất khó, những quân cờ khác nhau, kết hợp.. .Thuật toán AlphaBeta * * • Nếu như đạt đến giới hạn tìm kiếm (đến tầng dưới cùng của kiếm) , tính giá trị tĩnh của thế cờ hiện tại ứng với người chơ Ghi lại kết quả * Nếu như mức đang xét là của người chơi cực đại, o Thực hiện các công việc sau cho đến khi tất cả cá nó đã được xét với thủ tục AlphaBeta hoặc cho đế alpha là bằng hoặc lớn hơn beta - Áp dụng thủ tục AlphaBeta với giá trị alp beta. .. } } 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 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 tiếp vòng lặp, có nghĩa là nó không chịu mở rộng tiếp những nhánh còn lại nữa Các nhánh đó đã bị cắt bỏ - và do đó ta sẽ tiết kiệm... lại giữa hai thuật toán Minimax và AlphaBeta để thấy được sự khác biết về tốc độ tính toán 3.2 Xây dựng chương trình a Lượng giá Đá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... gian Việc cắt bỏ này hoàn toàn an toàn với những lí do ta đã xét ở trên Ta thấy rằng mỗi lần hàm này được gọi thì chỉ có tham số beta được dùng để so sánh cắt bỏ, còn tham số alpha không được dùng Tuy nhiên khi áp dụng cùng thuật toán cho cây con thì ta đã hoán vị hai giá trị alpha, beta cho nhau (và đảo cả dấu), do đó alpha sẽ có tác dụng trong độ sâu sau, rồi độ sâu sau nữa lại đến lượt beta Nói... trình mô phỏng thành công thuật toán tìm kiếm MiniMax và phương pháp cắt tỉa AlphaBeta Tuy nhiên chương trình mới chỉ dừng lại ở mục đích học tập nghiên cứu, giao diện chưa được thân thiện với người sử dụng 3 Hướng phát tiển và cải tiến trong tương lai Mặc dù bước đầu đã ứng dụng những thuật toán tìm kiếm với tri thức bổ sung vào một bài toán cụ thể, song chương trình mô phỏng vẫn chưa thực sự hoàn thiện... và d = 5 ta có số nút phải xét là 40 3 + 405/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 Minimax Tỉ lệ số nút AlphaBeta Minimax / AlphaBeta Độ sâu Số nút Số lần tăng 1 40 2 1600 Số nút Số lần tăng 40 1 40 79 1.9 20 3 64000 40 1852... mặt Tướng thủ tục này sẽ không đưa nước đi đó c Giao diện chương trình 3.3 Cài đặt chương trình Chương trình cờ tướng được viết trên nền java, sử dụng IDE là NetBean Toàn bộ Project gồm Source Code các file liên quan được chứa trong thư mục China Chess gửi kèm với báo cáo Để sử dụng có thể chạy file ChineseChess.jar III Kết luận 1 Các vấn đề khó khăn và cách thức giải quyết Mặc dù đã áp dụng được thuậ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 Minimax và AlphaBeta trên cây này như thế nào. Đây là một trò chơi thú vị và rất phổ biến ở Việtnam, châu Á cũng như trên toàn. NỘI VIỆN CÔNG NGHỆ THÔNG TIN VÀ TRUYỀN THÔNG BÁO CÁO BÀI TẬP LỚN TRÍ TUỆ NHÂN TẠO Đề tài: Tìm hiểu và cài đặt thuật toán MinMax và AlphaBeta vào game Cờ Tướng Giảng viên: Phạm Văn Hải Sinh. trị alpha, nếu giá trị đó lớn hơn thì đặt alpha bằng giá trị mới này. o Ghi nhớ lại alpha. 11 2.2. Xây dựng 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

Ngày đăng: 23/10/2014, 23:58

Từ khóa liên quan

Mục lục

  • I. Lời nói đầu

  • II. Thuật toán MiniMax và AlphaBeta

    • 1. Thuật toán MiniMax

      • 1.1. Mô tả

      • 1.2. Xây dựng chương trình cho thuật toán Minimax

      • 1.3. Đánh giá

      • 2. Thuật toán cắt tỉa AlphaBeta

        • 2.1. Mô tả

        • 2.2. Xây dựng chương trình cho thuật toán AlphaBeta

        • 2.3. Đánh giá

        • 3. Chương trình cờ tướng áp dụng thuật toán Minimax

          • 3.1. Mô tả ý tưởng

          • 3.2. Xây dựng chương trình

          • a. Lượng giá.

          • b. Sinh nước đi.

          • c. Giao diện chương trình.

          • 3.3. Cài đặt chương trình

          • III. Kết luận

            • 1. Các vấn đề khó khăn và cách thức giải quyết.

            • 2. Đánh giá chương trình.

            • 3. Hướng phát tiển và cải tiến trong tương lai.

            • 4. Tài liệu tham khảo.

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

  • Đang cập nhật ...

Tài liệu liên quan