Ứng dụng thuật toán BFS để làm trò chơi Line
Friday, February 23, 2007 4:54:46 AM
Download source code
Chắc hẳn chò chơi Line rất quen thuộc với các bạn, trò chơi gồm một bảng chứa các viên bi, có 5 loại bi được đặt bằng 5 màu khác nhau. Người chơi sẽ di chuyển vị trí của các viên bi để chúng thành một hàng ngang (từ trái qua phải), hàng đứng (từ trên xuống dưới) hay đường chéo 5 viên bi liên tiếp thì 5 viên bi này sẽ được xóa khỏi bảng. Trò chơi kết thúc khi bảng đầy các viên bi.Để làm chò chơi Line đầu tiên các bạn phải xác định được đường đi của viên bi (khi các bạn chọn một viên bi và chọn vào một ô trống nào đó trên bảng). Có thể có rất nhiền cách để xác định đường đi này, ở đây tôi chỉ xin trình bày cách sử dụng thuật toán BFS để tìm đường đi của viên bi trên bảng. Để áp dụng thuật toán BFS các bạn xem bảng như một đồ thị với mỗi ô trên bảng như một đỉnh của đồ thị.
Giả sử các bạn cần tìm đường đi từ ô (si, sj) đến (fi, fj), các bạn sử dụng 2 hàng đợi để loang. Đầu tiên các bạn bỏ phần tử đầu tiên (si, sj) vào hàng đợi. Sau đó các bạn lặp vòng lặp sau để tìm đường đi:
Trong khi (Hàng đợi[0] chưa rỗng)
{
Lấy từng phần tử trong Hàng đợi[0]
{
Kiểm tra 4 ô xung quanh (trên, dưới, trái, phải) của phần tử này
{
Nếu là ô còn trống
{
- Bỏ phần tử này vào Hàng đợi[1]
- Lưu lại đường đi từ phần từ này đến vị trí mới (là 1 trong 4 ô xung quanh phần tử hiện tại)
- Nếu phần tử này là ô đích
Dừng vòng lặp chính (Thành công)
}
}
}
Bỏ tất cả các phần tử của Hàng đợi[1] vào Hàng đợi[0] để tiếp tục loang
}
Sau khi kết thúc vòng lặp --> Không tìm thấy đường đi (Thất bại)
//Loang (BFS) trên lưới để tìm đường đi từ (si, sj) đến (fi, fj)
private bool BFS(int si, int sj, int fi, int fj, Point [] pPath)
{
int [] di = {-1, 1, 0, 0}; //mảng lưu hướng đi (trên, dưới, trái, phải)
int [] dj = {0 , 0,-1, 1};
int i, j, k, nCount;
bool [,] bCheck = new bool[ nMaxCell, nMaxCell ]; //mảng đánh dấu các ô đã xét
Point [,] pQuery = new Point[ 2, nMaxCell * nMaxCell ]; //2 hàng đợi để loang
Point [,] pPathBall = new Point[ nMaxCell, nMaxCell ]; //mảng lưu các ô đã đi qua
Point pStart, pFinish, pCurrent;
pStart = new Point(si, sj);
pFinish = new Point(fi, fj);
//Bỏ phần tử đầu tiên vào hàng đợi
int nQueryLast = 1;
pQuery[0, 0] = pStart;
//Khởi tạo mảng đánh dấu các ô đã đi qua
for (i=0; i < nMaxCell; i++)
for (j=0; j < nMaxCell; j++)
bCheck[i,j] = anBoard[i,j] > 0; //đánh dấu các ô đã có viên bi là true
bCheck[pStart.X, pStart.Y] = true; //đánh dấu ô xuất phát
if (bCheck[fi, fj]) //nếu ô đích là ô đã có viên bi
return false; //thì không cần tìm kiếm vì chắc chắn không có kết quả
pPathBall[pStart.X, pStart.Y] = new Point(-1,-1); //danh dấu ô xuất phát
//LOANG (BFS)
while (nQueryLast > 0) //Trong khi Hàng đợi[0] chưa rỗng
{
nCount = 0;
//Xét tất cả các phần tử trong Hàng đợi[0]
for (int nLast=0; nLast < nQueryLast; nLast++)
{
pCurrent = pQuery[0, nLast ];
//Tìm xung quanh 4 hướng của ô (i,j) xem có hướng nào có thể đi được không ?
for (k=0; k < 4; k++)
{
i = pCurrent.X + di[k];
j = pCurrent.Y + dj[k];
if (i>=0 && i < nMaxCell && j >=0 & j < nMaxCell && !bCheck[i, j])
{
pQuery[1, nCount++] = new Point( i, j);
bCheck[ i , j ] = true;
pPathBall[ i , j ] = new Point(pCurrent.X, pCurrent.Y);
if (bCheck[ fi, fj]) //Tìm thấy ô đích, thì dừng tìm kiếm
{
nCountPath = 0;
FindPath(new Point(fi, fj), pPathBall);
nIndexPath = 0;
tmrPath.Enabled = true;
return true;
}
}
}
}
//Bỏ tất cả các phần tử của pQuery[1] vào pQuery[0] để tiếp tục loang
for (k=0; k < nCount; k++)
pQuery[ 0, k ] = pQuery[ 1, k ];
nQueryLast = nCount;
}
return false;
}
Để truy hồi đường đi ta sẽ truy hồi từ đỉnh đích tới đỉnh xuất phát, giải thuật đệ quy như sau:
private void FindPath(Point p, Point [,] pPathBall)
{
//Nếu đỉnh trước của đỉnh (p.X, P.Y) không phải là đỉnh xuất phát
if (pPathBall[ p.X, p.Y ] != new Point(-1,-1))
FindPath(pPathBall[ p.X, p.Y ], pPathBall); //Tiếp tục truy hồi
pPath[nCountPath++] = p; //Lưu các đỉnh đã truy hồi vào mảng pPath
}
Trên đây chỉ là giải thuật chính để làm trò chơi Line, ngoài ra còn có các hàm để xóa các viên bi (khi đủ 5 viên liên tiếp) và hàm tạo ngẫu nhiên 3 vị trí tiếp theo trên bảng và các hàm phụ khác còn toàn bộ code của bài viết này download tại đây.













