diff options
author | Antoine Cellerier <dionoea@videolan.org> | 2006-08-13 20:44:53 +0000 |
---|---|---|
committer | Antoine Cellerier <dionoea@videolan.org> | 2006-08-13 20:44:53 +0000 |
commit | e2a73dc3895d2f2457cf6397def93773f15050d9 (patch) | |
tree | f45be604d6e2777bb623fa28f95edb863488ffeb | |
parent | c9bb152a33fc293955b4b60170deb40c34857072 (diff) |
*: Enhance minesweeper graphics
minesweeper.c: clean source code (ipod keys still need to be changed)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10562 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/plugins/bitmaps/native/SOURCES | 12 | ||||
-rw-r--r-- | apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp | bin | 0 -> 2950 bytes | |||
-rw-r--r-- | apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp | bin | 0 -> 5670 bytes | |||
-rw-r--r-- | apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp | bin | 0 -> 10038 bytes | |||
-rw-r--r-- | apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp | bin | 0 -> 2550 bytes | |||
-rw-r--r-- | apps/plugins/minesweeper.c | 806 |
6 files changed, 384 insertions, 434 deletions
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES index 98c3eef443..10e61fb97b 100644 --- a/apps/plugins/bitmaps/native/SOURCES +++ b/apps/plugins/bitmaps/native/SOURCES @@ -280,4 +280,16 @@ rockpaint.bmp rockpaint_hsvrgb.bmp #endif +#if defined( HAVE_LCD_COLOR ) +#if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130 +minesweeper_tiles.16x16x24.bmp +#else +minesweeper_tiles.12x12x24.bmp +#endif +#elif LCD_DEPTH > 1 +minesweeper_tiles.12x12x2.bmp +#else +minesweeper_tiles.8x8x1.bmp +#endif + #endif /* HAVE_LCD_BITMAP */ diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp Binary files differnew file mode 100644 index 0000000000..fddd366782 --- /dev/null +++ b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp Binary files differnew file mode 100644 index 0000000000..28340760df --- /dev/null +++ b/apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp Binary files differnew file mode 100644 index 0000000000..4e1191fad0 --- /dev/null +++ b/apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp diff --git a/apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp b/apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp Binary files differnew file mode 100644 index 0000000000..610fbac1fb --- /dev/null +++ b/apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c index 21e655671f..317a969fb0 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -17,230 +17,155 @@ * ****************************************************************************/ -/***************************************************************************** -Mine Sweeper by dionoea -*****************************************************************************/ - #include "plugin.h" #ifdef HAVE_LCD_BITMAP PLUGIN_HEADER -/*what the minesweeper() function can return */ -#define MINESWEEPER_USB 3 -#define MINESWEEPER_QUIT 2 -#define MINESWEEPER_LOSE 1 -#define MINESWEEPER_WIN 0 +/* what the minesweeper() function can return */ +enum minesweeper_status { + MINESWEEPER_WIN, + MINESWEEPER_LOSE, + MINESWEEPER_QUIT, + MINESWEEPER_USB +}; /* variable button definitions */ #if CONFIG_KEYPAD == RECORDER_PAD -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_ON -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_TOGGLE2 BUTTON_F1 -#define MINESWP_DISCOVER BUTTON_ON -#define MINESWP_DISCOVER2 BUTTON_F2 -#define MINESWP_INFO BUTTON_F3 -#define MINESWP_RIGHT (BUTTON_F1 | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_F1 | BUTTON_LEFT) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_ON +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_TOGGLE2 BUTTON_F1 +# define MINESWP_DISCOVER BUTTON_ON +# define MINESWP_DISCOVER2 BUTTON_F2 +# define MINESWP_INFO BUTTON_F3 +# define MINESWP_RIGHT (BUTTON_F1 | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_F1 | BUTTON_LEFT) #elif CONFIG_KEYPAD == ONDIO_PAD -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_MENU -#define MINESWP_TOGGLE_PRE BUTTON_MENU -#define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL) -#define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT) -#define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF) -#define MINESWP_RIGHT (BUTTON_MENU | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_MENU | BUTTON_LEFT) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_MENU +# define MINESWP_TOGGLE_PRE BUTTON_MENU +# define MINESWP_TOGGLE (BUTTON_MENU | BUTTON_REL) +# define MINESWP_DISCOVER (BUTTON_MENU | BUTTON_REPEAT) +# define MINESWP_INFO (BUTTON_MENU | BUTTON_OFF) +# define MINESWP_RIGHT (BUTTON_MENU | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_MENU | BUTTON_LEFT) #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_OFF -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_ON -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO BUTTON_MODE -#define MINESWP_RIGHT (BUTTON_ON | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_ON | BUTTON_LEFT) - -#define MINESWP_RC_QUIT BUTTON_RC_STOP +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_OFF +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_ON +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO BUTTON_MODE +# define MINESWP_RIGHT (BUTTON_ON | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_ON | BUTTON_LEFT) + +# define MINESWP_RC_QUIT BUTTON_RC_STOP #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || \ (CONFIG_KEYPAD == IPOD_3G_PAD) -#define MINESWP_UP BUTTON_SCROLL_BACK -#define MINESWP_DOWN BUTTON_SCROLL_FWD -#define MINESWP_QUIT BUTTON_MENU -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_PLAY) -#define MINESWP_INFO (BUTTON_SELECT | BUTTON_MENU) -#define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) +# define MINESWP_UP BUTTON_SCROLL_BACK +# define MINESWP_DOWN BUTTON_SCROLL_FWD +# define MINESWP_QUIT BUTTON_MENU +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER (BUTTON_SELECT | BUTTON_PLAY) +# define MINESWP_INFO (BUTTON_SELECT | BUTTON_MENU) +# define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) #elif (CONFIG_KEYPAD == IAUDIO_X5_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_POWER -#define MINESWP_START BUTTON_REC -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO (BUTTON_REC | BUTTON_PLAY) -#define MINESWP_RIGHT (BUTTON_PLAY | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_PLAY | BUTTON_LEFT) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_POWER +# define MINESWP_START BUTTON_REC +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO (BUTTON_REC | BUTTON_PLAY) +# define MINESWP_RIGHT (BUTTON_PLAY | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_PLAY | BUTTON_LEFT) #elif (CONFIG_KEYPAD == GIGABEAT_PAD) -#define MINESWP_UP BUTTON_UP -#define MINESWP_DOWN BUTTON_DOWN -#define MINESWP_QUIT BUTTON_A -#define MINESWP_START BUTTON_SELECT -#define MINESWP_TOGGLE BUTTON_POWER -#define MINESWP_DISCOVER BUTTON_SELECT -#define MINESWP_INFO BUTTON_MENU -#define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) -#define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_A +# define MINESWP_START BUTTON_SELECT +# define MINESWP_TOGGLE BUTTON_POWER +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO BUTTON_MENU +# define MINESWP_RIGHT (BUTTON_SELECT | BUTTON_RIGHT) +# define MINESWP_LEFT (BUTTON_SELECT | BUTTON_LEFT) #elif (CONFIG_KEYPAD == IRIVER_H10_PAD) -#define MINESWP_UP BUTTON_SCROLL_UP -#define MINESWP_DOWN BUTTON_SCROLL_DOWN -#define MINESWP_QUIT BUTTON_POWER -#define MINESWP_START BUTTON_FF -#define MINESWP_TOGGLE BUTTON_PLAY -#define MINESWP_DISCOVER BUTTON_REW -#define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY) -#define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY) -#define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY) +# define MINESWP_UP BUTTON_SCROLL_UP +# define MINESWP_DOWN BUTTON_SCROLL_DOWN +# define MINESWP_QUIT BUTTON_POWER +# define MINESWP_START BUTTON_FF +# define MINESWP_TOGGLE BUTTON_PLAY +# define MINESWP_DISCOVER BUTTON_REW +# define MINESWP_INFO (BUTTON_REW | BUTTON_PLAY) +# define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY) +# define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY) +#else +# warning Missing key definitions for this keypad #endif /* here is a global api struct pointer. while not strictly necessary, - it's nice not to have to pass the api pointer in all function calls - in the plugin */ -static struct plugin_api* rb; - - -/* define how numbers are displayed (that way we don't have to */ -/* worry about fonts) */ -static unsigned char num[10][8] = { - /*reading the sprites: - on screen f123 - 4567 - 890a - bcde - - in binary b84f - c951 - d062 - ea73 - */ - - /* 0 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ........ */ - 0x00},/* ........ */ - /* 1 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x00, /* ...OO... */ - 0x44, /* ....O... */ - 0x7c, /* ....O... */ - 0x40, /* ....O... */ - 0x00, /* ...OOO.. */ - 0x00},/* ........ */ - /* 2 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x48, /* ...OO... */ - 0x64, /* ..O..O.. */ - 0x54, /* ....O... */ - 0x48, /* ...O.... */ - 0x00, /* ..OOOO.. */ - 0x00},/* ........ */ - /* 3 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x44, /* ..OOO... */ - 0x54, /* .....O.. */ - 0x54, /* ...OO... */ - 0x28, /* .....O.. */ - 0x00, /* ..OOO... */ - 0x00},/* ........ */ - /* 4 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x1c, /* ..O..... */ - 0x10, /* ..O..... */ - 0x70, /* ..OOOO.. */ - 0x10, /* ....O... */ - 0x00, /* ....O... */ - 0x00},/* ........ */ - /* 5 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x5c, /* ..OOOO.. */ - 0x54, /* ..O..... */ - 0x54, /* ..OOO... */ - 0x24, /* .....O.. */ - 0x00, /* ..OOO... */ - 0x00},/* ........ */ - /* 6 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x38, /* ...OOO.. */ - 0x54, /* ..O..... */ - 0x54, /* ..OOO... */ - 0x24, /* ..O..O.. */ - 0x00, /* ...OO... */ - 0x00},/* ........ */ - /* 7 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x44, /* ..OOOO.. */ - 0x24, /* .....O.. */ - 0x14, /* ....O... */ - 0x0c, /* ...O.... */ - 0x00, /* ..O..... */ - 0x00},/* ........ */ - /* 8 */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x28, /* ...OO... */ - 0x54, /* ..O..O.. */ - 0x54, /* ...OO... */ - 0x28, /* ..O..O.. */ - 0x00, /* ...OO... */ - 0x00},/* ........ */ - /* mine */ - {0x00, /* ........ */ - 0x00, /* ........ */ - 0x18, /* ...OO... */ - 0x3c, /* ..OOOO.. */ - 0x3c, /* ..OOOO.. */ - 0x18, /* ...OO... */ - 0x00, /* ........ */ - 0x00},/* ........ */ + * it's nice not to have to pass the api pointer in all function calls + * in the plugin + */ +static struct plugin_api *rb; + +extern const fb_data minesweeper_tiles[]; + +#ifdef HAVE_LCD_COLOR +# if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130 + /* We want to have at least 130 tiles on the screen */ +# define TileSize 16 +# else +# define TileSize 12 +# endif +# define BackgroundColor LCD_RGBPACK( 128, 128, 128 ) +#elif LCD_DEPTH > 1 +# define TileSize 12 +#else +# define TileSize 8 +#endif + +#define Mine 9 +#define Flag 10 +#define Unknown 11 +#define ExplodedMine 12 + +#define draw_tile( num, x, y ) \ + rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \ + TileSize, left+x*TileSize, top+y*TileSize, \ + TileSize, TileSize ) + +#define invert_tile( x, y ) \ + rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \ + rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \ + rb->lcd_set_drawmode(DRMODE_SOLID); -}; /* the tile struct -if there is a mine, mine is true -if tile is known by player, known is true -if tile has a flag, flag is true -neighbors is the total number of mines arround tile -*/ -typedef struct tile { + * if there is a mine, mine is true + * if tile is known by player, known is true + * if tile has a flag, flag is true + * neighbors is the total number of mines arround tile + */ +typedef struct tile +{ unsigned char mine : 1; unsigned char known : 1; unsigned char flag : 1; @@ -248,17 +173,21 @@ typedef struct tile { } tile; /* the height and width of the field */ -int height = LCD_HEIGHT/8; -int width = LCD_WIDTH/8; +#define MAX_HEIGHT (LCD_HEIGHT/TileSize) +#define MAX_WIDTH (LCD_WIDTH/TileSize) +int height = MAX_HEIGHT; +int width = MAX_WIDTH; +int top; +int left; /* The Minefield. Caution it is defined as Y, X! Not the opposite. */ -tile minefield[LCD_HEIGHT/8][LCD_WIDTH/8]; +tile minefield[MAX_HEIGHT][MAX_WIDTH]; /* total number of mines on the game */ int mine_num = 0; /* percentage of mines on minefield used during generation */ -int p=16; +int p = 16; /* number of tiles left on the game */ int tiles_left; @@ -269,83 +198,77 @@ bool no_mines = true; /* We need a stack (created on discover()) for the cascade algorithm. */ int stack_pos = 0; -/* Functions to center the board on screen. */ -int c_height(void){ - return LCD_HEIGHT/16 - height/2; -} - -int c_width(void){ - return LCD_WIDTH/16 - width/2; -} +/* a usefull string for snprintf */ +char str[30]; -void push (int *stack, int y, int x){ - if(stack_pos <= height*width){ - stack_pos++; - stack[stack_pos] = y; - stack_pos++; - stack[stack_pos] = x; +void push( int *stack, int y, int x ) +{ + if( stack_pos <= height*width ) + { + stack[++stack_pos] = y; + stack[++stack_pos] = x; } } /* Unveil tiles and push them to stack if they are empty. */ -void unveil(int *stack, int y, int x){ +void unveil( int *stack, int y, int x ) +{ + if( x < 0 || y < 0 || x > width - 1 || y > height - 1 + || minefield[y][x].known + || minefield[y][x].mine || minefield[y][x].flag ) return; - if(x < c_width() || y < c_height() || x > c_width() + width-1 - || y > c_height() + height-1 || minefield[y][x].known - || minefield[y][x].mine || minefield[y][x].flag) return; + minefield[y][x].known = 1; - if(minefield[y][x].neighbors == 0){ - minefield[y][x].known = 1; - push(stack, y, x); - } else - minefield[y][x].known = 1; + if( minefield[y][x].neighbors == 0 ) + push( stack, y, x ); } -void discover(int y, int x){ - +void discover( int y, int x ) +{ int stack[height*width]; /* Selected tile. */ - if(x < c_width() || y < c_height() || x > c_width() + width-1 - || y > c_height() + height-1 || minefield[y][x].known - || minefield[y][x].mine || minefield[y][x].flag) return; + if( x < 0 || y < 0 || x > width - 1 || y > height - 1 + || minefield[y][x].known + || minefield[y][x].mine || minefield[y][x].flag ) return; minefield[y][x].known = 1; /* Exit if the tile is not empty. (no mines nearby) */ - if(minefield[y][x].neighbors) return; + if( minefield[y][x].neighbors ) return; - push(stack, y, x); + push( stack, y, x ); /* Scan all nearby tiles. If we meet a tile with a number we just unveil - it. If we meet an empty tile, we push the location in stack. For each - location in stack we do the same thing. (scan again all nearby tiles) */ - while(stack_pos){ - /* Retrieve x, y from stack. */ - x = stack[stack_pos]; - y = stack[stack_pos-1]; - - /* Pop. */ - if(stack_pos > 0) stack_pos -= 2; - else rb->splash(HZ,true,"ERROR"); - - unveil(stack, y-1, x-1); - unveil(stack, y-1, x); - unveil(stack, y-1, x+1); - unveil(stack, y, x+1); - unveil(stack, y+1, x+1); - unveil(stack, y+1, x); - unveil(stack, y+1, x-1); - unveil(stack, y, x-1); + * it. If we meet an empty tile, we push the location in stack. For each + * location in stack we do the same thing. (scan again all nearby tiles) + */ + while( stack_pos ) + { + /* Pop x, y from stack. */ + x = stack[stack_pos--]; + y = stack[stack_pos--]; + + unveil( stack, y-1, x-1 ); + unveil( stack, y-1, x ); + unveil( stack, y-1, x+1 ); + unveil( stack, y, x+1 ); + unveil( stack, y+1, x+1 ); + unveil( stack, y+1, x ); + unveil( stack, y+1, x-1 ); + unveil( stack, y, x-1 ); } } /* Reset the whole board for a new game. */ -void minesweeper_init(void){ +void minesweeper_init( void ) +{ int i,j; - for(i=0;i<LCD_HEIGHT/8;i++){ - for(j=0;j<LCD_WIDTH/8;j++){ + for( i = 0; i < MAX_HEIGHT; i++ ) + { + for( j = 0; j < MAX_WIDTH; j++ ) + { minefield[i][j].known = 0; minefield[i][j].flag = 0; minefield[i][j].mine = 0; @@ -360,16 +283,22 @@ void minesweeper_init(void){ /* put mines on the mine field */ /* there is p% chance that a tile is a mine */ /* if the tile has coordinates (x,y), then it can't be a mine */ -void minesweeper_putmines(int p, int x, int y){ +void minesweeper_putmines( int p, int x, int y ) +{ int i,j; mine_num = 0; - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ - if(rb->rand()%100<p && !(y==i && x==j)){ + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( rb->rand()%100 < p && !( y==i && x==j ) ) + { minefield[i][j].mine = 1; mine_num++; - } else { + } + else + { minefield[i][j].mine = 0; } minefield[i][j].neighbors = 0; @@ -377,59 +306,66 @@ void minesweeper_putmines(int p, int x, int y){ } /* we need to compute the neighbor element for each tile */ - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ - if(i>0){ - if(j>0) + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( i > 0 ) + { + if( j > 0 ) minefield[i][j].neighbors += minefield[i-1][j-1].mine; minefield[i][j].neighbors += minefield[i-1][j].mine; - if(j<c_width() + width-1) + if( j < width - 1 ) minefield[i][j].neighbors += minefield[i-1][j+1].mine; } - if(j>0) + if( j > 0 ) minefield[i][j].neighbors += minefield[i][j-1].mine; - if(j<c_width() + width-1) + if( j < width - 1 ) minefield[i][j].neighbors += minefield[i][j+1].mine; - if(i<c_height() + height-1){ - if(j>0) + if( i < height - 1 ) + { + if( j > 0 ) minefield[i][j].neighbors += minefield[i+1][j-1].mine; minefield[i][j].neighbors += minefield[i+1][j].mine; - if(j<c_width() + width-1) + if( j < width - 1 ) minefield[i][j].neighbors += minefield[i+1][j+1].mine; } } } no_mines = false; + /* In case the user is lucky and there are no mines positioned. */ - if(!mine_num && height*width != 1) minesweeper_putmines(p, x, y); + if( !mine_num && height*width != 1 ) + { + minesweeper_putmines(p, x, y); + } } /* A function that will uncover all the board, when the user wins or loses. can easily be expanded, (just a call assigned to a button) as a solver. */ -void mine_show(void){ +void mine_show( void ) +{ int i, j, button; - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_DARKGRAY); - rb->lcd_drawrect(j*8,i*8,8,8); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_drawrect(j*8,i*8,8,8); -#endif - if(!minefield[i][j].known){ - if(minefield[i][j].mine){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[9], j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - } else if(minefield[i][j].neighbors){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[minefield[i][j].neighbors], - j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( minefield[i][j].mine ) + { + if( minefield[i][j].known ) + { + draw_tile( ExplodedMine, j, i ); } + else + { + draw_tile( Mine, j, i ); + } + } + else + { + draw_tile( minefield[i][j].neighbors, j, i ); } } } @@ -437,90 +373,97 @@ void mine_show(void){ do button = rb->button_get(true); - while ((button == BUTTON_NONE) || (button & (BUTTON_REL|BUTTON_REPEAT))); + while( ( button == BUTTON_NONE ) + || ( button & (BUTTON_REL|BUTTON_REPEAT) ) ); } +int count_tiles_left( void ) +{ + int tiles_left = 0; + int i, j; + for( i = 0; i < height; i++ ) + for( j = 0; j < width; j++ ) + if( minefield[i][j].known == 0 ) + tiles_left++; + return tiles_left; +} -/* the big and ugly function that is the game */ -int minesweeper(void) +/* welcome screen where player can chose mine percentage */ +enum minesweeper_status menu( void ) { - int i,j; int button; - int lastbutton = BUTTON_NONE; - - /* the cursor coordinates */ - int x=0, y=0; - /* a usefull string for snprintf */ - char str[30]; - - /* welcome screen where player can chose mine percentage */ - i = 0; - while(true){ + while( true ) + { +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background( LCD_WHITE ); + rb->lcd_set_foreground( LCD_BLACK ); +#endif rb->lcd_clear_display(); - rb->lcd_puts(0,0,"Mine Sweeper"); + rb->lcd_puts( 0, 0, "Mine Sweeper" ); - rb->snprintf(str, 20, "%d%% mines", p); - rb->lcd_puts(0,2,str); - rb->lcd_puts(0,3,"down / up"); - rb->snprintf(str, 20, "%d cols x %d rows", width, height); - rb->lcd_puts(0,4,str); - rb->lcd_puts(0,5,"left x right "); + rb->snprintf( str, 20, "%d%% mines", p ); + rb->lcd_puts( 0, 2, str ); + rb->lcd_puts( 0, 3, "down / up" ); + rb->snprintf( str, 20, "%d cols x %d rows", width, height ); + rb->lcd_puts( 0, 4, str ); + rb->lcd_puts( 0, 5, "left x right" ); + rb->lcd_puts( 0, 6, #if CONFIG_KEYPAD == RECORDER_PAD - rb->lcd_puts(0,6,"ON to start"); + "ON to start" #elif CONFIG_KEYPAD == ONDIO_PAD - rb->lcd_puts(0,6,"MODE to start"); -#elif (CONFIG_KEYPAD==IRIVER_H100_PAD) || (CONFIG_KEYPAD==IPOD_4G_PAD) - rb->lcd_puts(0,6,"SELECT to start"); + "MODE to start" +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \ + || (CONFIG_KEYPAD == IRIVER_H300_PAD ) \ + || (CONFIG_KEYPAD == IPOD_4G_PAD) + "SELECT to start" #elif CONFIG_KEYPAD == IAUDIO_X5_PAD - rb->lcd_puts(0,6,"REC to start"); + "REC to start" +#else + "" +# warning Please define help string for this keypad. #endif + ); rb->lcd_update(); - button = rb->button_get(true); - switch(button){ + switch( button = rb->button_get( true ) ) + { case MINESWP_DOWN: - case (MINESWP_DOWN | BUTTON_REPEAT): - p = (p + 98)%100; - /* Don't let the user play without mines. */ - if(!p) p = 98; + case MINESWP_DOWN|BUTTON_REPEAT: + p = (p + 94)%98 + 2; break; case MINESWP_UP: - case (MINESWP_UP | BUTTON_REPEAT): - p = (p + 2)%100; - /* Don't let the user play without mines. */ - if(!p) p = 2; + case MINESWP_UP|BUTTON_REPEAT: + p = p%98 + 2; break; case BUTTON_RIGHT: - case (BUTTON_RIGHT | BUTTON_REPEAT): - height = height%(LCD_HEIGHT/8)+1; + case BUTTON_RIGHT|BUTTON_REPEAT: + height = height%MAX_HEIGHT + 1; break; case BUTTON_LEFT: - case (BUTTON_LEFT | BUTTON_REPEAT): - width = width%(LCD_WIDTH/8)+1; + case BUTTON_LEFT|BUTTON_REPEAT: + width = width%MAX_WIDTH + 1; break; case MINESWP_RIGHT: - case (MINESWP_RIGHT | BUTTON_REPEAT): + case MINESWP_RIGHT|BUTTON_REPEAT: height--; - if(height < 1) height = LCD_HEIGHT/8; - if(height > LCD_HEIGHT) height = 1; + if( height < 1 ) height = MAX_HEIGHT; break; case MINESWP_LEFT: - case (MINESWP_LEFT | BUTTON_REPEAT): + case MINESWP_LEFT|BUTTON_REPEAT: width--; - if(width < 1) width = LCD_WIDTH/8; - if(width > LCD_WIDTH) width = 1; + if( width < 1 ) width = MAX_WIDTH; break; case MINESWP_START:/* start playing */ - i = 1; - break; + return MINESWEEPER_WIN; + #ifdef MINESWP_RC_QUIT case MINESWP_RC_QUIT: #endif @@ -528,74 +471,79 @@ int minesweeper(void) return MINESWEEPER_QUIT; default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + if( rb->default_event_handler(button) == SYS_USB_CONNECTED ) return MINESWEEPER_USB; break; } - if(i==1) - break; } +} +/* the big and ugly game function */ +enum minesweeper_status minesweeper( void ) +{ + int i, j; + int button; + int lastbutton = BUTTON_NONE; - /******************** - * init * - ********************/ - - minesweeper_init(); - x = c_width(); - y = c_height(); + /* the cursor coordinates */ + int x=0, y=0; - /********************** - * play * - **********************/ + /** + * Show the menu + */ + if( ( i = menu() ) != MINESWEEPER_WIN ) return i; - while(true){ + /** + * Init game + */ + top = (LCD_HEIGHT-height*TileSize)/2; + left = (LCD_WIDTH-width*TileSize)/2; - /*clear the screen buffer */ + rb->srand( *rb->current_tick ); + minesweeper_init(); + x = 0; + y = 0; + + /** + * Play + */ + while( true ) + { + + /* clear the screen buffer */ +#ifdef HAVE_LCD_COLOR + rb->lcd_set_background( BackgroundColor ); +#endif rb->lcd_clear_display(); - /*display the mine field */ - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_DARKGRAY); - rb->lcd_drawrect(j*8,i*8,8,8); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_drawrect(j*8,i*8,8,8); -#endif - if(minefield[i][j].known){ - if(minefield[i][j].neighbors){ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_mono_bitmap(num[minefield[i][j].neighbors], - j*8,i*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); - } - } else if(minefield[i][j].flag) { - rb->lcd_drawline(j*8+2,i*8+2,j*8+5,i*8+5); - rb->lcd_drawline(j*8+2,i*8+5,j*8+5,i*8+2); - } else { -#if LCD_DEPTH > 1 - rb->lcd_set_foreground(LCD_LIGHTGRAY); - rb->lcd_fillrect(j*8+1,i*8+1,6,6); - rb->lcd_set_foreground(LCD_BLACK); -#else - rb->lcd_fillrect(j*8+2,i*8+2,4,4); -#endif + /* display the mine field */ + for( i = 0; i < height; i++ ) + { + for( j = 0; j < width; j++ ) + { + if( minefield[i][j].known ) + { + draw_tile( minefield[i][j].neighbors, j, i ); + } + else if(minefield[i][j].flag) + { + draw_tile( Flag, j, i ); + } + else + { + draw_tile( Unknown, j, i ); } } } /* display the cursor */ - rb->lcd_set_drawmode(DRMODE_COMPLEMENT); - rb->lcd_fillrect(x*8,y*8,8,8); - rb->lcd_set_drawmode(DRMODE_SOLID); + invert_tile( x, y ); /* update the screen */ rb->lcd_update(); - button = rb->button_get(true); - switch(button){ + switch( button = rb->button_get( true ) ) + { /* quit minesweeper (you really shouldn't use this button ...) */ #ifdef MINESWP_RC_QUIT case MINESWP_RC_QUIT: @@ -603,94 +551,83 @@ int minesweeper(void) case MINESWP_QUIT: return MINESWEEPER_QUIT; - /* move cursor left */ + /* move cursor left */ case BUTTON_LEFT: - case (BUTTON_LEFT | BUTTON_REPEAT): - if(x<=c_width()) x = width + c_width(); - x = x-1; + case BUTTON_LEFT|BUTTON_REPEAT: + x = ( x + width - 1 )%width; break; - /* move cursor right */ + /* move cursor right */ case BUTTON_RIGHT: - case (BUTTON_RIGHT | BUTTON_REPEAT): - if(x>=width + c_width() - 1) x = c_width() - 1; - x = x+1; + case BUTTON_RIGHT|BUTTON_REPEAT: + x = ( x + 1 )%width; break; - /* move cursor down */ + /* move cursor down */ case MINESWP_DOWN: - case (MINESWP_DOWN | BUTTON_REPEAT): - if(y>=height + c_height() - 1) y = c_height() - 1; - y = y+1; + case MINESWP_DOWN|BUTTON_REPEAT: + y = ( y + 1 )%height; break; - /* move cursor up */ + /* move cursor up */ case MINESWP_UP: - case (MINESWP_UP | BUTTON_REPEAT): - if(y<=c_height()) y = height + c_height(); - y = y-1; + case MINESWP_UP|BUTTON_REPEAT: + y = ( y + height - 1 )%height; break; - /* discover a tile (and it's neighbors if .neighbors == 0) */ + /* discover a tile (and it's neighbors if .neighbors == 0) */ case MINESWP_DISCOVER: #ifdef MINESWP_DISCOVER2 case MINESWP_DISCOVER2: #endif - if(minefield[y][x].flag) break; - /* we put the mines on the first "click" so that you don't */ - /* lose on the first "click" */ - if(tiles_left == width*height && no_mines) + if( minefield[y][x].flag ) break; + /* we put the mines on the first "click" so that you don't + * lose on the first "click" */ + if( tiles_left == width*height && no_mines ) minesweeper_putmines(p,x,y); discover(y, x); - if(minefield[y][x].mine){ + if( minefield[y][x].mine ) + { + minefield[y][x].known = 1; return MINESWEEPER_LOSE; } - tiles_left = 0; - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ - if(minefield[i][j].known == 0) tiles_left++; - } - } - if(tiles_left == mine_num){ + tiles_left = count_tiles_left(); + if( tiles_left == mine_num ) + { return MINESWEEPER_WIN; } break; - /* toggle flag under cursor */ + /* toggle flag under cursor */ case MINESWP_TOGGLE: #ifdef MINESWP_TOGGLE_PRE - if (lastbutton != MINESWP_TOGGLE_PRE) + if( lastbutton != MINESWP_TOGGLE_PRE ) break; #endif #ifdef MINESWP_TOGGLE2 case MINESWP_TOGGLE2: #endif - minefield[y][x].flag = (minefield[y][x].flag + 1)%2; + minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2; break; - /* show how many mines you think you have found and how many */ - /* there really are on the game */ + /* show how many mines you think you have found and how many + * there really are on the game */ case MINESWP_INFO: - if(no_mines) break; - tiles_left = 0; - for(i=c_height();i<c_height() + height;i++){ - for(j=c_width();j<c_width() + width;j++){ - if(minefield[i][j].flag && !minefield[i][j].known) - tiles_left++; - } - } - rb->splash(HZ*2, true, "You found %d mines out of %d", - tiles_left, mine_num); + if( no_mines ) + break; + tiles_left = count_tiles_left(); + rb->splash( HZ*2, true, "You found %d mines out of %d", + tiles_left, mine_num ); break; default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) return MINESWEEPER_USB; break; } - if (button != BUTTON_NONE) + if( button != BUTTON_NONE ) lastbutton = button; } @@ -700,21 +637,22 @@ int minesweeper(void) enum plugin_status plugin_start(struct plugin_api* api, void* parameter) { bool exit = false; - /* plugin init */ + (void)parameter; rb = api; - /* end of plugin init */ - while(!exit) { - switch(minesweeper()){ + while( !exit ) + { + switch( minesweeper() ) + { case MINESWEEPER_WIN: - rb->splash(HZ*2, true, "You Win! Press a key"); + rb->splash( HZ, true, "You Win!" ); rb->lcd_clear_display(); mine_show(); break; case MINESWEEPER_LOSE: - rb->splash(HZ*2, true, "You Lose! Press a key"); + rb->splash( HZ, true, "You Lose!" ); rb->lcd_clear_display(); mine_show(); break; |