/* the big and ugly game function */ enum minesweeper_status minesweeper( void ) { int i, j; int button; #if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE) int lastbutton = BUTTON_NONE; #endif /* the cursor coordinates */ 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; #ifdef HAVE_TOUCHSCREEN mine_raster.tl_x = left; mine_raster.tl_y = top; mine_raster.width = width*TileSize; mine_raster.height = height*TileSize; #endif 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 = 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 */ invert_tile( x, y ); /* update the screen */ rb->lcd_update(); button = rb->button_get(true); #ifdef HAVE_TOUCHSCREEN if(button & BUTTON_TOUCHSCREEN) { struct ts_raster_result res; if(touchscreen_map_raster(&mine_raster, rb->button_get_data() >> 16, rb->button_get_data() & 0xffff, &res) == 1) { button &= ~BUTTON_TOUCHSCREEN; lastbutton &= ~BUTTON_TOUCHSCREEN; if(button & BUTTON_REPEAT && lastbutton != MINESWP_TOGGLE && lastbutton ^ BUTTON_REPEAT) button = MINESWP_TOGGLE; else if(button == BUTTON_REL && lastbutton ^ BUTTON_REPEAT) button = MINESWP_DISCOVER; else button |= BUTTON_TOUCHSCREEN; x = res.x; y = res.y; } } #endif switch(button) { /* quit minesweeper (you really shouldn't use this button ...) */ #ifdef MINESWP_RC_QUIT case MINESWP_RC_QUIT: #endif case MINESWP_QUIT: return MINESWEEPER_QUIT; /* move cursor left */ case MINESWP_LEFT: case MINESWP_LEFT|BUTTON_REPEAT: if( --x < 0) x += width; break; /* move cursor right */ case MINESWP_RIGHT: case MINESWP_RIGHT|BUTTON_REPEAT: if( ++x >= width ) x -= width; break; /* move cursor down */ case MINESWP_DOWN: case MINESWP_DOWN|BUTTON_REPEAT: if( ++y >= height ) y -= height; break; /* move cursor up */ case MINESWP_UP: case MINESWP_UP|BUTTON_REPEAT: if( --y < 0 ) y += height; break; /*move cursor though the entire field*/ #ifdef MINESWP_SCROLLWHEEL case MINESWP_NEXT: case MINESWP_NEXT|BUTTON_REPEAT: if (x == width -1 ) { if( ++y >= height ) y -= height; } if( ++x >= width ) x -= width; break; case MINESWP_PREV: case MINESWP_PREV|BUTTON_REPEAT: if (x == 0) { if( --y < 0 ) y += height; } if( --x < 0 ) x += width; break; #endif /* 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 ) minesweeper_putmines(percent,x,y); if( discover( y, x, true ) ) { minefield[y][x].known = 1; return MINESWEEPER_LOSE; } tiles_left = count_tiles_left(); if( tiles_left == mine_num ) { return MINESWEEPER_WIN; } break; /* toggle flag under cursor */ case MINESWP_TOGGLE: #ifdef MINESWP_TOGGLE_PRE if( lastbutton != MINESWP_TOGGLE_PRE ) break; #endif #ifdef MINESWP_TOGGLE2 case MINESWP_TOGGLE2: #endif if( !minefield[y][x].known ) minefield[y][x].flag = !minefield[y][x].flag; break; /* 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; int flags_used = count_flags(); if (flags_used == 1) { rb->splashf( HZ*2, "You marked 1 field. There are %d mines.", mine_num ); } else { rb->splashf( HZ*2, "You marked %d fields. There are %d mines.", flags_used, mine_num ); } break; default: if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) return MINESWEEPER_USB; break; } #if defined(HAVE_TOUCHSCREEN) || defined(MINESWP_TOGGLE_PRE) if( button != BUTTON_NONE ) lastbutton = button; #endif } }
/* the big and ugly function that is the game */ int minesweeper(void) { int i,j; int button; int lastbutton = BUTTON_NONE; /* the cursor coordinates */ int x=0,y=0; /* number of tiles left on the game */ int tiles_left=width*height; /* percentage of mines on minefield used durring generation */ int p=16; /* a usefull string for snprintf */ char str[30]; /* welcome screen where player can chose mine percentage */ i = 0; while(true){ rb->lcd_clear_display(); 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 "); #if CONFIG_KEYPAD == RECORDER_PAD rb->lcd_puts(0,6,"ON to start"); #elif CONFIG_KEYPAD == ONDIO_PAD rb->lcd_puts(0,6,"MODE to start"); #elif CONFIG_KEYPAD == IRIVER_H100_PAD rb->lcd_puts(0,6,"SELECT to start"); #endif rb->lcd_update(); button = rb->button_get(true); switch(button){ case BUTTON_DOWN: p = (p + 98)%100; break; case BUTTON_UP: p = (p + 2)%100; break; case BUTTON_RIGHT: height = height%(LCD_HEIGHT/8)+1; break; case BUTTON_LEFT: width = width%(LCD_WIDTH/8)+1; break; case MINESWP_START:/* start playing */ i = 1; break; case MINESWP_QUIT:/* quit program */ return MINESWEEPER_QUIT; default: if (rb->default_event_handler(button) == SYS_USB_CONNECTED) return MINESWEEPER_USB; break; } if(i==1) break; } /******************** * init * ********************/ minesweeper_init(); /********************** * play * **********************/ while(true){ //clear the screen buffer rb->lcd_clear_display(); //display the mine field for(i=0;i<height;i++){ for(j=0;j<width;j++){ #if LCD_DEPTH > 1 rb->lcd_set_foreground(DARK_GRAY); 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_putsxy(j*8+1,i*8+1,"b"); } else if(minefield[i][j].neighbors){ rb->lcd_set_drawmode(DRMODE_FG); 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(LIGHT_GRAY); 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 cursor */ rb->lcd_set_drawmode(DRMODE_COMPLEMENT); rb->lcd_fillrect(x*8,y*8,8,8); rb->lcd_set_drawmode(DRMODE_SOLID); /* update the screen */ rb->lcd_update(); button = rb->button_get(true); switch(button){ /* quit minesweeper (you really shouldn't use this button ...) */ case MINESWP_QUIT: return MINESWEEPER_QUIT; /* move cursor left */ case BUTTON_LEFT: case (BUTTON_LEFT | BUTTON_REPEAT): x = (x + width - 1)%width; break; /* move cursor right */ case BUTTON_RIGHT: case (BUTTON_RIGHT | BUTTON_REPEAT): x = (x + 1)%width; break; /* move cursor down */ case BUTTON_DOWN: case (BUTTON_DOWN | BUTTON_REPEAT): y = (y + 1)%height; break; /* move cursor up */ case BUTTON_UP: case (BUTTON_UP | BUTTON_REPEAT): y = (y + height - 1)%height; break; /* 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) minesweeper_putmines(p,x,y); discover(x,y); if(minefield[y][x].mine){ return MINESWEEPER_LOSE; } tiles_left = 0; for(i=0;i<height;i++){ for(j=0;j<width;j++){ if(minefield[i][j].known == 0) tiles_left++; } } if(tiles_left == mine_num){ return MINESWEEPER_WIN; } break; /* toggle flag under cursor */ case MINESWP_TOGGLE: #ifdef 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; break; /* show how many mines you think you have found and how many */ /* there really are on the game */ case MINESWP_INFO: tiles_left = 0; for(i=0;i<height;i++){ for(j=0;j<width;j++){ if(minefield[i][j].flag) 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) return MINESWEEPER_USB; break; } if (button != BUTTON_NONE) lastbutton = button; } }