Unregistered user # Tuesday, June 26, 2007 10:31:15 AM
Quang Hoanghodawa # Thursday, July 5, 2007 6:46:55 AM
hatcatgiuadoi # Saturday, November 17, 2007 4:05:03 PM
Em đang có một bài tập vẽ đồ thị trên VC++(MFC).
Bài tập yêu cầu vẽ đồ thị với 2 trục X,Y. Với các điểm tọa độ (x,y) thay đổi.
Hay với một tọa độ nhập vào sẽ hiển thị lên hình ảnh của tọa độ đó trên đồ thị.
Anh có thể hướng dẫn cho em làm bài tập này được ko ?
vì em với tiếp xúc với ngôn ngữ VC++ nên còn rất nhiều bỡ ngỡ.
Cám ơn anh rất nhiều.
thucv # Monday, September 29, 2008 10:10:14 AM
Em co bai toan 7 cay cau
bay gio em dang can dung giai thuat DFS va BFS (ca quay lui cung duoc)
de giai bai toan nay
Nhung kho qua em chua biet the nao ca
Anh nao co giup em voi'
Unregistered user # Tuesday, April 27, 2010 12:24:24 PM
Unregistered user # Friday, May 7, 2010 6:10:20 AM
Quang Hoanghodawa # Friday, May 7, 2010 5:45:38 PM
Unregistered user # Saturday, May 8, 2010 10:53:54 PM
Quang Hoanghodawa # Sunday, May 9, 2010 3:31:38 AM
Unregistered user # Wednesday, October 13, 2010 2:38:45 AM
Unregistered user # Saturday, April 16, 2011 3:59:04 AM