minesweeper.c

来自「开发linux应用-用gtk+和gdk开发linux图形用户界面应用--的实例」· C语言 代码 · 共 849 行 · 第 1/2 页

C
849
字号
    /* --- Make this the current image --- */    gtk_container_add (GTK_CONTAINER (button_start), widget);}/* * start_button_clicked * * Event handler for the clicking of the start  * button */void start_button_clicked (GtkWidget *widget, gpointer *data){    SetStartButtonIcon ((gchar **) xpm_smile);    ResetGame (nCols, nRows, nTotalBombs, FALSE);}/* * mine_button_clicked * * Event handler for one of the mine buttons being * clicked. * * widget - button pressed. * data - button label. */void mine_button_clicked (GtkWidget *widget, gpointer *data){    typMinesweeperButton *mine;    GtkWidget *label;    mine = (typMinesweeperButton *) data;    //printf ("button clicked - game over = %d\n", bGameOver);    /* --- If the game is over --- */    if (bGameOver) {        /* --- Let the button as it was. --- */        gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (widget),                            (mine->buttonState == BUTTON_DOWN));        return;    }    /* --- If game is being reset --- */    if (bResetGame) return;    /* --- Start the time ... now --- */    StartTimer ();    /* --- If they clicked on a mine button... --- */    if (mine->bHasBomb) {        /* --- Game over, dude! --- */        bGameOver = TRUE;        /* --- Smiley face is frowning. --- */        SetStartButtonIcon ((gchar **) xpm_frown);        /* --- Display all unseen bombs. --- */        StopTimer ();        ShowBombs (mine);    } else {        /* --- Create a label for the cell and put the  --- */        /* --- number of nearby bombs in it. --- */        DisplayHiddenInfo (mine);        CheckForWin ();    }}/* * button_press * * The button press could be a right mouse button * which needs to be handled by rotating the  * image in the button. */void button_press (GtkWidget *widget, GdkEventButton *event, gpointer *data){    typMinesweeperButton *mine;    GtkWidget *pixmapWidget;    /* --- Ignore if game is already over with --- */    if (bGameOver) {        return;    }    /* --- Which mine was clicked? --- */    mine = (typMinesweeperButton *) data;    /* --- Make sure it's a button event --- */    if (event->type == GDK_BUTTON_PRESS) {         /* --- Was it the right mouse button? --- */        if (event->button == 3) {            switch (mine->buttonState) {                case BUTTON_UNKNOWN:                    /* --- Free button children --- */                    FreeChild (widget);                    mine->buttonState = BUTTON_FLAGGED;                    AddImageToMine (mine, xpm_flag);                    nBombsLeft --;                    break;                case BUTTON_FLAGGED:                    /* --- Free button children --- */                    FreeChild (widget);                    /* --- Free button children --- */                    mine->buttonState = BUTTON_UNKNOWN;                    nBombsLeft ++;                    break;            }            DisplayBombCount ();            CheckForWin ();        }    }}/* * CreateButton * * Create a button, assign event handlers, and attach the button to the * table in the proper place. */GtkWidget *CreateButton (GtkWidget *table,                          typMinesweeperButton *mine,                          int row,                          int column){    GtkWidget *button;    /* --- Create the button --- */    button = gtk_toggle_button_new ();    /* --- Init the button fields --- */    mine->buttonState = BUTTON_UNKNOWN;    mine->nRow = row;    mine->nCol = column;    /* --- We care if the button is clicked --- */    gtk_signal_connect (GTK_OBJECT (button), "clicked",                        GTK_SIGNAL_FUNC (mine_button_clicked), mine);    /* --- We care about other mouse events. --- */    gtk_signal_connect (GTK_OBJECT (button), "button_press_event",                        GTK_SIGNAL_FUNC (button_press), mine);    /* --- Put the button in the table in the right place. --- */    gtk_table_attach (GTK_TABLE (table), button,                       column, column+1,                       row + 1, row + 2,                       GTK_FILL | GTK_EXPAND,                       GTK_FILL | GTK_EXPAND,                       0, 0);    /* --- Set the button to a uniform size --- */    gtk_widget_set_usize (button, BUTTON_WIDTH, BUTTON_HEIGHT);    /* --- Make the button visible --- */    gtk_widget_show (button);    /* --- return the button. --- */    return (button);}/*  * CountNearbyBombs * * Count the number of bombs this square is next to. */int CountNearbyBombs (int col, int row){    int i, j;    int nCount = 0;    /* --- Every square that would be at most 1 square away --- */    for (i = MAX (col-1, 0); i <= MIN (col+1, nCols-1); i++) {        for (j = MAX (row-1, 0); j <= MIN (row+1, nRows-1); j++) {            /* --- If it's got a bomb --- */            if (mines[i][j].bHasBomb) {               /* --- Keep track of the count. --- */               nCount++;            }        }    }    return (nCount);}/* * CreateMinesweeperButtons *  * Create the buttons on the minesweeper from the table we defined at the * beginning of this program.  The button pointers (handles) are stored * back in the table so they can be referenced later. */void CreateMinesweeperButtons (GtkWidget *table,                                int nGridColumns,                                int nGridRows,                               int bNewButtons){    int ci;    int ri;    GtkWidget *button;    int nBombs;    typMinesweeperButton *mine;     /* --- Update the global variables --- */    nCols = nGridColumns;    nRows = nGridRows;    bGameOver = FALSE;    bResetGame = TRUE;    /* --- Update bomb count. --- */    DisplayBombCount ();    /* --- Check each button --- */    for (ci = 0; ci < nCols; ci++) {        for (ri = 0; ri < nRows; ri++) {            /* --- The button has nothing at all. --- */            mine = &mines[ci][ri];            mine->bHasBomb = 0;            mine->buttonState = BUTTON_UNKNOWN;            /* --- Widget assoc to the mine? --- */            if (bNewButtons) {                /* --- Create a button --- */                mine->widget = CreateButton (table, mine, ri, ci);            } else {                /* --- Reuse button --- */                /* --- Free any existing xpm/label --- */                FreeChild (mine->widget);                /* --- Put button up. --- */                gtk_toggle_button_set_state (                           GTK_TOGGLE_BUTTON (mine->widget),                            FALSE);            }        }    }    /* --- Place the bombs. --- */    nBombs = nTotalBombs;    /* --- While we have bombs to deliver --- */    while (nBombs > 0) {        /* --- Calculate a row/col position --- */        ci = rand () % nCols;        ri = rand () % nRows;        /* --- If no bomb exists, create one! --- */        if (mines[ci][ri].bHasBomb == 0) {            mines[ci][ri].bHasBomb = 1;            nBombs--;        }    }    /* --- Once all bombs have been distributed, calculate      *     how many bombs are adjacent to each button.     */    /* --- Check every button --- */    for (ci = 0; ci < nCols; ci++) {        for (ri = 0; ri < nRows; ri++) {            mine = &mines[ci][ri];                       /* --- How many buttons? --- */            mine->nBombsNearby = CountNearbyBombs (ci, ri);        }    }    bResetGame = FALSE;}/* * SetGrid * * Sets the game grid to the size specified with the * number of bombs. */void SetGrid (int nGridColumns, int nGridRows, int nBombs){    int row, col;    /* --- If the packing table exists. --- */    if (table) {        /* --- Destroy it and all the buttons. --- */        gtk_widget_destroy (table);    }     /* --- Create a table for the buttons --- */    table = gtk_table_new (nGridColumns, nGridRows, FALSE);     /* --- Add it to the vbox --- */    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);    /* --- Show the table. --- */    gtk_widget_realize (table);    /* --- Do a game reset with the numbers --- */    ResetGame (nGridColumns, nGridRows, nBombs, TRUE);    /* --- Show the table. --- */    gtk_widget_show (table);}/* * main * * Program begins here */int main (int argc, char *argv[]){    GtkWidget *window;    GdkBitmap *mask;    GtkStyle  *style;    GtkWidget *widget_smile;              GtkWidget *hbox;              /* --- GTK initialization --- */    gtk_init (&argc, &argv);    /* --- Create the top window --- */    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);    /* --- Don't allow window to be resized.  --- */    gtk_window_set_policy (GTK_WINDOW (window), FALSE, FALSE, TRUE);    /* --- Give the window a title. --- */    gtk_window_set_title (GTK_WINDOW (window), "Minesweeper");    /* --- You should always remember to connect the destroy event      *     to the main window.     */    gtk_signal_connect (GTK_OBJECT (window), "delete_event",                        GTK_SIGNAL_FUNC (delete_event), NULL);        vbox = gtk_vbox_new (FALSE, 1);    gtk_widget_show (vbox);    /* --- Create the application menu --- */    CreateMenu (window, vbox);    /* --- Horizontal box for score/start button --- */    hbox = gtk_hbox_new (TRUE, 1);    gtk_widget_show (hbox);    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);    /*     * --- Bombs left on the page is a label      */     /* --- Add label with # of bombs left. --- */    label_bombs = gtk_label_new ("");    gtk_box_pack_start (GTK_BOX (hbox), label_bombs, FALSE, FALSE, 0);    gtk_widget_show (label_bombs);    /*     * --- Create the start button with smilely face on it      */    button_start = gtk_button_new ();    /* --- We care if the button is clicked --- */    gtk_signal_connect (GTK_OBJECT (button_start),                         "clicked",                        GTK_SIGNAL_FUNC (start_button_clicked),                         NULL);    gtk_box_pack_start (GTK_BOX (hbox), button_start, FALSE, FALSE, 0);    gtk_widget_show (button_start);    /*     * --- Time on the right      */     /* --- Add label with # of bombs left. --- */    label_time = gtk_label_new ("");    gtk_box_pack_start (GTK_BOX (hbox), label_time, FALSE, FALSE, 0);    gtk_widget_show (label_time);    /* --- Make them visible --- */    gtk_widget_show (vbox);    /* --- Add application vbox to main window --- */    gtk_container_add (GTK_CONTAINER (window), vbox);    gtk_widget_show (window);    /* --- Create the *smile* and put it on the start button --- */    SetStartButtonIcon ((gchar **) xpm_smile);    /* --- Create 10x10 grid. --- */    SetGrid (10, 10, 10);    /* --- Start gtk event processing --- */     gtk_main ();    exit (0);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?