forked from len0rd/rockbox
*: 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
This commit is contained in:
parent
c9bb152a33
commit
e2a73dc389
6 changed files with 378 additions and 428 deletions
|
@ -280,4 +280,16 @@ rockpaint.bmp
|
||||||
rockpaint_hsvrgb.bmp
|
rockpaint_hsvrgb.bmp
|
||||||
#endif
|
#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 */
|
#endif /* HAVE_LCD_BITMAP */
|
||||||
|
|
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp
Normal file
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.12x12x2.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.9 KiB |
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp
Normal file
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.12x12x24.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp
Normal file
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.16x16x24.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp
Normal file
BIN
apps/plugins/bitmaps/native/minesweeper_tiles.8x8x1.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.5 KiB |
|
@ -17,10 +17,6 @@
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
Mine Sweeper by dionoea
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
|
||||||
#ifdef HAVE_LCD_BITMAP
|
#ifdef HAVE_LCD_BITMAP
|
||||||
|
@ -28,10 +24,12 @@ Mine Sweeper by dionoea
|
||||||
PLUGIN_HEADER
|
PLUGIN_HEADER
|
||||||
|
|
||||||
/* what the minesweeper() function can return */
|
/* what the minesweeper() function can return */
|
||||||
#define MINESWEEPER_USB 3
|
enum minesweeper_status {
|
||||||
#define MINESWEEPER_QUIT 2
|
MINESWEEPER_WIN,
|
||||||
#define MINESWEEPER_LOSE 1
|
MINESWEEPER_LOSE,
|
||||||
#define MINESWEEPER_WIN 0
|
MINESWEEPER_QUIT,
|
||||||
|
MINESWEEPER_USB
|
||||||
|
};
|
||||||
|
|
||||||
/* variable button definitions */
|
/* variable button definitions */
|
||||||
#if CONFIG_KEYPAD == RECORDER_PAD
|
#if CONFIG_KEYPAD == RECORDER_PAD
|
||||||
|
@ -118,129 +116,56 @@ PLUGIN_HEADER
|
||||||
# define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY)
|
# define MINESWP_RIGHT (BUTTON_RIGHT | BUTTON_PLAY)
|
||||||
# define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY)
|
# define MINESWP_LEFT (BUTTON_LEFT | BUTTON_PLAY)
|
||||||
|
|
||||||
|
#else
|
||||||
|
# warning Missing key definitions for this keypad
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* here is a global api struct pointer. while not strictly necessary,
|
/* 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
|
* it's nice not to have to pass the api pointer in all function calls
|
||||||
in the plugin */
|
* in the plugin
|
||||||
|
*/
|
||||||
static struct plugin_api *rb;
|
static struct plugin_api *rb;
|
||||||
|
|
||||||
|
extern const fb_data minesweeper_tiles[];
|
||||||
|
|
||||||
/* define how numbers are displayed (that way we don't have to */
|
#ifdef HAVE_LCD_COLOR
|
||||||
/* worry about fonts) */
|
# if ( LCD_HEIGHT * LCD_WIDTH ) / ( 16 * 16 ) >= 130
|
||||||
static unsigned char num[10][8] = {
|
/* We want to have at least 130 tiles on the screen */
|
||||||
/*reading the sprites:
|
# define TileSize 16
|
||||||
on screen f123
|
# else
|
||||||
4567
|
# define TileSize 12
|
||||||
890a
|
# endif
|
||||||
bcde
|
# define BackgroundColor LCD_RGBPACK( 128, 128, 128 )
|
||||||
|
#elif LCD_DEPTH > 1
|
||||||
|
# define TileSize 12
|
||||||
|
#else
|
||||||
|
# define TileSize 8
|
||||||
|
#endif
|
||||||
|
|
||||||
in binary b84f
|
#define Mine 9
|
||||||
c951
|
#define Flag 10
|
||||||
d062
|
#define Unknown 11
|
||||||
ea73
|
#define ExplodedMine 12
|
||||||
*/
|
|
||||||
|
|
||||||
/* 0 */
|
#define draw_tile( num, x, y ) \
|
||||||
{0x00, /* ........ */
|
rb->lcd_bitmap_part( minesweeper_tiles, 0, num * TileSize, \
|
||||||
0x00, /* ........ */
|
TileSize, left+x*TileSize, top+y*TileSize, \
|
||||||
0x00, /* ........ */
|
TileSize, TileSize )
|
||||||
0x00, /* ........ */
|
|
||||||
0x00, /* ........ */
|
#define invert_tile( x, y ) \
|
||||||
0x00, /* ........ */
|
rb->lcd_set_drawmode(DRMODE_COMPLEMENT); \
|
||||||
0x00, /* ........ */
|
rb->lcd_fillrect( left+x*TileSize, top+y*TileSize, TileSize, TileSize ); \
|
||||||
0x00},/* ........ */
|
rb->lcd_set_drawmode(DRMODE_SOLID);
|
||||||
/* 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},/* ........ */
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
/* the tile struct
|
/* the tile struct
|
||||||
if there is a mine, mine is true
|
* if there is a mine, mine is true
|
||||||
if tile is known by player, known is true
|
* if tile is known by player, known is true
|
||||||
if tile has a flag, flag is true
|
* if tile has a flag, flag is true
|
||||||
neighbors is the total number of mines arround tile
|
* neighbors is the total number of mines arround tile
|
||||||
*/
|
*/
|
||||||
typedef struct tile {
|
typedef struct tile
|
||||||
|
{
|
||||||
unsigned char mine : 1;
|
unsigned char mine : 1;
|
||||||
unsigned char known : 1;
|
unsigned char known : 1;
|
||||||
unsigned char flag : 1;
|
unsigned char flag : 1;
|
||||||
|
@ -248,11 +173,15 @@ typedef struct tile {
|
||||||
} tile;
|
} tile;
|
||||||
|
|
||||||
/* the height and width of the field */
|
/* the height and width of the field */
|
||||||
int height = LCD_HEIGHT/8;
|
#define MAX_HEIGHT (LCD_HEIGHT/TileSize)
|
||||||
int width = LCD_WIDTH/8;
|
#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. */
|
/* 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 */
|
/* total number of mines on the game */
|
||||||
int mine_num = 0;
|
int mine_num = 0;
|
||||||
|
@ -269,46 +198,39 @@ bool no_mines = true;
|
||||||
/* We need a stack (created on discover()) for the cascade algorithm. */
|
/* We need a stack (created on discover()) for the cascade algorithm. */
|
||||||
int stack_pos = 0;
|
int stack_pos = 0;
|
||||||
|
|
||||||
/* Functions to center the board on screen. */
|
/* a usefull string for snprintf */
|
||||||
int c_height(void){
|
char str[30];
|
||||||
return LCD_HEIGHT/16 - height/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
int c_width(void){
|
|
||||||
return LCD_WIDTH/16 - width/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
void push (int *stack, int y, int x){
|
void push( int *stack, int y, int x )
|
||||||
|
{
|
||||||
if(stack_pos <= height*width){
|
if( stack_pos <= height*width )
|
||||||
stack_pos++;
|
{
|
||||||
stack[stack_pos] = y;
|
stack[++stack_pos] = y;
|
||||||
stack_pos++;
|
stack[++stack_pos] = x;
|
||||||
stack[stack_pos] = x;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unveil tiles and push them to stack if they are empty. */
|
/* 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 < c_width() || y < c_height() || x > c_width() + width-1
|
if( x < 0 || y < 0 || x > width - 1 || y > height - 1
|
||||||
|| y > c_height() + height-1 || minefield[y][x].known
|
|| minefield[y][x].known
|
||||||
|| minefield[y][x].mine || minefield[y][x].flag ) return;
|
|| minefield[y][x].mine || minefield[y][x].flag ) return;
|
||||||
|
|
||||||
if(minefield[y][x].neighbors == 0){
|
|
||||||
minefield[y][x].known = 1;
|
minefield[y][x].known = 1;
|
||||||
|
|
||||||
|
if( minefield[y][x].neighbors == 0 )
|
||||||
push( stack, y, x );
|
push( stack, y, x );
|
||||||
} else
|
|
||||||
minefield[y][x].known = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void discover(int y, int x){
|
void discover( int y, int x )
|
||||||
|
{
|
||||||
int stack[height*width];
|
int stack[height*width];
|
||||||
|
|
||||||
/* Selected tile. */
|
/* Selected tile. */
|
||||||
if(x < c_width() || y < c_height() || x > c_width() + width-1
|
if( x < 0 || y < 0 || x > width - 1 || y > height - 1
|
||||||
|| y > c_height() + height-1 || minefield[y][x].known
|
|| minefield[y][x].known
|
||||||
|| minefield[y][x].mine || minefield[y][x].flag ) return;
|
|| minefield[y][x].mine || minefield[y][x].flag ) return;
|
||||||
|
|
||||||
minefield[y][x].known = 1;
|
minefield[y][x].known = 1;
|
||||||
|
@ -318,16 +240,14 @@ void discover(int y, int x){
|
||||||
push( stack, y, x );
|
push( stack, y, x );
|
||||||
|
|
||||||
/* Scan all nearby tiles. If we meet a tile with a number we just unveil
|
/* 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
|
* 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) */
|
* location in stack we do the same thing. (scan again all nearby tiles)
|
||||||
while(stack_pos){
|
*/
|
||||||
/* Retrieve x, y from stack. */
|
while( stack_pos )
|
||||||
x = stack[stack_pos];
|
{
|
||||||
y = stack[stack_pos-1];
|
/* Pop x, y from stack. */
|
||||||
|
x = stack[stack_pos--];
|
||||||
/* Pop. */
|
y = stack[stack_pos--];
|
||||||
if(stack_pos > 0) stack_pos -= 2;
|
|
||||||
else rb->splash(HZ,true,"ERROR");
|
|
||||||
|
|
||||||
unveil( stack, y-1, x-1 );
|
unveil( stack, y-1, x-1 );
|
||||||
unveil( stack, y-1, x );
|
unveil( stack, y-1, x );
|
||||||
|
@ -341,11 +261,14 @@ void discover(int y, int x){
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset the whole board for a new game. */
|
/* Reset the whole board for a new game. */
|
||||||
void minesweeper_init(void){
|
void minesweeper_init( void )
|
||||||
|
{
|
||||||
int i,j;
|
int i,j;
|
||||||
|
|
||||||
for(i=0;i<LCD_HEIGHT/8;i++){
|
for( i = 0; i < MAX_HEIGHT; i++ )
|
||||||
for(j=0;j<LCD_WIDTH/8;j++){
|
{
|
||||||
|
for( j = 0; j < MAX_WIDTH; j++ )
|
||||||
|
{
|
||||||
minefield[i][j].known = 0;
|
minefield[i][j].known = 0;
|
||||||
minefield[i][j].flag = 0;
|
minefield[i][j].flag = 0;
|
||||||
minefield[i][j].mine = 0;
|
minefield[i][j].mine = 0;
|
||||||
|
@ -360,16 +283,22 @@ void minesweeper_init(void){
|
||||||
/* put mines on the mine field */
|
/* put mines on the mine field */
|
||||||
/* there is p% chance that a tile is a mine */
|
/* there is p% chance that a tile is a mine */
|
||||||
/* if the tile has coordinates (x,y), then it can't be 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;
|
int i,j;
|
||||||
|
|
||||||
mine_num = 0;
|
mine_num = 0;
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
for( i = 0; i < height; i++ )
|
||||||
for(j=c_width();j<c_width() + width;j++){
|
{
|
||||||
if(rb->rand()%100<p && !(y==i && x==j)){
|
for( j = 0; j < width; j++ )
|
||||||
|
{
|
||||||
|
if( rb->rand()%100 < p && !( y==i && x==j ) )
|
||||||
|
{
|
||||||
minefield[i][j].mine = 1;
|
minefield[i][j].mine = 1;
|
||||||
mine_num++;
|
mine_num++;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
minefield[i][j].mine = 0;
|
minefield[i][j].mine = 0;
|
||||||
}
|
}
|
||||||
minefield[i][j].neighbors = 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 */
|
/* we need to compute the neighbor element for each tile */
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
for( i = 0; i < height; i++ )
|
||||||
for(j=c_width();j<c_width() + width;j++){
|
{
|
||||||
if(i>0){
|
for( j = 0; j < width; j++ )
|
||||||
|
{
|
||||||
|
if( i > 0 )
|
||||||
|
{
|
||||||
if( j > 0 )
|
if( j > 0 )
|
||||||
minefield[i][j].neighbors += minefield[i-1][j-1].mine;
|
minefield[i][j].neighbors += minefield[i-1][j-1].mine;
|
||||||
minefield[i][j].neighbors += minefield[i-1][j].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;
|
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;
|
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;
|
minefield[i][j].neighbors += minefield[i][j+1].mine;
|
||||||
if(i<c_height() + height-1){
|
if( i < height - 1 )
|
||||||
|
{
|
||||||
if( j > 0 )
|
if( j > 0 )
|
||||||
minefield[i][j].neighbors += minefield[i+1][j-1].mine;
|
minefield[i][j].neighbors += minefield[i+1][j-1].mine;
|
||||||
minefield[i][j].neighbors += minefield[i+1][j].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;
|
minefield[i][j].neighbors += minefield[i+1][j+1].mine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
no_mines = false;
|
no_mines = false;
|
||||||
|
|
||||||
/* In case the user is lucky and there are no mines positioned. */
|
/* 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.
|
/* 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. */
|
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;
|
int i, j, button;
|
||||||
|
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
for( i = 0; i < height; i++ )
|
||||||
for(j=c_width();j<c_width() + width;j++){
|
{
|
||||||
#if LCD_DEPTH > 1
|
for( j = 0; j < width; j++ )
|
||||||
rb->lcd_set_foreground(LCD_DARKGRAY);
|
{
|
||||||
rb->lcd_drawrect(j*8,i*8,8,8);
|
if( minefield[i][j].mine )
|
||||||
rb->lcd_set_foreground(LCD_BLACK);
|
{
|
||||||
#else
|
if( minefield[i][j].known )
|
||||||
rb->lcd_drawrect(j*8,i*8,8,8);
|
{
|
||||||
#endif
|
draw_tile( ExplodedMine, j, i );
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
draw_tile( Mine, j, i );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
draw_tile( minefield[i][j].neighbors, j, i );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,26 +373,32 @@ void mine_show(void){
|
||||||
|
|
||||||
do
|
do
|
||||||
button = rb->button_get(true);
|
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 )
|
||||||
/* the big and ugly function that is the game */
|
|
||||||
int minesweeper(void)
|
|
||||||
{
|
{
|
||||||
|
int tiles_left = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
int button;
|
for( i = 0; i < height; i++ )
|
||||||
int lastbutton = BUTTON_NONE;
|
for( j = 0; j < width; j++ )
|
||||||
|
if( minefield[i][j].known == 0 )
|
||||||
/* the cursor coordinates */
|
tiles_left++;
|
||||||
int x=0, y=0;
|
return tiles_left;
|
||||||
|
}
|
||||||
/* a usefull string for snprintf */
|
|
||||||
char str[30];
|
|
||||||
|
|
||||||
/* welcome screen where player can chose mine percentage */
|
/* welcome screen where player can chose mine percentage */
|
||||||
i = 0;
|
enum minesweeper_status menu( void )
|
||||||
while(true){
|
{
|
||||||
|
int button;
|
||||||
|
|
||||||
|
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_clear_display();
|
||||||
|
|
||||||
rb->lcd_puts( 0, 0, "Mine Sweeper" );
|
rb->lcd_puts( 0, 0, "Mine Sweeper" );
|
||||||
|
@ -467,60 +409,61 @@ int minesweeper(void)
|
||||||
rb->snprintf( str, 20, "%d cols x %d rows", width, height );
|
rb->snprintf( str, 20, "%d cols x %d rows", width, height );
|
||||||
rb->lcd_puts( 0, 4, str );
|
rb->lcd_puts( 0, 4, str );
|
||||||
rb->lcd_puts( 0, 5, "left x right" );
|
rb->lcd_puts( 0, 5, "left x right" );
|
||||||
|
rb->lcd_puts( 0, 6,
|
||||||
#if CONFIG_KEYPAD == RECORDER_PAD
|
#if CONFIG_KEYPAD == RECORDER_PAD
|
||||||
rb->lcd_puts(0,6,"ON to start");
|
"ON to start"
|
||||||
#elif CONFIG_KEYPAD == ONDIO_PAD
|
#elif CONFIG_KEYPAD == ONDIO_PAD
|
||||||
rb->lcd_puts(0,6,"MODE to start");
|
"MODE to start"
|
||||||
#elif (CONFIG_KEYPAD==IRIVER_H100_PAD) || (CONFIG_KEYPAD==IPOD_4G_PAD)
|
#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) \
|
||||||
rb->lcd_puts(0,6,"SELECT to start");
|
|| (CONFIG_KEYPAD == IRIVER_H300_PAD ) \
|
||||||
|
|| (CONFIG_KEYPAD == IPOD_4G_PAD)
|
||||||
|
"SELECT to start"
|
||||||
#elif CONFIG_KEYPAD == IAUDIO_X5_PAD
|
#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
|
#endif
|
||||||
|
);
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
|
||||||
button = rb->button_get(true);
|
switch( button = rb->button_get( true ) )
|
||||||
switch(button){
|
{
|
||||||
case MINESWP_DOWN:
|
case MINESWP_DOWN:
|
||||||
case (MINESWP_DOWN | BUTTON_REPEAT):
|
case MINESWP_DOWN|BUTTON_REPEAT:
|
||||||
p = (p + 98)%100;
|
p = (p + 94)%98 + 2;
|
||||||
/* Don't let the user play without mines. */
|
|
||||||
if(!p) p = 98;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINESWP_UP:
|
case MINESWP_UP:
|
||||||
case (MINESWP_UP | BUTTON_REPEAT):
|
case MINESWP_UP|BUTTON_REPEAT:
|
||||||
p = (p + 2)%100;
|
p = p%98 + 2;
|
||||||
/* Don't let the user play without mines. */
|
|
||||||
if(!p) p = 2;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BUTTON_RIGHT:
|
case BUTTON_RIGHT:
|
||||||
case (BUTTON_RIGHT | BUTTON_REPEAT):
|
case BUTTON_RIGHT|BUTTON_REPEAT:
|
||||||
height = height%(LCD_HEIGHT/8)+1;
|
height = height%MAX_HEIGHT + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BUTTON_LEFT:
|
case BUTTON_LEFT:
|
||||||
case (BUTTON_LEFT | BUTTON_REPEAT):
|
case BUTTON_LEFT|BUTTON_REPEAT:
|
||||||
width = width%(LCD_WIDTH/8)+1;
|
width = width%MAX_WIDTH + 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINESWP_RIGHT:
|
case MINESWP_RIGHT:
|
||||||
case (MINESWP_RIGHT | BUTTON_REPEAT):
|
case MINESWP_RIGHT|BUTTON_REPEAT:
|
||||||
height--;
|
height--;
|
||||||
if(height < 1) height = LCD_HEIGHT/8;
|
if( height < 1 ) height = MAX_HEIGHT;
|
||||||
if(height > LCD_HEIGHT) height = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINESWP_LEFT:
|
case MINESWP_LEFT:
|
||||||
case (MINESWP_LEFT | BUTTON_REPEAT):
|
case MINESWP_LEFT|BUTTON_REPEAT:
|
||||||
width--;
|
width--;
|
||||||
if(width < 1) width = LCD_WIDTH/8;
|
if( width < 1 ) width = MAX_WIDTH;
|
||||||
if(width > LCD_WIDTH) width = 1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINESWP_START:/* start playing */
|
case MINESWP_START:/* start playing */
|
||||||
i = 1;
|
return MINESWEEPER_WIN;
|
||||||
break;
|
|
||||||
#ifdef MINESWP_RC_QUIT
|
#ifdef MINESWP_RC_QUIT
|
||||||
case MINESWP_RC_QUIT:
|
case MINESWP_RC_QUIT:
|
||||||
#endif
|
#endif
|
||||||
|
@ -532,70 +475,75 @@ int minesweeper(void)
|
||||||
return MINESWEEPER_USB;
|
return MINESWEEPER_USB;
|
||||||
break;
|
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;
|
||||||
|
|
||||||
/********************
|
/* the cursor coordinates */
|
||||||
* init *
|
int x=0, y=0;
|
||||||
********************/
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the menu
|
||||||
|
*/
|
||||||
|
if( ( i = menu() ) != MINESWEEPER_WIN ) return i;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init game
|
||||||
|
*/
|
||||||
|
top = (LCD_HEIGHT-height*TileSize)/2;
|
||||||
|
left = (LCD_WIDTH-width*TileSize)/2;
|
||||||
|
|
||||||
|
rb->srand( *rb->current_tick );
|
||||||
minesweeper_init();
|
minesweeper_init();
|
||||||
x = c_width();
|
x = 0;
|
||||||
y = c_height();
|
y = 0;
|
||||||
|
|
||||||
/**********************
|
/**
|
||||||
* play *
|
* Play
|
||||||
**********************/
|
*/
|
||||||
|
while( true )
|
||||||
while(true){
|
{
|
||||||
|
|
||||||
/* clear the screen buffer */
|
/* clear the screen buffer */
|
||||||
|
#ifdef HAVE_LCD_COLOR
|
||||||
|
rb->lcd_set_background( BackgroundColor );
|
||||||
|
#endif
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
|
|
||||||
/* display the mine field */
|
/* display the mine field */
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
for( i = 0; i < height; i++ )
|
||||||
for(j=c_width();j<c_width() + width;j++){
|
{
|
||||||
#if LCD_DEPTH > 1
|
for( j = 0; j < width; j++ )
|
||||||
rb->lcd_set_foreground(LCD_DARKGRAY);
|
{
|
||||||
rb->lcd_drawrect(j*8,i*8,8,8);
|
if( minefield[i][j].known )
|
||||||
rb->lcd_set_foreground(LCD_BLACK);
|
{
|
||||||
#else
|
draw_tile( minefield[i][j].neighbors, j, i );
|
||||||
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) {
|
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);
|
draw_tile( Flag, j, i );
|
||||||
} else {
|
}
|
||||||
#if LCD_DEPTH > 1
|
else
|
||||||
rb->lcd_set_foreground(LCD_LIGHTGRAY);
|
{
|
||||||
rb->lcd_fillrect(j*8+1,i*8+1,6,6);
|
draw_tile( Unknown, j, i );
|
||||||
rb->lcd_set_foreground(LCD_BLACK);
|
|
||||||
#else
|
|
||||||
rb->lcd_fillrect(j*8+2,i*8+2,4,4);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* display the cursor */
|
/* display the cursor */
|
||||||
rb->lcd_set_drawmode(DRMODE_COMPLEMENT);
|
invert_tile( x, y );
|
||||||
rb->lcd_fillrect(x*8,y*8,8,8);
|
|
||||||
rb->lcd_set_drawmode(DRMODE_SOLID);
|
|
||||||
|
|
||||||
/* update the screen */
|
/* update the screen */
|
||||||
rb->lcd_update();
|
rb->lcd_update();
|
||||||
|
|
||||||
button = rb->button_get(true);
|
switch( button = rb->button_get( true ) )
|
||||||
switch(button){
|
{
|
||||||
/* quit minesweeper (you really shouldn't use this button ...) */
|
/* quit minesweeper (you really shouldn't use this button ...) */
|
||||||
#ifdef MINESWP_RC_QUIT
|
#ifdef MINESWP_RC_QUIT
|
||||||
case MINESWP_RC_QUIT:
|
case MINESWP_RC_QUIT:
|
||||||
|
@ -605,30 +553,26 @@ int minesweeper(void)
|
||||||
|
|
||||||
/* move cursor left */
|
/* move cursor left */
|
||||||
case BUTTON_LEFT:
|
case BUTTON_LEFT:
|
||||||
case (BUTTON_LEFT | BUTTON_REPEAT):
|
case BUTTON_LEFT|BUTTON_REPEAT:
|
||||||
if(x<=c_width()) x = width + c_width();
|
x = ( x + width - 1 )%width;
|
||||||
x = x-1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* move cursor right */
|
/* move cursor right */
|
||||||
case BUTTON_RIGHT:
|
case BUTTON_RIGHT:
|
||||||
case (BUTTON_RIGHT | BUTTON_REPEAT):
|
case BUTTON_RIGHT|BUTTON_REPEAT:
|
||||||
if(x>=width + c_width() - 1) x = c_width() - 1;
|
x = ( x + 1 )%width;
|
||||||
x = x+1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* move cursor down */
|
/* move cursor down */
|
||||||
case MINESWP_DOWN:
|
case MINESWP_DOWN:
|
||||||
case (MINESWP_DOWN | BUTTON_REPEAT):
|
case MINESWP_DOWN|BUTTON_REPEAT:
|
||||||
if(y>=height + c_height() - 1) y = c_height() - 1;
|
y = ( y + 1 )%height;
|
||||||
y = y+1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* move cursor up */
|
/* move cursor up */
|
||||||
case MINESWP_UP:
|
case MINESWP_UP:
|
||||||
case (MINESWP_UP | BUTTON_REPEAT):
|
case MINESWP_UP|BUTTON_REPEAT:
|
||||||
if(y<=c_height()) y = height + c_height();
|
y = ( y + height - 1 )%height;
|
||||||
y = y-1;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* discover a tile (and it's neighbors if .neighbors == 0) */
|
/* discover a tile (and it's neighbors if .neighbors == 0) */
|
||||||
|
@ -637,23 +581,21 @@ int minesweeper(void)
|
||||||
case MINESWP_DISCOVER2:
|
case MINESWP_DISCOVER2:
|
||||||
#endif
|
#endif
|
||||||
if( minefield[y][x].flag ) break;
|
if( minefield[y][x].flag ) break;
|
||||||
/* we put the mines on the first "click" so that you don't */
|
/* we put the mines on the first "click" so that you don't
|
||||||
/* lose on the first "click" */
|
* lose on the first "click" */
|
||||||
if( tiles_left == width*height && no_mines )
|
if( tiles_left == width*height && no_mines )
|
||||||
minesweeper_putmines(p,x,y);
|
minesweeper_putmines(p,x,y);
|
||||||
|
|
||||||
discover(y, x);
|
discover(y, x);
|
||||||
|
|
||||||
if(minefield[y][x].mine){
|
if( minefield[y][x].mine )
|
||||||
|
{
|
||||||
|
minefield[y][x].known = 1;
|
||||||
return MINESWEEPER_LOSE;
|
return MINESWEEPER_LOSE;
|
||||||
}
|
}
|
||||||
tiles_left = 0;
|
tiles_left = count_tiles_left();
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
if( tiles_left == mine_num )
|
||||||
for(j=c_width();j<c_width() + width;j++){
|
{
|
||||||
if(minefield[i][j].known == 0) tiles_left++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(tiles_left == mine_num){
|
|
||||||
return MINESWEEPER_WIN;
|
return MINESWEEPER_WIN;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -670,17 +612,12 @@ int minesweeper(void)
|
||||||
minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2;
|
minefield[y][x].flag = ( minefield[y][x].flag + 1 )%2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* show how many mines you think you have found and how many */
|
/* show how many mines you think you have found and how many
|
||||||
/* there really are on the game */
|
* there really are on the game */
|
||||||
case MINESWP_INFO:
|
case MINESWP_INFO:
|
||||||
if(no_mines) break;
|
if( no_mines )
|
||||||
tiles_left = 0;
|
break;
|
||||||
for(i=c_height();i<c_height() + height;i++){
|
tiles_left = count_tiles_left();
|
||||||
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",
|
rb->splash( HZ*2, true, "You found %d mines out of %d",
|
||||||
tiles_left, mine_num );
|
tiles_left, mine_num );
|
||||||
break;
|
break;
|
||||||
|
@ -700,21 +637,22 @@ int minesweeper(void)
|
||||||
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
enum plugin_status plugin_start(struct plugin_api* api, void* parameter)
|
||||||
{
|
{
|
||||||
bool exit = false;
|
bool exit = false;
|
||||||
/* plugin init */
|
|
||||||
(void)parameter;
|
(void)parameter;
|
||||||
rb = api;
|
rb = api;
|
||||||
/* end of plugin init */
|
|
||||||
|
|
||||||
while(!exit) {
|
while( !exit )
|
||||||
switch(minesweeper()){
|
{
|
||||||
|
switch( minesweeper() )
|
||||||
|
{
|
||||||
case MINESWEEPER_WIN:
|
case MINESWEEPER_WIN:
|
||||||
rb->splash(HZ*2, true, "You Win! Press a key");
|
rb->splash( HZ, true, "You Win!" );
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
mine_show();
|
mine_show();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MINESWEEPER_LOSE:
|
case MINESWEEPER_LOSE:
|
||||||
rb->splash(HZ*2, true, "You Lose! Press a key");
|
rb->splash( HZ, true, "You Lose!" );
|
||||||
rb->lcd_clear_display();
|
rb->lcd_clear_display();
|
||||||
mine_show();
|
mine_show();
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue