Tạo mê cung bằng Qt creator

Xin chào mọi người, hiện mình đang gặp rắc rối trong chương trình tạo mê cung bằng phần mềm Qtcreator. Đại khái là mình đã tạo như sau:

Mê cung mà mình định tạo có hình dáng như thế này

Phần rìa đỏ ngoài chính là phần tường rìa ngoài, còn phần xanh bên trong là phía bên trong của mê cung cũng như các bức tường sẽ được tạo ngẫu nhiên để làm thành lối đi trong nó.

Mình quy định là các bức tường sẽ là 0, và nhưng phần không có tường che sẽ là 1.

Đầu tiên mình tạo toàn bộ mảng dữ liệu là 1, sau đó bao viền bên ngoài là 0

Định nghĩa dữ liệu
    int main() {
    int imax=3;
    int jmax=3;
    int kmax=4;
    int countmax=imax*jmax;
    int data[imax][jmax][kmax];
    int xdata[countmax];
    int ydata[countmax];
    int kdata[countmax];
    int count=0;
    int i,j,k;
    int countk[imax][jmax], datas[imax][jmax][kmax];
tạo dữ liệu
//toan bo mang du lieu
    for(i=0;i<imax;i++){
        for(j=0;j<jmax;j++){
            for(k=1; k<=kmax; k++){
                data[i][j][k]=1;
            }
        }
    }

//phan tuong ria ngoai bao boc

    for(i=0;i<imax;i++){
        for(j=0;j<jmax;j++){
            if(j==0){
                data[i][j][1]=0;
                count+=1;
                xdata[count]=i;
                ydata[count]=j;
                kdata[count]=1;
            }
            if(i==0){
                data[i][j][3]=0;
                count+=1;
                xdata[count]=i;
                ydata[count]=j;
                kdata[count]=3;
            }
            if(i==imax-1){
                data[i][j][4]=0;
                count+=1;
                xdata[count]=i;
                ydata[count]=j;
                kdata[count]=4;
            }
            if(j==jmax-1){
                data[i][j][2]=0;
                count+=1;
                xdata[count]=i;
                ydata[count]=j;
                kdata[count]=2;
            }
        }
    }
rồi in
    for(i=0;i<imax;i++){
        for(j=0;j<jmax;j++) {
            for(k=1; k<=kmax; k++){
                qDebug() << "data[" << i << "," << j << "," << k << "] = " << data[i][j][k];
            }
        }
    }
sau đó mình tạo cửa ra/vào
    qDebug() << "count" << count;
    srand(QTime::currentTime().second());
    int numin=rand()%count+1;
    int numout=rand()%count+1;
    int numnum=rand()%count+1;
    while(numin==numout){
        numout=rand()%count+1;
   }
    qDebug() << "numin=" << numin; qDebug() << "numout=" << numout;
    qDebug() << "in=[" << xdata[numin] << "," << ydata[numin] << "," << kdata[numnum] <<"]";
    qDebug() << "out=[" << xdata[numout] << "," << ydata[numout] << "," << kdata[numnum] <<"]";

và mình nhận ra rằng nếu chỉ viết như thế thôi thì cửa ra vào có thể sẽ nằm ở vị trí có giá trị là 1(tức không phải tường), nên mình thêm đoạn mã code này vào (trước đó mình có chỉnh vài lần nhưng vẫn không được nên mình sẽ bê bản chỉnh sửa mới nhất này của mình lên).
Nhưng có vấn đề phát sinh là khi mình dùng thử qDebug() để in thử dữ liệu data[i][j][k] ra thì toàn bộ nó là 0, mình không hiểu tại sao?
Có cao nhân nào vào giải thích hộ mình vì sao và sửa hộ mình được không? (Vấn đề thứ nhất)

    while(data[xdata[numin]][ydata[numin]][kdata[numnum]] == (data[i][j][k] == 1)){
        numnum =rand()%count+1;

    while(data[xdata[numout]][ydata[numout]][kdata[numnum]] == (data[i][j][k] == 1)){
        numnum =rand()%count+1;
    }
    }

//--------------------------------------------------------------------------------------------------------------------------
Sau khi tạo cửa ra vào thì mình muốn in ra một lối đi đi từ “in” ra “out” mà không bị vướng vào “0”.
Và trong quá trình di chuyển nó sẽ tìm xem hướng đó(có tổng 4 hướng) có tường hay không, liệt kê ra(ko phải in ra màn hình) các lối đi không có tường và chọn random các hướng đó để di chuyển tới “out” là kết thúc chương trình.

[details=Ngó hình để hiểu thêm chi tiết]

[/details]

Chúng ta sẽ xuất phát từ ô có cửa “in” và di chuyển sang ô tiếp theo. Khi di chuyển sang ô tiếp theo thi không thể quay lại (tức là tối đa là 3 hướng và thấp nhất sẽ là 0 hướng có thể di chuyển được).
Ông thầy có chỉ mình sử dụng đoạn mã như sau

đoạn mã ông thầy
for(int i=0;i<imax;i++){
    for(int j=0;j<jmax;j++){
        for(int k=1;k<=kmax;k++){
            if(data[i][j][k]==1){
                countk[i][j]=countk[i][j]+1;
                datas[i][j][countk[i][j]]=k;
            }
        }
    }
}

Và có giải thích rằng với đoạn mã này, nếu vào ở ô thứ [0,0,1] thì sẽ có tổng 2 hướng là [0,0,2] và [0,0,4].
data[i][j][k] sẽ kiểm tra nó có phải là tường không, nếu không phải thì tăng countk lên 1. Ở ví dụ này countk =2.
và với mỗi giá trị của countk sẽ có một giá trị tương ứng của datas[i][j][countk[][]] = k.
Nhưng mình thấy đoạn mã này không bắt đầu đi từ “in” nên mình sửa nó thành như sau

    for(i=0; i<imax; i++){
        for(j=0; j<jmax; j++){
            for(k=1; k<=kmax; k++){
                datas[i][j][countk[i][j]] = data[xdata[numin]][ydata[numin]][kdata[numin]];                
                if(data[i][j][k] == 1){
                    countk[i][j] ++;
                    datas[i][j][countk[i][j]] = k;
                }
            }
        }
    }

[spoiler]Sửa rồi nhưng không biết đúng không nữa,[/spoiler] bạn nào cho mình ý kiến (vấn đề thứ 2)
//--------------------------------------------------------------------------------------------------------------------------
sau khi xuất phát được từ cửa và đếm được số hướng có thể đi rồi thì mình không biết làm thế nào để nó di chuyển sang ô tiếp theo bằng cách sử dụng lệnh rand() (mình muốn nó di chuyển ngẫu nhiên) và và in ra hướng đi đi từ “in” ra “out” (vấn đề thứ 3).
//---------------------------------------------------------------------------------------------------------------------------
Phần cuối đấy là mình muốn tạo ngẫu nhiên tường ở phía bên trong nữa thì nên làm như thế nào, có bác nào chỉ giúp mình với được không (ở ví dụ hiện tại chỉ là mê cung 3x3 nhưng sau khi hoàn thiện thì mình sẽ chuyển lên mê cung rộng hơn). (vấn đề thứ 4).
//--------------------------------------------------------------------------------------------------------------------------
Cảm ơn mọi người đã đọc hết toàn bộ những gì mình viết.[spoiler]Muốn khóc luôn quá[/spoiler]

1 Like

Rất muốn giúp nhưng đọc không hiểu gì :sob::sob:
Đây là một bài viết hay :joy::joy:

1 Like

đọc comment của bạn xong tự nhiên mình muốn khóc :sob:

Mình chỉ hỗ trợ bạn đc đoạn code bạn viết sai thôi:

Bạn khai báo toàn bộ biến tại runtime, sẽ ảnh hưởng tới mảng tĩnh như countk, datas,…
Xử lí:
cho toàn bộ thành constexpr


    constexpr  int imax=3;
    constexpr  int jmax=3;
    constexpr  int kmax=4;
    constexpr  int countmax=imax*jmax;
2 Likes

bạn giải thích cái constexpr kĩ hơn một chút được không. Mình chưa được học về constexpr nên mình không hiệu nó nghĩa là gì và có công dụng gì
và bạn bảo gây ảnh hưởng là ảnh hưởng gì ?

Mảng tĩnh là mảng được khởi tạo tại compile time, cho nên toàn bộ thông tin phải được xác định ngay khi compile.
Code bạn dùng cách khai báo bình thường là int xxx = yyy;, nó chỉ được xác định tại runtime
=> mảng tĩnh có thể mang giá trị từ -INT_MAX->INT_MAX chứ không phải giá trị mà bạn khai báo.
Ngày trước người ta thường dùng #define để định nghĩa cho các biến kiểu này, tuy nhiên nó gây đau đầu khi debug
constexpr là từ khóa được đưa vào từ c++11 (?vs thì hình như 2015 mới đưa vào), nó giúp các biến này khai báo và nhận giá trị luôn tại compile time

3 Likes

Ồ ra là thế. Trước ông thầy mình cứ tới đâu thì sẽ định nghĩa lại một lần. Kiểu for(int i… xong tới chỗ khác lại for(int i… Mình thấy chướng mắt quá nên xoá hết int i… đi, chỉ để lại i thôi rồi Khai báo i,j… lên bên trên nhìn cho gọn. Lúc chạy thử nó có cảnh báo tam giác vàng, chắc là do cái này ha

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?