My Opera is closing 1st of March

QUANG HOANG'S BLOG

Welcome to everybody !

Ứng dụng thuật toán BFS để làm trò chơi Line

,

hodawa
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.


Người đàn ông đó là aiCài font VNI, TCVN, Unicode và bộ gõ xvnbk vào RedHat Linux

Comments

Unregistered user Tuesday, June 26, 2007 10:31:15 AM

Phúc writes: He he he, Có lời chào thân ái tới thằng bạn! Hôm nay vô tình được một người trong list Y!Messenger 'spam' cái bài "Làm lập trình viên hay không làm lập trình viên?". Thật bất giờ, bài viết này là từ blog của mày. Cái bài này tao nhớ là đã được đọc lâu lắm rồi, nhưng không biết là của ai. Hôm nay, vô tình lại gặp. Thật là có duyên. Dạo này thế nào rồi? Thấy có vẻ ít post bài rồi thì phải? Công việc có vất vả lắm không? Tao thấy mày cũng hy sinh và chịu cày lắm rồi đó, có lẽ đã đến lúc nên nghĩ cho chính mình đi. Tao cũng đã từng có những cảm giác như bài viết của mày vậy... Dù sao cũng cầu chúc cho anh em mình ăn nên làm ra, và không dùng hết thời gian cho công việc... he he, còn gia đình và bạn bè nữa mà. Good Luck to You.

Quang Hoanghodawa Thursday, July 5, 2007 6:46:55 AM

oh, bạn nhầm rồi, bài đó tui chỉ sưu tầm thôi, tui có ghi tên tác giả của bài viết đó ở cuối mà, ko phải tui viết bài đó đâu....

hatcatgiuadoi Saturday, November 17, 2007 4:05:03 PM

chào anh!

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

Hi

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

heocon writes: troi nhin vo chang hieu gi het ah hixhix lam sao de mo code ra doc day huhu

Unregistered user Friday, May 7, 2010 6:10:20 AM

huong writes: chao anh!anh cho em hỏi.trò chơi line dùng giải thuật BFS để thiết kế vậy hàm đánh giá được áp dụng ở chỗ nào ạ? ko a?

Quang Hoanghodawa Friday, May 7, 2010 5:45:38 PM

BFS chỉ dùng để xác định đường đi của viên bi thôi. Còn về hàm đánh giá bạn nói nếu mình hiểu ko lầm là việc kiểm tra các viên bi sau khi di chuyển có bị loại bỏ ra khỏi bảng hay không. Cái đó chỉ cần kiểm tra trên mảng 2 chiều của bảng thì sẽ biết.

Unregistered user Saturday, May 8, 2010 10:53:54 PM

Anonymous writes: Ham danh gia la thuat toan A* ban oi

Quang Hoanghodawa Sunday, May 9, 2010 3:31:38 AM

thuật toán A* dùng để dánh giá cái gì?

Unregistered user Wednesday, October 13, 2010 2:38:45 AM

Nhóc con sành điệu writes: Thuật toán A* : Đánh giá chi phí đường đi, dựa vào đó để chọn đường đi. Là cách kết hợp ưu điểm của 2 phương pháp BFS và DFS.

Unregistered user Saturday, April 16, 2011 3:59:04 AM

Anonymous writes: Anh o! Co the chuyen giup em code tro choi line qua mail cho em voi. bua truoc em co lay roi ma gio mat roi. mail em ne: letrang050788@gmail.com Thanks!

Write a comment

New comments have been disabled for this post.

February 2014
S M T W T F S
January 2014March 2014
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 26 27 28