📄 minesweep.c
字号:
case TILE_WRONG: draw_tile(GET_TILE(minefield[y][x]), x, y); break; case TILE_EMPTY: draw_empty(x, y); break; } } } GrCopyArea(minefield_wid, gc, 0, 0, TILE_WIDTH * g_width, TILE_HEIGHT * g_height, minefield_pixmap, 0, 0, MWROP_SRCCOPY); GrDestroyGC(gc);}voidset_bomb(int x, int y){ CLEAR_TILE(minefield[y][x]); SET_TILE(minefield[y][x], TILE_BOMB);}voidset_wrong(int x, int y){ CLEAR_TILE(minefield[y][x]); SET_TILE(minefield[y][x], TILE_WRONG);}voidset_empty(int x, int y){ CLEAR_TILE(minefield[y][x]); SET_TILE(minefield[y][x], TILE_EMPTY); game_info.tiles_cleared++;}voidclear_tile(int x, int y){ /* Only proceed if this tile has been unchecked */ if (GET_TILE(minefield[y][x]) == TILE_EMPTY || GET_TILE(minefield[y][x]) == TILE_FLAG) return; /* If this tile is hiding a bomb, then return */ if (minefield[y][x] & BOMB_FLAG) return; set_empty(x, y); if (check_neighbors(x, y) != 0) return; /* Otherwise, see if we can't clear our any of our neighbors too */ clear_neighbors(x, y);}intis_bomb(int x, int y){ if (minefield[y][x] & BOMB_FLAG) if (GET_TILE(minefield[y][x]) != TILE_FLAG) return (1); return (0);}/* Immediately set the user up as teh winner */voidhandle_cheat(void){ int r, s; game_info.tiles_cleared = 0; game_info.flags_set = 0; for (r = 0; r < g_height; r++) for (s = 0; s < g_width; s++) { if (minefield[r][s] & BOMB_FLAG) { CLEAR_TILE(minefield[r][s]); SET_TILE(minefield[r][s], TILE_FLAG); game_info.flags_set++; } else { CLEAR_TILE(minefield[r][s]); SET_TILE(minefield[r][s], TILE_EMPTY); game_info.tiles_cleared++; } } draw_field();}voidhandle_minefield_down(GR_EVENT_BUTTON * button){ int x = button->x / TILE_WIDTH; int y = button->y / TILE_HEIGHT; if (game_info.state == GAME_OVER) return; /* On the X86 demo, we use a right button press here, otherwise, on the PDAs, we use the key */#ifdef CONFIG_PLATFORM_X86DEMO if (button->buttons & MWBUTTON_R) #else if ((g_keyflags & KEY_UP) == KEY_UP) #endif { switch (GET_TILE(minefield[y][x])) { case TILE_REGULAR: if (game_info.flags_set == g_bombs) return; CLEAR_TILE(minefield[y][x]); SET_TILE(minefield[y][x], TILE_FLAG); game_info.flags_set++; break; case TILE_FLAG: CLEAR_TILE(minefield[y][x]); SET_TILE(minefield[y][x], TILE_REGULAR); game_info.flags_set--; break; default: break; } } else { if (GET_TILE(minefield[y][x]) == TILE_EMPTY) { int bcount = 0; if (x > 0) { bcount += is_bomb(x - 1, y); if (y > 0) bcount += is_bomb(x - 1, y - 1); if (y < g_height - 1) bcount += is_bomb(x - 1, y + 1); } if (x < g_width - 1) { bcount += is_bomb(x + 1, y); if (y > 0) bcount += is_bomb(x + 1, y - 1); if (y < g_height - 1) bcount += is_bomb(x + 1, y + 1); } if (y > 0) bcount += is_bomb(x, y - 1); if (y < g_height - 1) bcount += is_bomb(x, y + 1); if (!bcount) clear_neighbors(x, y); } else { if (GET_TILE(minefield[y][x]) == TILE_FLAG) goto dofield; if (minefield[y][x] & BOMB_FLAG) { int r, s; game_info.state = GAME_OVER; for (r = 0; r < g_height; r++) for (s = 0; s < g_width; s++) { if (minefield[r][s] & BOMB_FLAG) { if (GET_TILE(minefield[r][s]) != TILE_FLAG) set_bomb(s, r); } else { if (GET_TILE(minefield[r][s]) == TILE_FLAG) set_wrong(s, r); } } draw_button(BUTTON_WRONG); } else clear_tile(x, y); } } dofield: /* Start the timer if the game is active */ if (game_info.state == GAME_START) { game_info.state = GAME_ACTIVE; game_info.start_time = time(0); } draw_field();}voiddraw_button(int state){ GR_GC_ID gc = GrNewGC(); GrCopyArea(button_wid, gc, 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, tileset_pixmap, (state * BUTTON_WIDTH), TILE_HEIGHT, MWROP_SRCCOPY); GrDestroyGC(gc);}voidhandle_button(GR_EVENT_BUTTON * button, int state){ draw_button(state); if (state == 1) { start_game(); draw_field(); }}voidstart_game(void){ time_t val = time(0); /* Reseed the randomizer */ srand(val); /* Initalize the mine field */ init_field(); /* Set some variables */ game_info.flags_set = 0; game_info.tiles_cleared = 0; game_info.timer = 0; game_info.start_time = 0; game_info.state = GAME_START;}intmain(int argc, char **argv){ int w, h; /* The default game width and height */ g_width = g_height = 10; g_bombs = 0; while (1) { signed char ch = getopt(argc, argv, "w:h:b:"); if (ch == -1) break; switch (ch) { case 'w': g_width = atoi(optarg); if (g_width > 14) g_width = 14; if (g_width < 7) g_width = 7; break; case 'h': g_height = atoi(optarg); if (g_height > 14) g_height = 14; if (g_height < 7) g_height = 7; break; case 'b': g_bombs = atoi(optarg); break; } } /* Load the high scores from the list */ bzero(g_scores, sizeof(g_scores)); load_scores("/tmp/scores", g_scores); /* Set the number of bombs */ if (!g_bombs) g_bombs = ((g_width * g_height) / 5); else if (g_bombs < 5) g_bombs = 5; else if (g_bombs > ((g_width * g_height) - 1)) g_bombs = (g_width * g_height) - 1; if (GrOpen() == -1) { fprintf(stderr, "Error - Unable to open the graphics engine\n"); exit(-1); } g_font = GrCreateFont(GR_FONT_GUI_VAR, 0, 0); load_tileset("mine.xpm"); /* Initalize the field */ start_game(); /* Creat the main container window */ main_wid = GrNewWindowEx(WM_PROPS, "Minesweeper", GR_ROOT_WINDOW_ID, 0, 0, 240, 300, 0xFFFFFFFF); GrSelectEvents(main_wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_KEY_DOWN | GR_EVENT_MASK_KEY_UP | GR_EVENT_MASK_CLOSE_REQ); /* Make the minefield */ w = (240 - TILE_WIDTH * g_width) / 2; h = (300 - TILE_HEIGHT * g_height) / 2; minefield_wid = GrNewWindow(main_wid, w, h, TILE_WIDTH * g_width, TILE_HEIGHT * g_height, 0, GR_RGB(0xD5, 0xD6, 0xD5), 0); GrSelectEvents(minefield_wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_BUTTON_DOWN); minefield_pixmap = GrNewPixmap(TILE_WIDTH * g_width, TILE_HEIGHT * g_height, 0); /* Finally, create the button that we use for game control */ button_wid = GrNewWindow(main_wid, (240 - BUTTON_WIDTH) / 2, h - (5 + BUTTON_HEIGHT), BUTTON_WIDTH, BUTTON_HEIGHT, 0, 0, 0); GrSelectEvents(button_wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_BUTTON_DOWN | GR_EVENT_MASK_BUTTON_UP); GrMapWindow(main_wid); GrMapWindow(button_wid); GrMapWindow(minefield_wid); while (1) { GR_EVENT event; GrGetNextEventTimeout(&event, 1000L); switch (event.type) { case GR_EVENT_TYPE_EXPOSURE: if (event.exposure.wid == main_wid) draw_main(); else if (event.exposure.wid == minefield_wid) draw_field(); else if (event.exposure.wid == button_wid) draw_button(BUTTON_REGULAR); else if (event.exposure.wid == scores_wid) draw_scores(); // else //draw_dialog(); break; case GR_EVENT_TYPE_BUTTON_DOWN: if (event.button.wid == button_wid) handle_button(&event.button, BUTTON_WRONG); else if (event.button.wid == minefield_wid) handle_minefield_down(&event.button); else if (event.button.wid == scores_wid) GrUnmapWindow(scores_wid); else if (event.button.wid == menus[0].wid) show_scores(); // else // dialog_handle_keystroke(); break; case GR_EVENT_TYPE_BUTTON_UP: if (event.button.wid == button_wid) handle_button(&event.button, BUTTON_REGULAR); break; case GR_EVENT_TYPE_KEY_DOWN: { int togglekey = MWKEY_UP; /* Use the UP key to toggle the flag on the Ipaq */#ifdef CONFIG_PLATFORM_IPAQ togglekey = MWKEY_UP;#endif /* Use the accpet key to toggle the flag on the Zaurus */#ifdef CONFIG_PLATFORM_ZAURUS togglekey = ' ';#endif if (event.keystroke.wid == main_wid) { if (event.keystroke.ch == togglekey) g_keyflags |= KEY_UP; if (event.keystroke.ch == 'c') handle_cheat(); } } break; case GR_EVENT_TYPE_KEY_UP: { int togglekey = MWKEY_UP; /* Use the UP key to toggle the flag on the Ipaq */#ifdef CONFIG_PLATFORM_IPAQ togglekey = MWKEY_UP;#endif /* Use the accpet key to toggle the flag on the Zaurus */#ifdef CONFIG_PLATFORM_ZAURUS togglekey = ' ';#endif if (event.keystroke.ch == togglekey) g_keyflags &= ~(KEY_UP); } break; case GR_EVENT_TYPE_TIMEOUT: break; case GR_EVENT_TYPE_CLOSE_REQ: exit(0); } if (game_info.state == GAME_ACTIVE) { int i; int elapsed = time(0) - game_info.start_time; if (((g_width * g_height) - g_bombs) == game_info.tiles_cleared) { game_info.state = GAME_OVER; draw_button(BUTTON_WON); /* Check to see if we have a high score */ for (i = 0; i < 10; i++) { int t; if (!g_scores[i].seconds || g_scores[i].seconds > elapsed) { for (t = 9; t >= (i + 1); t--) { g_scores[t].seconds = g_scores[t - 1].seconds; g_scores[t].date = g_scores[t - 1].date; } break; } } if (i < 10) { g_scores[i].seconds = elapsed; g_scores[i].date = time(0); save_scores("/tmp/scores", g_scores); } //show_name_dialog(); } else game_info.timer = time(0) - game_info.start_time; } draw_main(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -