Thuật toán khởi đầu tại đỉnh gốc hoặc chọn mộtđỉnh nào đó coi như gốc và duyệt tất cả các đỉnh lân cận.. Khi đã kiểm tra một đỉnh, đỉnh đó sẽ được đánh dấu đi qua.. Quá trìnhđó lặp lại c
Trang 1BỘ CÔNG THƯƠNG TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
BÁO CÁO BÀI TẬP LỚN HỌC PHẦN
TRÍ TUỆ NHÂN TẠO
Đề tài: Xây dựng trò chơi 3 tu sĩ và 3 con quỷ
Thành viên: Nguyễn Phúc Hưng
Nguyễn Quang Hưng
Hà Nội, Năm 2022
Trang 2MỤC LỤC
MỤC LỤC 1
LỜI CẢM ƠN 2
DANH SÁCH HÌNH VẼ……….3
CHƯƠNG 1 Cơ sở lý thuyết………4
CHƯƠNG 2 Phân tích bài toán 7
2.1 Mục đích bài toán 7
2.2 Thuật toán của bài toán 8
CHƯƠNG 3 Lập trình trò chơi 9
3.1 Chương trình cho người tự chơi 9
3.1.1 Giới thiệu tổng quan trò chơi……… 9
3.1.2 Mã nguồn và giải thích……… 9
3.2 Chương trình cho máy tự chơi 12
3.2.1 Giới thiệu tổng quan trò chơi………12
3.2.2 Mã nguồn và giải thích……… 12
CHƯƠNG 4 Giao diện chương trình 18
4.1 Giao diện chương trình……….18
4.1.1 Giao diện chương trình cho người chơi………18
4.1.2 Giao diện chương trình cho máy tự chơi……… 18
CHƯƠNG 5 Kết luận ………20
5.1 Kết luận……….20
CHƯƠNG 6 Tài liệu tham khảo ……….21
6.1 Tài liệu tham khảo……… 21
Trang 3LỜI CẢM ƠN
Là một sinh viên trường đại học Công nghiệp Hà Nội, báo cáo bài tập lớn
là minh chứng cho những kiến thức đã có sau thời gian học tập Trong quá trình hoàn thành bài tập lớn, ngoài sự cố gắng của nhóm thì nhóm cũng nhận được sự hướng dẫn tận tình của thầy Trần Thanh Huân Qua đây, nhóm xin chân thành cảm ơn khoa Công nghệ thông tin, trường đại học Công nghiệp Hà Nội đã trang
bị kiến thức cho em trong suốt quá trình học tập Đặc biệt, nhóm cảm ơn tới thầyTrần Thanh Huân đã luôn giúp đỡ, hướng dẫn, chỉ bảo tận tình để giúp nhóm hoàn thành tốt bài tập lớn của mình Nhóm đã cố gắng hoàn thành bài tập lớn nhưng vẫn rất mong nhận được sự đóng góp ý của thầy cô và các bạn để bài tập lớn cuả nhóm được hoàn thiện hơn
Chúng em xin chân thành cảm ơn!
Nhóm thực hiện
18
Trang 4DANH SÁCH HÌNH VẼ Danh sách hình vẽ:
Hình 1: Mô tả thuật toán……….4
Hình 2: Ví dụ đồ thị BFS………5
Hình 3: Sơ đồ cây……… 13
Hình 4: Giao diện bắt đầu……… 18
Hình 5: Giao diện đăng ký………18
Hình 6: Giao diện đăng nhập………19
Hình 7: Giao diện trò chơi (trò chơi dành cho người)……… 19
Hình 8: Giao diện trò chơi (trò chơi dành cho máy)………19
Trang 5CHƯƠNG 1 Cơ sở lý thuyếtThuật toán tìm kiếm theo chiều rộng (BFS: Breadth First Search)
1.1 Ý tưởng thuật toán
Tìm kiếm theo chiều rộng (BFS) là một thuật toán duyệt hoặc tìm kiếmtrên một cây hoặc đồ thị Thuật toán khởi đầu tại đỉnh gốc (hoặc chọn mộtđỉnh nào đó coi như gốc) và duyệt tất cả các đỉnh lân cận Sau đó, lần lượtđối với các đỉnh lân cận, nó kiểm tra các đỉnh con của đỉnh đó mà chưa điqua Khi đã kiểm tra một đỉnh, đỉnh đó sẽ được đánh dấu đi qua Quá trình
đó lặp lại cho đến khi tìm được đường đi ngắn nhất
Chính xác hơn, thuật toán có thể được mô tả như sau:
Đầu tiên ta thăm đỉnh nguồn S
Việc thăm đỉnh ss sẽ phát sinh thứ tự thăm các đỉnh (u1, u2,
… up) (u1, u2, …up) kề với S (những đỉnh gần S nhất) Tiếptheo, ta thăm đỉnh u1, khi thăm đỉnh u1 sẽ lại phát sinh yêucầu thăm những đỉnh (v1, v2, …, vq) (v1, v2, …, vq) kềvới u1 Nhưng rõ ràng những đỉnh v này “xa” Ss hơn nhữngđỉnh u nên chúng chỉ được thăm khi tất cả những đỉnh u đều
đã được thăm Tức là thứ tự thăm các đỉnh sẽ là: s, u1, u2, …,
up, v1, v2, …, vq, …
Mô tả thuật toán
Trang 6Thuật toán tìm kiếm theo chiều rộng sử dụng một danh sách để chứanhững đỉnh đang “chờ” thăm Tại mỗi bước, ta thăm một đỉnh đầu danhsách, loại nó ra khỏi danh sách và cho những đỉnh kề với nó chưa đượcthăm xếp hàng vào cuối danh sách Thuật toán sẽ kết thúc khi danhsách rỗng.
1.2 Phân tích thuật toán
Thuật toán sử dụng một cấu trúc dữ liệu hàng đợi (queue) để
chứa các đỉnh sẽ được duyệt theo thứ tự ưu tiên chiều rộng
Các bước thực hiện thuật toán:
Bước 1: Khởi tạo
Các đỉnh đều ở trạng thái chưa được đánh dấu Ngoại trừđỉnh nguồn s đã được đánh dấu
Một hàng đợi ban đầu chỉ chứa 1 phần tử là s
Bước 2: Lặp lại các bước sau cho đến khi hàng đợi rỗng:
Lấy đỉnh u ra khỏi hàng đợi
Xét tất cả những đỉnh v kề với u mà chưa được đánh dấu,với mỗi đỉnh v đó:
o Đánh dấu v đã thăm
o Lưu lại vết đường đi từ u đến v
o Đẩy v vào trong hàng đợi (đỉnh v sẽ chờ được duyệttại những bước sau)
Bước 3: Truy vết tìm đường đi.
1.3 Ví dụ
Xét đồ thị sau đây, với đỉnh nguồn s = 1
Trang 7Hình 2: Ví dụ đồ thị BFS
Để thứ tự các phần tử lấy ra khỏi hàng đợi, ta thấy trước hết là 1; sau đóđến 2, 3; rồi mới tới 4, 5; cuối cùng là 6 Rõ ràng là đỉnh gần S hơn sẽđược duyệt trước Và như vậy, ta có nhận xét: nếu kết các thuật toán đồ thịhợp lưu vết tìm đường đi thì đường đi từ S tới F sẽ là đường đi ngắn nhất(theo nghĩa qua ít cạnh nhất)
ST
T
Đỉnh đã duyệt Các đỉnh
trong hàng đợi
Trang 8CHƯƠNG 2 Phân tích bài toán2.1Mục đích của bài toán
Bài toán tập trung vào quy tắc: Nếu ở 1 nơi nào đó, số quỷ nhiều hơn số
tu sĩ thì quỷ sẽ ăn thịt tu sĩ- nói theo ứng xử trò chơi, đây là trạng thái thua-
còn nói theo tập trạng thái ta muốn xây dựng thì đây là trạng thái vi phạm, vó
nó sẽ không được xem xét trong tập trạng thái
Cách thức biến đổi từ trạng thái này đến trạng thái khác là: Từ bờ bên này có thuyền chở 1, 2 tu sĩ hoặc qủy lên thuyền vào cho chạy qua bờ bên kia.Trạng thái xung đột sẽ chỉ được xem xét sau khi tu sĩ hay quỷ đã sang được bên kia
Tìm kiếm theo chiều rộng (BFS) là một thuật toán tìm kiếm trong đồ thị trong đó việc tìm kiếm chỉ bao gồm 2 thao tác: (a) cho trước một đỉnh của
đồ thị; (b) thêm các đỉnh kề với đỉnh vừa cho vào danh sách có thể hướng tới tiếp theo Có thể sử dụng thuật toán tìm kiếm theo chiều rộng cho hai mục đích: tìm kiếm đường đi từ một đỉnh gốc cho trước tới một đỉnh đích, và tìm kiếm đường đi từ đỉnh gốc tới tất cả các đỉnh khác Trong đồ thị không có trọng số, thuật toán tìm kiếm theo chiều rộng luôn tìm ra đường đi ngắn nhất
có thể Thuật toán BFS bắt đầu từ đỉnh gốc và lần lượt nhìn các đỉnh kề với đỉnh gốc Sau đó, với mỗi đỉnh trong số đó, thuật toán lại lần lượt nhìn trước các đỉnh kề với nó mà chưa được quan sát trước đó và lặp lại Xem thêm thuậttoán tìm kiếm theo chiều sâu, trong đó cũng sử dụng 2 thao tác trên nhưng có trình tự quan sát các đỉnh khác với thuật toán tìm kiếm theo chiều rộng
Trang 92.2Thuật toán của bài toán
Xét về nơi có thể xảy ra xung đột thì có tất cả 3 nơi:
Cho nên ta chỉ quan tâm đến tình trạng tu sĩ và quỷ 2 bên bờ, và vị trí của thuyền ở bờ 1 hay bờ 2 Một nhận xét nữa là nếu đã biết bờ 1 có x tu sĩ, y quỷ, ta cũng biết luôn bên bờ 2 có 3-x tu sĩ và 3-y quỷ Vậy để phân biệt các trạng thái của bài này ta chỉ cần biết 3 yếu tố:
- Số tu sĩ ở bờ 1(x)
- Số quỷ bở bờ 1(y)
- Thuyền có đang ở bờ 1 không(b) (true/false)
Như vậy, chỉ cần dung 1 mảng [3][3][2]- theo thứ tự [số tu sĩ bờ 1][số quỷ bờ 1][thuyền có đang ở bờ 1 không ?] là có thể mô tả tất cả các trạng thái có thể Quy tắc xung đột đối với trạng thái[x,y,b]: Xung đột nếu:
o Hoặc là x>0 và y>x (xung đột ở bên bờ 1)
o Hoặc là 3-x>0 và 3-y>3-x (xung đột bên bờ 2)
Tập trạng thái có thể đến từ [x,y,true] :1,y,false], 2,y, false], 1,y-1,false], [x,y-1,false], [x,y-2,false]
[x-Tương tự ta có tập trạng thấy[x,y,false]: [x+1,y,true], [x,y+1,true], [x+1,y+1,true],[x+2,y,true],[x,y+2,true]
Thực tế thì phải xem xét xem các giá trị thực của x, y
Trạng thái đầu: [3, 3, true]
Trạng thái đích: [0, 0, false]
Trang 10CHƯƠNG 3 Lập trình trò chơi3.1 Trò chơi cho người chơi
3.1.1 Giới thiệu tổng quan trò chơi
Trò chơi được xây dựng dưới dạng web game, xử dụng HTML, CSS vàJavascript để lập trình thuật toán và giao diện người dung Trò chơi bao gồm phần đăng nhập, đồng hồ tính thời gian
3.1.2 Mã nguồn thuật toán và giải thích
Mã nguồn cơ chế hoạt động của trò chơi Cách nhận diện tu sĩ và quỷ trong khi chuyển đổi trạng thái của tu sĩ hoặc quỷ từ bờ này sang bờ kia:
sĩ hay quỷ Sau đó số lượng tu sĩ và quỷ sẽ được lưu trong 2 biến m và p
if(m>p && m!=0 && p!=0)
{
return true;
Trang 12return false;
};
Khi số lượng tu sĩ và quỷ ở bên bờ trái có ổng bằng 6 mà không có xung đột nào thì trò chơi sẽ kết thúc, người chơi thắng Sau đó hệ thống sẽ ghilại thời gian chơi Nếu có xung đột hoặc số lượng tu sĩ và quỷ bên bờ trái chưa đủ 6 trò chơi sẽ tiếp tục hoặc người chơi sẽ phải chơi lại từ đầu
- Hiển thị thông báo thắng:
var gameOver = function() {
move=true;
boat_p.style.left = 700+"px";
for (var i = 0; i < boat.length; i++) {
var ids = document.getElementById(boat[i]);
ids.style.left=ids.getBoundingClientRect().left+330+"px"; }
} else {
move=false;
boat_p.style.left = 370+"px";
for (var i = 0; i < boat.length; i++) {
Trang 13var ids = document.getElementById(boat[i]);
ids.style.left=ids.getBoundingClientRect().left-330+"px"; }
Sứ dụng getBoundungClientRect() để do khoảng cách của thuyền đến mép trái của khu vực chơi, nếu trả về giá trị 370px thì thuyền đang ở bờ bên phải, ngược lại nếu trả về giá trị 40px thì thuyền đang ở bờ trái Lúc này khi bấm nút di chuyển trên màn hình, thuyền sẽ được di chuyển đúng cách từ trái sang phải và ngược lại Khoảng cách giữa 2 bờ là 330px, vì vậy khi di chuyển sang phải giá trị getBoundingClientRect() sẽ trừ đi 330px và khi di chuyển sang phải thì sẽ cộng 330px
} }
else
{
alert("Driver is required to drive Boat");
}
Khi kiểm tra thấy trên thuyền không có ai thì hiển thị thông báo không có người lái thuyền Thuyền được khai báo dưới dạng chuỗi, khi kiểm tra chuỗi rỗng thì không có tu sĩ hay quỷ trên thuyền
3.2 Chương trình cho máy tự chơi
3.2.1 Giới thiệu tổng quan trò chơi
Chương trình cho máy tự chơi được xây dựng dưới dạng ứng dụng console, sử dụng ngôn ngữ C# để cài đặt và sử dụng thuật toán tìm kiếm theo chiều rộng để máy tự tìm thấy cách giải và hiển thị các bước giải ra màn hình
3.2.2 Mã nguồn thuật toán và giải thích
Để có thể để cho máy tự chơi và tự tìm lời giải, ta phải liệt kê hết các trạng thái chuyển đổi chi tiết dựa trên các trạng thái chuyển đổi tổng quát như
đã kể ở phần 1.2 Sau đây là 26 trạng thái chuyển đổi:
Trạng thái đầu: [3,3,true](0) – trạng thái đích: [0,0,false](25)
(1) [2,2,false] (9) [3,1,false] (17)[3,1,true]
(2) [3,2,false] (10)[3,0,false] (18) [2,2,true]
(3) [3,1,false] (11) [3,2,true] (19) [0,2,false]
(4) [3,3,true] (12) [3,3,true] (20) [1,1,false]
Trang 14(6) [3,3,true] (14) [3,2,true] (22) [0,3,false] (7) [3,2,true] (15) [1,1,false] (23) [0,1,false] (8) [2,2,false] (16) [3,0,false] (24) [0,2,false]
Sơ đồ cây:
Sơ đồ câyCác nốt được đánh số thứ tự giống với thứ tự của các trạng thái chuyển đổi đãlưu ở trên
Giải thích mã nguồn:
- Xây dựng lớp trạng thái chuyển đổi:
public class SolveAI
{
public int priets { get; set; }
public int demon { get; set; }
public bool onright {get; set; }
public void InBuoc()
Trang 15Console.WriteLine($"chuyen sang bo 2: {3 - priets} tu si");
Console.WriteLine($"chuyen sang bo 2: {3 - demon} quy");
}
else
{
Console.WriteLine($"chuyen ve bo 1: {Math.Abs(priets-3)} tu si");
Console.WriteLine($"chuyen ve bo 1: {Math.Abs(demon - 3)} quy");
chuyển sang bờ trái Ngược lại khi thuộc tính onright là true thì thuyền vừa vận chuyển tu sĩ hoặc quỷ từ trái sang phải
- Xây dựng lớp sơ đồ cây:
public class Graph<T>
Trang 16có hướng Sau đó sử dụng thêm IEnumberable<Tuple<T,T>> edges để thêm liên kết có hướng giữa các nút thông qua phương thức AddEdge() Trong phương thức AddEdge, ta sử dụng AdjacncyList(Danh sách kề) để thiết lập liên kết đầu cuối giữa 2 nốt để xách định hướng của liên kết
- Thuật toán tìm đường ngắn nhất:
public class Algorithms
{
public Func<T, IEnumerable<T>> ShortestPathFunction<T>(Graph<T> graph, T start)
{
var previous = new Dictionary<T, T>();
var queue = new Queue<T>();
queue.Enqueue(start);
while (queue.Count > 0)
{
var vertex = queue.Dequeue();
foreach (var neighbor in graph.AdjacencyList[vertex])
Trang 17Func<T, IEnumerable<T>> shortestPath = v => {
var path = new List<T> { };
sử dụng phương thức shortestPath, khao báo biến path kiểu list để ghi đường
đi, current để xét nút hiện tại Khi nút current khác nút bắt đầu, thêm nút đangxét vào danh sách path và tìm nút trước đó của current bằng previous cho đến khi vòng lặp kết thúc, ta thêm nút bắt đầu rồi đảo ngược chuỗi để có đường đi
đi ngắn nhất đến điểm cuối từ điểm đầu
- Áp dụng vào bài toán:
Khai báo các trạng thái chuyển đổi:
SolveAI[] a = new SolveAI[30];
a[0] = new SolveAI() { priets = 3, demon = 3,onright=true };
a[1] = new SolveAI() { priets = 2, demon = 2, onright = false };
Trang 18a[3] = new SolveAI() { priets = 3, demon = 1, onright = false };
a[4] = new SolveAI() { priets = 3, demon = 2, onright = true };
….
Khai báo số nút tương ứng với số lượng trạng thái chuyển đổi:
var vertices = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25};
Khai báo liên kết giữa các nút:
var edges = new[]{Tuple.Create(0,1), Tuple.Create(0, 2) , Tuple.Create(0, 3), Tuple.Create(2, 5), Tuple.Create(1, 4), Tuple.Create(1, 7),Tuple.Create(3,7),
Tuple.Create(3,6),Tuple.Create(7,8),Tuple.Create(7,9),Tuple.Create(7,10),Tuple.Create(9, 11),Tuple.Create(9,12),Tuple.Create(9,11),Tuple.Create(10,13),Tuple.Create(10,14),Tuple Create(13,15),Tuple.Create(13,16),Tuple.Create(15,17),Tuple.Create(15,18),Tuple.Create( 18,19),Tuple.Create(18,20),Tuple.Create(19,21), Tuple.Create(19,22), Tuple.Create(22,23), Tuple.Create(23,24),Tuple.Create(24,25)};
Tìm đường và in ra các bước giải:
var shortestPath = algorithms.ShortestPathFunction(graph, startVertex);
string[] arrListStr = string.Join(", ", shortestPath(25)).Split(new char[] { ',' }); foreach (var q in arrListStr)
{
int temp = Int32.Parse(q);
a[temp].InBuoc();
Trang 19CHƯƠNG 4 GIAO DIỆN CHƯƠNG TRÌNH4.1 Giao diện chương trình
4.1.1 Chương trình cho người chơi
Giao diện bắt đầu
Giao diện đăng kí
Trang 20Giao diện đăng nhập
Giao diện trò chơi
4.1.2 Giao diện trò chơi cho máy
Giao diện trò chơi
Trang 21CHƯƠNG 5. Kết luận 5.1 Kết luận
Nhóm đã giải quyết được bài toàn lập trình game 3 tu sĩ và 3 con quỷ dành cho người chơi bằng HTML và CSS và phần game dành cho máy tự chơi bằng ngôn ngữ C# Tìm ra thuật toán của chương trình và hiểu rõ về giải thuật tìm kiếm theo chiều sâu Tuy nhiên, phần game dành cho máy tự chơi chỉ là một ứng dụng
console, chỉ hiện thị trắng đen chưa có giao diện thân thiện với người dung, chúng
em sẽ học thêm về ngôn ngữ python và các framework để thiết kế lại phần game dành cho máy có giao diện dễ nhìn và hiện thị rõ các bước đi của máy.
Thông qua việc tìm hiểu và nghiên cứu đề tài này giúp chúng em đã có cái nhìn toàn diện hơn trong việc ứng dụng trí tuệ nhân tạo vào giải quyết vấn đề thực
tế Đây là bài toán đặc trưng trong trí tuệ nhân tạo cho các thuật toán tìm kiếm đường đi liên quan đến tìm kiếm có tri thức bổ sung Đề tài đã được nhiều người nghiên cứu giải quyết, hiện nay nó đã được ứng dụng rất nhiều trong thực tế và mang lại một nguồn lợi vô cùng to lớn Hy vọng những nghiên cứu đánh giá của chúng em sẽ góp phần giải quyết một số tình huống nhỏ và giải thích cho các bạn nguyên lý hoạt động của những app map Do thời gian có hạn nên đề tài không tránh khỏi những sai sót, mong thầy cô góp ý, đánh giá giúp chúng em hoàn thiện
đề tài.