📄 minesweep.c
字号:
/* * Copyright (c) 2003 Century Software, Inc. All Rights Reserved. * * This file is part of the PIXIL Operating Environment * * The use, copying and distribution of this file is governed by one * of two licenses, the PIXIL Commercial License, or the GNU General * Public License, version 2. * * Licensees holding a valid PIXIL Commercial License may use this file * in accordance with the PIXIL Commercial License Agreement provided * with the Software. Others are governed under the terms of the GNU * General Public License version 2. * * This file may be distributed and/or modified under the terms of the * GNU General Public License version 2 as published by the Free * Software Foundation and appearing in the file LICENSE.GPL included * in the packaging of this file. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. * * RESTRICTED RIGHTS LEGEND * * Use, duplication, or disclosure by the government is subject to * restriction as set forth in paragraph (b)(3)(b) of the Rights in * Technical Data and Computer Software clause in DAR 7-104.9(a). * * See http://www.pixil.org/gpl/ for GPL licensing * information. * * See http://www.pixil.org/license.html or * email cetsales@centurysoftware.com for information about the PIXIL * Commercial License Agreement, or if any conditions of this licensing * are not clear to you. */#include <pixil_config.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <getopt.h>#include <nano-X.h>#include <nxcolors.h>#include <unistd.h>#ifdef CONFIG_PAR#include <par/par.h>#endif#include "minesweep.h"#define WM_PROPS (GR_WM_PROPS_MAXIMIZE | GR_WM_PROPS_BORDER |\ GR_WM_PROPS_CAPTION |\ GR_WM_PROPS_CLOSEBOX)/* The actual playing field */static unsigned char minefield[14][14];/* Various pixmaps and windows */static GR_WINDOW_ID main_wid, minefield_wid, button_wid, scores_wid;static GR_WINDOW_ID minefield_pixmap = 0, tileset_pixmap = 0;/* Global variables */static GR_FONT_ID g_font;static int g_width, g_height, g_bombs;/* The game info structure */struct{ unsigned char state; unsigned char flags_set; unsigned char tiles_cleared; int start_time; int timer;}game_info;/* The number colors will alternate between these three colors */static GR_COLOR text_colors[3] = { GR_COLOR_BLUE, GR_COLOR_GREEN, GR_COLOR_RED };#define KEY_UP 0x01static unsigned short g_keyflags = 0;typedef struct{ unsigned long date; int seconds;}score_t;static score_t g_scores[10];struct{ char str[25]; GR_WINDOW_ID wid;}menus[] ={ { "Scores", 0} , /* { "Difficulty", 0 }, */ { "", 0}};/* Advance declarations */void start_game(void);void clear_tile(int x, int y);void draw_button(int state);/* Read the top 10 high scores from the file */voidload_scores(char *filename, score_t * scores){ int i = 0; FILE *stream = fopen(filename, "r"); if (!stream) return; for (i = 0; i < 10; i++) fscanf(stream, "%ld %d\n", &scores[i].date, &scores[i].seconds); fclose(stream);}voidsave_scores(char *filename, score_t * scores){ int i = 0; FILE *stream = fopen(filename, "w+"); if (!stream) return; for (i = 0; i < 10; i++) fprintf(stream, "%ld %d\n", scores[i].date, scores[i].seconds); fclose(stream);}voiddraw_scores(void){ int ypos = 25; int i = 0; GR_GC_ID gc = GrNewGC(); GrSetGCFont(gc, g_font); GrSetGCForeground(gc, GR_COLOR_BLACK); GrSetGCBackground(gc, GR_COLOR_WHITE); GrText(scores_wid, gc, 5, 5, "Minesweeper High Scores", -1, GR_TFTOP); for (i = 0; i < 10; i++, ypos += 15) { char str[50]; char *ptr = str; if (i < 9) ptr += sprintf(ptr, " %d. ", i + 1); else ptr += sprintf(ptr, "%d. ", i + 1); GrText(scores_wid, gc, 10, ypos, str, -1, GR_TFTOP); ptr = str; if (g_scores[i].seconds) { struct tm *tm = localtime(&g_scores[i].date); ptr += sprintf(ptr, "%2.2d/%2.2d/%2.2d %2.2d:%2.2d", tm->tm_mon + 1, tm->tm_mday, (tm->tm_year + 1900) % 1000, tm->tm_hour, tm->tm_min); ptr += sprintf(ptr, " %2.2d:%2.2d", g_scores[i].seconds / 60, g_scores[i].seconds % 60); } else ptr += sprintf(ptr, "---------- --:--"); GrText(scores_wid, gc, 30, ypos, str, -1, GR_TFTOP); } ypos += 15; GrText(scores_wid, gc, 5, ypos, "Click the window to close...", -1, GR_TFTOP); GrDestroyGC(gc);}voidshow_scores(void){ if (!scores_wid) { scores_wid = GrNewWindowEx(GR_WM_PROPS_NODECORATE, "Scores", main_wid, 0, 0, 240, 300, GR_COLOR_WHITE); GrSelectEvents(scores_wid, GR_EVENT_MASK_EXPOSURE | GR_EVENT_MASK_BUTTON_DOWN); } GrMapWindow(scores_wid);}voidload_tileset(char *filename){ GR_GC_ID gc = GrNewGC(); char path[256];#ifdef CONFIG_PAR db_handle *par_db = db_openDB(db_getDefaultDB(), PAR_DB_MODE_RDONLY); if (par_db) { par_getScreentopDir(par_db, "icondir", path, sizeof(path) - 1); db_closeDB(par_db); strcat(path, "/"); strcat(path, filename); } else#endif { getcwd(path, sizeof(path)); strcat(path, "/"); strcat(path, filename); } /* Create the pixmap if needed */ if (!tileset_pixmap) tileset_pixmap = GrNewPixmap(TILE_WIDTH * 6, TILE_HEIGHT + BUTTON_HEIGHT, 0); /* Load the image directly from the file */ printf("Trying to draw the image from %s\n", path); GrDrawImageFromFile(tileset_pixmap, gc, 0, 0, -1, -1, path, 0); GrDestroyGC(gc);}voidinit_field(void){ int i, x, y; int field_size = g_height * g_width; /* Reset each tile to be bomb free and regular */ for (y = 0; y < g_height; y++) for (x = 0; x < g_width; x++) { minefield[y][x] = 0; SET_TILE(minefield[y][x], TILE_REGULAR); } /* Add the given number of bombs to the field */ for (i = 0; i < g_bombs; i++) { int pos; do pos = rand() % field_size; while ((minefield[pos / g_height][pos % g_width]) & BOMB_FLAG); minefield[pos / g_height][pos % g_width] |= BOMB_FLAG; }}voiddraw_menus(void){ int mx = 5; int i = 0; GR_GC_ID gc = GrNewGC(); GrSetGCForeground(gc, GR_COLOR_BLACK); GrSetGCBackground(gc, GR_COLOR_WHITE); GrSetGCFont(gc, g_font); while (strlen(menus[i].str)) { int tw, th, tb; GrGetGCTextSize(gc, menus[i].str, -1, GR_TFTOP, &tw, &th, &tb); GrText(main_wid, gc, mx, 5, menus[i].str, -1, GR_TFTOP); GrLine(main_wid, gc, mx, 6 + tb, mx + tw, 6 + tb); if (!menus[i].wid) { menus[i].wid = GrNewInputWindow(main_wid, mx, 5, tw, th); GrSelectEvents(menus[i].wid, GR_EVENT_MASK_BUTTON_DOWN); GrMapWindow(menus[i].wid); } mx += (tw + 10); i++; }}/* Draw the main window */voiddraw_main(void){ char flagstr[32]; char timestr[32]; int w = (240 - TILE_WIDTH * g_width) / 2; int h = ((300 - TILE_HEIGHT * g_height) / 2) + (TILE_HEIGHT * g_height) + 5; int tw, th, tb; GR_GC_ID gc = GrNewGC(); GrSetGCForeground(gc, GR_COLOR_BLACK); GrSetGCBackground(gc, GR_COLOR_WHITE); GrSetGCFont(gc, g_font); sprintf(flagstr, "Flags: %2.2d/%2.2d", game_info.flags_set, g_bombs); GrText(main_wid, gc, w, h, flagstr, -1, GR_TFTOP); sprintf(timestr, "Time: %2.2d:%2.2d", game_info.timer / 60, game_info.timer % 60); GrGetGCTextSize(gc, timestr, -1, GR_TFTOP, &tw, &th, &tb); GrText(main_wid, gc, w + (TILE_WIDTH * g_width) - tw, h, timestr, -1, GR_TFTOP); GrDestroyGC(gc); draw_menus();}voiddraw_tile(int tile, int x, int y){ GR_GC_ID gc = GrNewGC(); GrCopyArea(minefield_pixmap, gc, (x * TILE_WIDTH), (y * TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT, tileset_pixmap, (tile - 1) * TILE_WIDTH, 0, MWROP_SRCCOPY); GrDestroyGC(gc);}intcheck_neighbors(int x, int y){ int count = 0; if (x > 0) { if (minefield[y][x - 1] & BOMB_FLAG) count++; if (y > 0) if (minefield[y - 1][x - 1] & BOMB_FLAG) count++; if (y < (g_height) - 1) if (minefield[y + 1][x - 1] & BOMB_FLAG) count++; } if (x < (g_width) - 1) { if (minefield[y][x + 1] & BOMB_FLAG) count++; if (y > 0) if (minefield[y - 1][x + 1] & BOMB_FLAG) count++; if (y < (g_height) - 1) if (minefield[y + 1][x + 1] & BOMB_FLAG) count++; } if (y > 0) if (minefield[y - 1][x] & BOMB_FLAG) count++; if (y < (g_height) - 1) if (minefield[y + 1][x] & BOMB_FLAG) count++; return (count);}voidclear_neighbors(int x, int y){ if (x > 0) { clear_tile(x - 1, y); if (y > 0) clear_tile(x - 1, y - 1); if (y < g_height - 1) clear_tile(x - 1, y + 1); } if (x < g_width - 1) { clear_tile(x + 1, y); if (y > 0) clear_tile(x + 1, y - 1); if (y < g_height - 1) clear_tile(x + 1, y + 1); } if (y > 0) clear_tile(x, y - 1); if (y < g_height - 1) clear_tile(x, y + 1);}voiddraw_empty(int x, int y){ int count; GR_GC_ID gc = GrNewGC(); GrSetGCForeground(gc, GR_RGB(0xC5, 0xC2, 0xC5)); draw_tile(TILE_DEPRESSED, x, y); /* GrFillRect(minefield_pixmap, gc, (x * TILE_WIDTH), (y * TILE_HEIGHT), TILE_WIDTH, TILE_HEIGHT); */ count = check_neighbors(x, y); /* If there are bombs around us, then print how many there are */ if (count) { char ch; int w, h, b; GrSetGCForeground(gc, text_colors[count % 3]); GrSetGCUseBackground(gc, 0); GrSetGCFont(gc, g_font); ch = 48 + count; GrGetGCTextSize(gc, &ch, 1, GR_TFTOP, &w, &h, &b); GrText(minefield_pixmap, gc, (x * TILE_WIDTH) + ((TILE_WIDTH - w) / 2), (y * TILE_HEIGHT) + ((TILE_HEIGHT - h) / 2), &ch, 1, GR_TFTOP); } GrDestroyGC(gc);}voiddraw_field(void){ int x, y; GR_GC_ID gc = GrNewGC(); for (y = 0; y < g_height; y++) { for (x = 0; x < g_width; x++) { switch (GET_TILE(minefield[y][x])) { case TILE_REGULAR: case TILE_BOMB: case TILE_FLAG:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -