Tìm đường đi ngắn nhất với Breadth First Search trong C# - Source code Wumpus Game
Tìm đường đi ngắn nhất là một trong những bài toán được ứng dụng trong
nhiều lĩnh vực. Và một thuật toán cơ bản và đơn giản nhất để làm điều
này mà bạn có thể đã biết là Breadth First Search (BFS – Tìm kiếm theo
chiều rộng). Cơ chế làm việc của thuật toán tương tự như vết dầu loang,
tìm kiếm những điểm gần nhất trước. Bạn có thể thấy một vài game sử dụng
bản đồ hay liên quan đến AI cũng có thể sử dụng thuật toán này. Một ví
dụ bạn có thể áp dụng thuật toán này là n-puzzle mà tôi đã cài đặt bằng thuật toán A* để giải quyết.
Download sourcecode + demo (VC# 2010) Pass giải nén: hoidapit.com.vn Giới thiệu
Wumpus
là một game điển hình được giải bằng cách sử dụng AI và logic. Tuy
nhiên vì đây là chỉ là mình họa đơn giản cho thuật toán Breadth First
Search nên ta không cần quan tâm tới phần các phần biểu diễn và suy luận
logic trong chương trình.
Dựa vào mục đích trên, tôi sẽ thiệu vài nét cơ bản về game Wumpus. Đây là một game đơn giản có dạng bản đồ bao gồm các đối tượng Agent (nhân vật chính), Pit (hố), Wumpus (một loại quái vật) và Gold (rương vàng).
Giải thuật tổng quátTrong giải thuật này ta cần định nghĩa các thành phần sau:
Ta
thấy rằng G(n) dựa vào tập Close để kiểm tra các vị trí có cần được
kiểm tra hay không. Nếu bạn cài đặt hai tập này bằng một collection thì
tốc độ thực thi sẽ tương đối chậm vì phải thực hiện tìm kiếm phần tử
trong danh sách.
Do ví dụ của ta có dạng bản đồ
nên thay vì dùng collection, ta sẽ sử dụng mảng hai chiều để có thể
truy xuất trực tiếp đến một phần tử dựa vào vị trí. Khi đó ta có thể
kiểm tra thuộc tính của phần tử xem nó đã được duyệt chưa.
Mỗi ô vuông đơn vị trong bản đồ được tôi sử dụng một đối tượng Square sau để biểu diễn. Giá trị của property State của Square cho ta biết chính xác ô đó chứa thứ gì. Thuộc tính Marked chỉ được dùng để đánh dấu làm nổi bật đường đi khi ta tìm thấy đường.Các lớp cơ bản
Phần
vẽ bản đồ đơn giản là ta tạo một mảng Square rồi random đặt các trạng
thái Wumpus, Pit, Gold. Sau cùng dùng sự kiện OnPaint() để hiển thị lên
màn hình.
Lớp BreadthFirstSearch hiện thực
đoạn mã giả ở phần trên bằng C#. Contructor của lớp này nhận một mảng 2
chiều Square để tạo nên mảng MyPoint. Các ô có giá trị là Wumpus hoặc
Pit sẽ không được tạo và sẽ mang giá trị mặc định là null.
Lớp MyPoint được định nghĩa như sau:
Tôi sử dụng biến Previous để lưu vị trí của phần tử trước đó, như vậy khi tìm được đích, ta sẽ dựa vào giá trị này để lần ngược lại đường đi từ vị trí xuất phát đến đích. Bạn có thể thấy phương thức GetSolution() trong lớp BreadthFirstSearch thực hiện điều này như thế nào. Phần kết |