Ergebnis 1 bis 6 von 6

Thema: MineSweeper mit Visual Basic

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1

    MineSweeper mit Visual Basic

    FF I Weißmagier: Hi, ich sitze hier grade mit Sumi im Info Unterricht und wir haben spontan beschlossen Minesweeper zu programmieren.
    Haben auch schon die Erlaubnis von unserem Info Lehrer und bräuchten jetzt ein paar Infos:

    1. Wie geht das?

    Sumi: Mal von mir selber, nachdem Weißi mir die Tasta geklaut hat.
    Das Visual haben wir, das Basic fehlt.

    Also:
    Wir haben labels erstellt, als Minenzähler und als Timer.
    Auch haben wir den Startbutton.

    Das Spielfeld haben wir momentan aus Command buttons erstellt.

    Problem 1:
    Wie verändert man jene Buttons, wenn man auf den nachbarbutton klickt.

    Ich selbst glaube, man bräuchte mehrere Ebenen, die 1. wo die Zahlen und die Minen liegen, die 2. wo halt die Buttons sind ... ... Letztenendes hab ich die gleiche Frage wie Weißmagier: Wie geht das?

    Unser Lehrer kann uns auch nichtmehr weiterhelfen und wir fighten uns grade durch die Hilfe, doch vielleicht ginge das mit Eurer Hilfe etwas schneller.

    lg
    FF I Weißmagier
    und
    Sumi

  2. #2
    ihr koenntet versuchen, die Buttons als Buttonlist zu machen, damit ihr auf diese wie mit einem Array zugreifen koennt, um somit die Nachbarn zu Berechnen, die um den Button herum liegen.

    Das mit den Zahlen und Mienen wuerde ich vielleicht so machen, dass das eine Graphik ist, die unter den Buttons liegt, und dass beim klick der Button unsichtbar und unklickbar gemacht wird ...

    Allerdings hab ich vom VB keine Ahnung ...

    Gruss Ineluki

  3. #3
    Sumi: Also wir haben uns erstmal die .gif Dateien runtergeladen

    Das mit dem Untergrundbild hatten wir auch schon in betracht gezogen. Allerdings wollten wir eine Minenverteilung haben, somit 'random'-like ... Momentan kommen wir auch recht gut vorran. : D

    Erstmal danke für die schnelle Antwort.

    Melden uns bei weiteren Fragen ^^
    Die sich scheinen wie von selbst zu klären, wenn man sich in der Hilfe umschaut *g*

    lg
    Sumi

  4. #4
    Zitat Zitat von Sumi
    Das mit dem Untergrundbild hatten wir auch schon in betracht gezogen. Allerdings wollten wir eine Minenverteilung haben, somit 'random'-like ... Momentan kommen wir auch recht gut vorran. : D
    Da die Buttons und die Untergrundbilder ja nur eine Darstellung des eigentlichen Spielfeldes sind, sollte es kein Problem sein die Benutzeroberfläche (Buttons usw.) erst nach dem Füllen des Spielfeldes aufzubauen. Also könnt ihr die Minen zufällig im Spielfeld verteilen und hinterher erst die entsprechende graphische Darstellung erzeugen.
    Vielzitiert aber immer wieder gut: Für solche Anwendugen eignet sich das Model-View-Controller (MVC) Muster.

    Geändert von Master of Disaster (11.01.2005 um 13:23 Uhr)

  5. #5
    Ich habe genau das gefunden was ihr sucht, hier:
    Klick mich für Tut

  6. #6
    Seltsam, gerade noch vor einer Woche hab ich einen MineSweeper-Clone in C++ geschrieben (oder den Ansatz dazu):

    Code:
    /*  Programm: MineSweeper
        Author:   Stefan Hof
        Date:     21. December 2004
    */
    
    #include <windows.h>
    #include <iostream.h>
    #include <fstream.h>
    #include <string.h>
    
    #define EMPTY 0
    #define BOMB 1
    #define SAVED_BOMB 2
    #define EXPLODED_BOMB 3
    
    struct feld_struct
    {
        bool status;        //false = zu, true = aufgedeckt
        short type;         //0 = empty, 1 = bomb
        char seek_status;  //'s' = anliegend, 'd' = bereits durchgecheckt, b = BOMB.
    } feld[10][10];
    
    
    void update_buttons(int, int);
    void seek_position(int, int);
    
    HANDLE h_exploded = LoadImage(0, "exploded_mine.bmp", IMAGE_BITMAP, 16, 16, LR_LOADFROMFILE);
    HANDLE h_saved = LoadImage(0, "saved_mine.bmp", IMAGE_BITMAP, 16, 16, LR_LOADFROMFILE);
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    HINSTANCE hbinstance;
    int z = 0, pushed = -1, zehner, einer, idchild;
    //short feld[10][10];
    HWND hwndchild, hwnd;
    
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                        PSTR szCmdLine, int showpref)
    {
        static char AppName[] = "WinTextedit 1.0";
        MSG msg;
        WNDCLASS wndclass;
    
        wndclass.style = NULL;
        wndclass.lpfnWndProc = WndProc;
        wndclass.cbClsExtra = 0;
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
        wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH) COLOR_MENU + 3;
        wndclass.lpszMenuName = NULL;
        wndclass.lpszClassName = AppName;
        
        if (RegisterClass(&wndclass) == false)
        {
            MessageBox(NULL, "Es ist ein Fehler aufgetreten. ", "Error! ", MB_ICONERROR);
            return 0;
        }
        
        hwnd = CreateWindow (AppName,
                             TEXT("WinProgramm 1.0"),
                             WS_OVERLAPPEDWINDOW,
                             100,
                             100,
                             258,
                             314,
                             NULL,
                             NULL,
                             hInstance,
                             NULL);
    
        ShowWindow(hwnd, SW_SHOWNORMAL);
        UpdateWindow(hwnd);
        
        while(GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    
        switch(message)
        {
       
        case WM_CREATE:
            feld[3][4].type = BOMB;
            feld[7][2].type = BOMB;
            feld[6][3].type = BOMB;
            feld[1][1].type = BOMB;
            feld[1][0].type = BOMB;
            feld[0][2].type = BOMB;
            feld[4][6].type = BOMB;
            feld[5][5].type = BOMB;
            feld[3][3].type = BOMB;
            feld[2][6].type = BOMB;
            feld[1][9].type = BOMB;
            feld[7][9].type = BOMB;
            feld[3][7].type = BOMB;
            feld[2][8].type = BOMB;
            feld[7][0].type = BOMB;
            feld[7][1].type = BOMB;
            feld[5][4].type = BOMB;
    
            for(int x=0; x<250; x+=25)
            {
                for(int y=0; y<250; y += 25)
                {
                    
                    CreateWindow("BUTTON",
                                 "",
                                 WS_CHILD | WS_VISIBLE | BS_BITMAP,
                                 x, 30 + y, 25, 25,
                                 hwnd,
                                 HMENU(z),
                                 hbinstance,
                                 NULL);
                    z++;
                }
            }
                            
            return 0;
    
        case WM_COMMAND:
            pushed = LOWORD(wParam);
            if ((pushed >= 0) and (pushed <= 99))
            {
    
                einer = (pushed / 10);
                zehner = pushed % 10;
    
                if (feld[einer][zehner].status == false)
                {
                    feld[einer][zehner].status = true;
                }
            }
            update_buttons(einer, zehner);
            return 0;
            
    
        case WM_LBUTTONDOWN:
            return 0;
    
        case WM_DESTROY:
            PostQuitMessage(0);    
            return 0;
        }
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    
    void update_buttons(int pos_x, int pos_y)
    {
    
        if (feld[pos_x][pos_y].type != BOMB)
        {
            feld[pos_x][pos_y].seek_status = 's';
    
    
            for(int x=0; x<10; x++)
            {
                for(int y=0; y<10; y++)
                {
                    if (feld[x][y].type == BOMB)
                    {
                        if (((feld[x+1][y].type != EMPTY) or (feld[x+1][y].status == true)) or (x+1 > 9))
                        {
                            if (((feld[x-1][y].type != EMPTY) or (feld[x-1][y].status == true)) or (x-1 < 0))
                            {
                                if (((feld[x][y+1].type != EMPTY) or (feld[x][y+1].status == true)) or (y+1 > 9))
                                {
                                    if (((feld[x][y-1].type != EMPTY) or (feld[x][y-1].status == true)) or (y-1 < 0))
                                    {
                                        feld[x][y].type = SAVED_BOMB;
                                    }
                                }
                            }
                        }
                    }
    
                    if (feld[x][y].seek_status == 's')
                    {
                        feld[x][y].seek_status = 'd';
                        feld[x][y].status = true;
                        seek_position(x, y);
                        x = -1;
                        y = -1;
                    }
                }
            }
         }
         else
         {
            feld[pos_x][pos_y].type = EXPLODED_BOMB;
    
            for(int x=0; x<10; x++)
            {
                for(int y=0; y<10; y++)
                {
                    if (feld[x][y].type == BOMB)
                    {
                        feld[x][y].type = EXPLODED_BOMB;
                        hwndchild = GetDlgItem(hwnd, (10 * x) + y);
                        EnableWindow(hwndchild, true);
                    }
                }
            }
         }
    
    
        for(int x=0; x<10; x++)
        {
            for(int y=0; y<10; y++)
            {
                if ((feld[x][y].type == EMPTY) and (feld[x][y].status == true))
                {
                    hwndchild = GetDlgItem(hwnd, (10 * x) + y);
                    SendMessage(hwndchild, BM_SETSTATE, TRUE, NULL);
                }
                else if (feld[x][y].type == SAVED_BOMB)
                {
                    hwndchild = GetDlgItem(hwnd, (10 * x) + y);
    //                SetWindowText(hwndchild, "B");
                    SendMessage(hwndchild, BM_SETIMAGE, IMAGE_BITMAP, (long)h_saved);
                }
                else if (feld[x][y].type == EXPLODED_BOMB)
                {
                    hwndchild = GetDlgItem(hwnd, (10 * x) + y);
    //                SetWindowText(hwndchild, "X");
                    SendMessage(hwndchild, BM_SETIMAGE, IMAGE_BITMAP, (long)h_exploded);
                }            
            }
        }
    }
    
    
        void seek_position(int pos_x, int pos_y)
        {
    
            for(int x=-1; x<=1; x+=2)
            {
                if ((pos_x + x <= 9) and (pos_x + x >= 0))
                {
                    if ((feld[pos_x + x][pos_y].type == BOMB) and (feld[pos_x + x][pos_y].seek_status != 'd'))
                    {
                        feld[pos_x + x][pos_y].seek_status = 'b';
                    }
                    else if ((feld[pos_x + x][pos_y].type == EMPTY) and (feld[pos_x + x][pos_y].seek_status != 'd'))
                    {
                        feld[pos_x + x][pos_y].seek_status = 's';
                    }
                }
            }
               
            for(int y=-1; y<=1; y+=2)
            {
                if ((pos_y + y <= 9) and (pos_y + y >= 0))
                {
                    if ((feld[pos_x][pos_y + y].type == BOMB) and (feld[pos_x][pos_y + y].seek_status != 'd'))
                    {
                        feld[pos_x][pos_y + y].seek_status = 'b';
                    }
                    else if ((feld[pos_x][pos_y + y].type == EMPTY) and (feld[pos_x][pos_y + y].seek_status != 'd'))
                    {
                        feld[pos_x][pos_y + y].seek_status = 's';
                    }
                }
            }
        }
    Dabei fasse ich die Minen in ein Array der Dimension [9][9] (also 0 - 9 * 0 - 9) und dieses Array ist des Typs Structur. Dabei habe ich in der Structur einmal ein Feld des Typs bool namens Status welches speichert ob das Feld bereits aufgedeckt ist oder noch nicht. Dann ein Short namens type welches speichert was sich unter dem Feld befindet (Bombe oder nichts) und ein char namens Seek-Status welcher für die Abfrage der benachbarten freigelegten Kästchen benötigt wird (sicherlich nicht zwangsweise aber ich hab mir da so einen algorithmus erdacht mitdem ich das benötige).
    Des weiteren habe ich dann (logischer Weise ) ein Fenster sowie 10 x 10 Child-Fenster welche auf Knopfdruck die WM_COMMAND message senden. (Per ID kann man dann das jeweilige Fenster ausfindig machen und die mine sprengen oder das unvermiente Feld aufdecken + benachbarte Felder - wie in Minesweeper eben).

    Eine Spielsteuerung, also Menüs, Toolbars und Co. und sowas gibts noch nicht. Die GUI (wenn man das bisschen Grafik so nennen kann^^) ist per Hand mit der WinAPI zusammengeschraubt, ohne Visuellen Designer und ohne jegliche Toolkits und GUI-Builder wie VB einen bietet.
    Vielleicht hilft dir ja der Code oben weiter wenn du dich etwas mit C++ auskennst. Dann sollte das eigentlich kein Problem sein denn ich bin selbst noch Anfänger in C++.

    Mehrere Ebenen ist imo nicht nötig wenn man Structures verwendet. Dann hat man eine Int oder Short-Variable welche speicher was sich an der Stelle XY befindet (etwa bei 3, 5) und fertig. Dafür braucht man keine mehrfachen Ebenen oder sowas... Und wenn sich keine Mine dort befindet und das Feld bereits aufgedeckt ist, kannst du dort ja den Wert der dort zu findenen Minen eintragen. (etwa eine 3 wenn sich soviele Minen dort befinden). Es sollte sich alles mit wenigen Variablen in der Structur machen lassen und auch bequem managen lassen.

    //EDIT:
    Zitat Zitat
    Das mit den Zahlen und Mienen wuerde ich vielleicht so machen, dass das eine Graphik ist, die unter den Buttons liegt, und dass beim klick der Button unsichtbar und unklickbar gemacht wird ...
    Da könnte man doch einfach Childwindows erstellen und diese leer lassen (ohne Text und ohne Bild). Wenn man dann drauf klickt ändert sich das Bild des Buttons, entweder zu einer Mine oder zu einer Zahl welche angibt, wie viele Minen sich im Umfeld befinden. Das kann man aber alles selbst auf den Button schreiben. (In meinem Spielchen oben hab ich die Button beim einmaligen Blicken eine EInrastfunktion verpasst sodass sie eingedrückt bleiben. Das sieht dann ähnlich dem Minesweeper von Microsoft aus. Man kann die Buttons zwar auch verschwinden lassen aber dann muss man auf die Fläche unter den Buttons malen was imo umständlicher ist als die Grafik der Buttons zu ändern).

    Anmerkung: Wenn ich von Child-Windows spreche meine ich die Buttons im Spiel unter denen sich Minen verstecken könnten. Da sie ja unter Windows nix anderes als Fenster sind, nenne ich sie manchmal Buttons und manchmal Fenster, also nicht in Verwirrung geraten.


    EDIT: Im Übrigen habe ich in meinem vorliegenden Programmchen noch keine Zufallsroutine für die Minenplatzierung drinne. Deshalb liegen die immer gleich und werden beim Initialisieren des Fensters (bei der WM_CREATE Message) einfach den Buttons zugewisen. Sollte aber kein Problem darstellen, sowas einzubauen. Ich hab hier aufgehört und mit was Neuem angefangen, war alles nur ne Übungsaufgabe von mir.


    mfg.

    Sunny

    Geändert von Ynnus (11.01.2005 um 16:05 Uhr)

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •