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 + -
显示快捷键?