diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/flag.c | 26 | ||||
| -rw-r--r-- | src/flip.c | 105 | ||||
| -rw-r--r-- | src/init.c | 115 | ||||
| -rw-r--r-- | src/main.c | 290 | ||||
| -rw-r--r-- | src/move.c | 55 | ||||
| -rw-r--r-- | src/xSDL.c | 35 | 
6 files changed, 626 insertions, 0 deletions
| diff --git a/src/flag.c b/src/flag.c new file mode 100644 index 0000000..9201cac --- /dev/null +++ b/src/flag.c @@ -0,0 +1,26 @@ +/* +** flag.c for  in /home/gayot_o/prog/minesweeper +**  +** Made by olivier gayot +** Login   <gayot_o@epitech.net> +**  +** Started on  Sun Apr 22 19:02:49 2012 olivier gayot +** Last update Sun Apr 22 19:02:49 2012 olivier gayot +*/ + +#include	"minesweeper.h" + +int		flag(map_t *map, int *selection) { +  case_t		*case_ = &map->tab[*selection / BLOCK_W][*selection % BLOCK_W]; + +  if (!case_->hidden) +    return 0; +  case_->flagged = (case_->flagged) ? false : true; +  if (case_->flagged) +    ++g_flags; +  else +    --g_flags; +  dsp_ribbon_flags(); +  show_map(map); +  return 0; +} diff --git a/src/flip.c b/src/flip.c new file mode 100644 index 0000000..3ab50d5 --- /dev/null +++ b/src/flip.c @@ -0,0 +1,105 @@ +/* +** flip.c for  in /home/gayot_o/prog/minesweeper +**  +** Made by olivier gayot +** Login   <gayot_o@epitech.net> +**  +** Started on  Sun Apr 22 17:49:25 2012 olivier gayot +** Last update Sun Apr 22 17:49:25 2012 olivier gayot +*/ + +#include	"minesweeper.h" + +static int	get_flag_touch(case_t tab[BLOCK_H][BLOCK_W], int j, int i); +static int	rec(case_t map[BLOCK_H][BLOCK_W], int j, int i); +static int	flip_around(case_t tab[BLOCK_H][BLOCK_W], int j, int i); + +int		flip(map_t *map, int *selection) { +  case_t		*case_ = &map->tab[*selection / BLOCK_W][*selection % BLOCK_W]; +  int		ret; + +  if (!case_->hidden && get_flag_touch(map->tab, +	*selection / BLOCK_W, *selection % BLOCK_W) == case_->touch) +    ret = flip_around(map->tab, *selection / BLOCK_W, *selection % BLOCK_W); +  else +    ret = rec(map->tab, *selection / BLOCK_W, *selection % BLOCK_W); +  show_map(map); +  return ret; +} + +static int	rec(case_t tab[BLOCK_H][BLOCK_W], int j, int i) { +  case_t		*case_ = &tab[j][i]; + +  if (!case_->hidden || case_->flagged) +    return 0; +  case_->hidden = false; +  if (!case_->type) +    ++discovered; +  if (case_->type) +    return -1; +  if (case_->touch == 0) { +    { +      if (j + 1 < BLOCK_H && i + 1 < BLOCK_W) +	rec(tab, j + 1, i + 1); +      if (j + 1 < BLOCK_H) +	rec(tab, j + 1, i); +      if (j + 1 < BLOCK_H && i - 1 >= 0) +	rec(tab, j + 1, i - 1); +      if (j - 1 >= 0 && i + 1 < BLOCK_W) +	rec(tab, j - 1, i + 1); +      if (j - 1 >= 0) +	rec(tab, j - 1, i); +      if (j - 1 >= 0 && i - 1 >= 0) +	rec(tab, j - 1, i - 1); +      if (i - 1 >= 0) +	rec(tab, j, i - 1); +      if (i + 1 < BLOCK_W) +	rec(tab, j, i + 1); +    } +  } +  return 0; +} + +static int	get_flag_touch(case_t tab[BLOCK_H][BLOCK_W], int j, int i) { +  int		flags = 0; + +  if (j + 1 < BLOCK_H && i + 1 < BLOCK_W && tab[j + 1][i + 1].flagged) +    ++flags; +  if (j + 1 < BLOCK_H && tab[j + 1][i].flagged) +    ++flags; +  if (j + 1 < BLOCK_H && i - 1 >= 0 && tab[j + 1][i - 1].flagged) +    ++flags; +  if (j - 1 >= 0 && i + 1 < BLOCK_W&& tab[j - 1][i + 1].flagged) +    ++flags; +  if (j - 1 >= 0 && tab[j - 1][i].flagged) +    ++flags; +  if (j - 1 >= 0 && i - 1 >= 0 && tab[j - 1][i - 1].flagged) +    ++flags; +  if (i - 1 >= 0 && tab[j][i - 1].flagged) +    ++flags; +  if (i + 1 < BLOCK_W && tab[j][i + 1].flagged) +    ++flags; +  return flags; +} + +static int	flip_around(case_t tab[BLOCK_H][BLOCK_W], int j, int i) { +  int		ret = 0; + +  if (j + 1 < BLOCK_H && i + 1 < BLOCK_W) +    if (rec(tab, j + 1, i + 1) == -1) ret = -1; +  if (j + 1 < BLOCK_H) +    if (rec(tab, j + 1, i) == -1) ret = -1; +  if (j + 1 < BLOCK_H && i - 1 >= 0) +    if (rec(tab, j + 1, i - 1) == -1) ret = -1; +  if (j - 1 >= 0 && i + 1 < BLOCK_W) +    if (rec(tab, j - 1, i + 1) == -1) ret = -1; +  if (j - 1 >= 0) +    if (rec(tab, j - 1, i) == -1) ret = -1; +  if (j - 1 >= 0 && i - 1 >= 0) +    if (rec(tab, j - 1, i - 1) == -1) ret = -1; +  if (i - 1 >= 0) +    if (rec(tab, j, i - 1) == -1) ret = -1; +  if (i + 1 < BLOCK_W) +    if (rec(tab, j, i + 1) == -1) ret = -1; +  return ret; +} diff --git a/src/init.c b/src/init.c new file mode 100644 index 0000000..812598f --- /dev/null +++ b/src/init.c @@ -0,0 +1,115 @@ +/* +** init.c for  in /home/gayot_o/prog/minesweeper +**  +** Made by olivier gayot +** Login   <gayot_o@epitech.net> +**  +** Started on  Sun Apr 22 16:09:49 2012 olivier gayot +** Last update Sun Apr 22 16:09:49 2012 olivier gayot +*/ + +#include	<stdio.h> +#include	<sdl_digit.h> +#include	<strings.h> +#include	"minesweeper.h" + +static void		rand_bombs(bool bombs[BLOCK_H][BLOCK_W]); +static SDL_Surface	*xSDL_LoadBMP(const char *path); + +void		init_map(map_t *map) { +  bool		bombs[BLOCK_H][BLOCK_W]; + +  rand_bombs(bombs); map->bombs = BOMBS; +  for (int j = 0; j < BLOCK_H; ++j) { +    for (int i = 0; i < BLOCK_W; ++i) { +      if (!(map->tab[j][i].type = bombs[j][i])) +	map->tab[j][i].touch = get_nbr_touch(bombs, j, i); +      map->tab[j][i].x = i * BLOCK_SIZE; +      map->tab[j][i].y = j * BLOCK_SIZE; +      map->tab[j][i].hidden = true; +      map->tab[j][i].selected = false; +      map->tab[j][i].flagged = false; +    } +  } +  map->tab[0][0].selected = true; +} + +static void	rand_bombs(bool bombs[BLOCK_H][BLOCK_W]) { +  int		i = 0; + +  memset((void *)bombs, 0, sizeof(bool) * BLOCK_H * BLOCK_W); +  while (i < BOMBS) { +    int id = rand() % (BLOCK_H * BLOCK_W); +    if (bombs[id / BLOCK_W][id % BLOCK_W] == 0) { +      bombs[id / BLOCK_W][id % BLOCK_W] = 1; +      ++i; +    } +  } +} + +void		load_surfaces(void) { +  char		str[256]; + +  for (int i = 0; i < 9; ++i) { +    snprintf(str, 256, "img/%d.bmp", i); +    surf_number[i] = xSDL_LoadBMP(str); +  } +  bmb_surf = xSDL_LoadBMP("img/b.bmp"); +  hidden_surf = xSDL_LoadBMP("img/hidden.bmp"); +  flag_surf = xSDL_LoadBMP("img/flag.bmp"); +  wrong_flag = xSDL_LoadBMP("img/wrong_flag.bmp"); +  selection_surf = xSDL_LoadBMP("img/selection.bmp"); +  SDL_SetColorKey(selection_surf, SDL_SRCCOLORKEY, 0); +} + +void		dsp_ribbon_flags(void) { +  SDL_Surface	*surf; +  char		str[256]; +  SDL_Rect	rect; + +  surf = SDL_CreateRGBSurface(SDL_HWSURFACE, 90, 40, 32, 0, 0, 0, 0); +  rect.x = BLOCK_SIZE * BLOCK_W - 90; +  rect.y = BLOCK_SIZE * BLOCK_H + 5; +  SDL_FillRect(surf, NULL, 0); +  xSDL_BlitSurface(surf, NULL, scr, &rect); +  if ((int)(BOMBS - g_flags) <= -100) +    sprintf(str, "-%u", ABS((int)(BOMBS - g_flags))); +  else if ((int)(BOMBS - g_flags) <= -10) +    sprintf(str, "-0%u", ABS((int)(BOMBS - g_flags))); +  else if ((int)(BOMBS - g_flags) < 0) +    sprintf(str, "-00%u", ABS((int)(BOMBS - g_flags))); +  else if ((int)(BOMBS - g_flags) < 10) +    sprintf(str, " 00%u", ABS((int)(BOMBS - g_flags))); +  else if ((int)(BOMBS - g_flags) < 100) +    sprintf(str, " 0%u", ABS((int)(BOMBS - g_flags))); +  else +    sprintf(str, " %d", BOMBS - g_flags); +  draw_string(surf, NULL, str, 0xff, 15); +  xSDL_BlitSurface(surf, NULL, scr, &rect); +  SDL_FreeSurface(surf); +} + +int		callback(void *param __attribute__((unused))) { +  Uint32	base_ticks = SDL_GetTicks(); + +  for (;;) { +    dsp_clock(base_ticks); +    SDL_Delay(200); +  } +  return 0; +} + +SDL_Thread	*start_clock(void) { +  return (SDL_CreateThread(&callback, NULL)); +} + +static SDL_Surface	*xSDL_LoadBMP(const char *path) { +  SDL_Surface		*surf; +  char			buffer[256]; + +  if (!(surf = SDL_LoadBMP(path))) { +    snprintf(buffer, 256, "Unable to load %s: %s\n", path, SDL_GetError()); +    exit(-1); +  } +  return (surf); +} diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..d2ef531 --- /dev/null +++ b/src/main.c @@ -0,0 +1,290 @@ +#include "minesweeper.h" + +#define shift_args(argc, argv)  *argv++ + +static void reveal_bombs(map_t *map) +{ +    SDL_Rect rect; + +    for (int j = 0; j < BLOCK_H; ++j) { +        for (int i = 0; i < BLOCK_W; ++i) { +            case_t  *case_ = &map->tab[j][i]; +            if (case_->type && case_->hidden && !case_->flagged) { +                rect.x = case_->x; +                rect.y = case_->y; +                xSDL_BlitSurface(bmb_surf, NULL, scr, &rect); +            } else if (!case_->type && case_->flagged) { +                rect.x = case_->x; +                rect.y = case_->y; +                xSDL_BlitSurface(wrong_flag, NULL, scr, &rect); +            } +        } +    } +} + +static int finished(SDL_Thread **clock_thread, int won, map_t *map) +{ +    SDL_Event event; +    SDL_Rect rect; +    SDL_Surface *surf; +    char  str[256]; +    int  ret = 1; + +    SDL_KillThread(*clock_thread); +    *clock_thread = NULL; +    reveal_bombs(map); +    sprintf(str, "You %s - press enter to continue", (won) ? "win" : "lose"); +    surf = new_string(str, 0xffffff, 10); +    rect.x = (BLOCK_W * BLOCK_SIZE) / 2 - surf->w / 2; +    rect.y = BLOCK_H * BLOCK_SIZE + 7; +    xSDL_BlitSurface(surf, NULL, scr, &rect); +    xSDL_Flip(scr); +    for (;;) { +        SDL_WaitEvent(&event); +        if (event.type == SDL_QUIT) { +            ret = 0; +            break; +        } +        else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_q) { +            ret = 0; +            break; +        } +        else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_RETURN) +            break; +    } +    SDL_FillRect(surf, NULL, 0); +    xSDL_BlitSurface(surf, NULL, scr, &rect); +    xSDL_Flip(scr); +    SDL_FreeSurface(surf); +    return (ret); +} + +static int quit(map_t *map __attribute__((unused)), +        int *selection __attribute__((unused))) +{ +    return 0; +} + +static int (*keydown(SDLKey key))(map_t *, int *) +{ +    if (key == SDLK_ESCAPE || key == SDLK_q) +        return (&quit); +    else if (key == SDLK_h || key == SDLK_LEFT) +        return (&move_left); +    else if (key == SDLK_l || key == SDLK_RIGHT) +        return (&move_right); +    else if (key == SDLK_k || key == SDLK_UP) +        return (&move_up); +    else if (key == SDLK_j || key == SDLK_DOWN) +        return (&move_down); +    else if (key == SDLK_f || key == SDLK_SPACE) +        return (&flip); +    else if (key == SDLK_d || key == SDLK_RETURN) +        return (&flag); +    return (NULL); +} + +static int mouseup(SDL_MouseButtonEvent *event, map_t *map) +{ +    int selection; + +    if (!(event->x < BLOCK_W * BLOCK_SIZE && event->y < BLOCK_H * BLOCK_SIZE)) +        return 0; + +    selection = event->x / BLOCK_SIZE + (event->y / BLOCK_SIZE) * BLOCK_W; + +    if (event->button == SDL_BUTTON_LEFT) { +        return flip(map, &selection); +    } else if (event->button == SDL_BUTTON_RIGHT) { +        flag(map, &selection); +    } + +    return 0; +} + +static int game(void) +{ +    SDL_Event event; +    map_t map; +    int (*f_ptr)(map_t *, int *); +    int selection = 0; +    int ret = 1; + +    discovered = 0; +    g_flags = 0; +    mutex = SDL_CreateMutex(); +    dsp_ribbon_flags(); +    init_map(&map); +    show_map(&map); +    SDL_Thread *clock_thread = start_clock(); +    for (;;) { +        if (discovered == BLOCK_W * BLOCK_H - BOMBS) { +            ret = finished(&clock_thread, 1, &map); +            break; +        } + +        SDL_WaitEvent(&event); +        if (event.type == SDL_KEYDOWN) { +            if ((f_ptr = keydown(event.key.keysym.sym))) { +                if (f_ptr(&map, &selection) == -1) { +                    ret = finished(&clock_thread, 0, &map); +                    quit(&map, &selection); +                    break; +                } else if (f_ptr == &quit) { +                    ret = 0; +                    break; +                } +            } +        } else if (event.type == SDL_QUIT) { +            quit(&map, &selection); +            ret = 0; +            break; +        } else if (event.type == SDL_MOUSEBUTTONUP) { +            if (mouseup(&event.button, &map) == -1) { +                ret = finished(&clock_thread, 0, &map); +                quit(&map, &selection); +                break; +            } +        } +    } + +    if (clock_thread) +        SDL_KillThread(clock_thread); +    SDL_DestroyMutex(mutex); +    return ret; +} + +int  get_nbr_touch(bool tab[BLOCK_H][BLOCK_W], int j, int i) { +    int  touch = 0; + +    if (i + 1 < BLOCK_W && tab[j][i + 1]) +        ++touch; +    if (j + 1 < BLOCK_H && tab[j + 1][i]) +        ++touch; +    if (j + 1 < BLOCK_H && i + 1 < BLOCK_W && tab[j + 1][i + 1]) +        ++touch; +    if (j - 1 >= 0 && tab[j - 1][i]) +        ++touch; +    if (j - 1 >= 0 && i + 1 < BLOCK_W && tab[j - 1][i + 1]) +        ++touch; +    if (j - 1 >= 0 && i - 1 >= 0 && tab[j - 1][i - 1]) +        ++touch; +    if (i - 1 >= 0 && tab[j][i - 1]) +        ++touch; +    if (i - 1 >= 0 && j + 1 < BLOCK_H && tab[j + 1][i - 1]) +        ++touch; +    return (touch); +} + +static void dsp_case(case_t *case_) { +    SDL_Surface *surf; +    SDL_Rect rect; + +    if (case_->flagged) +        surf = flag_surf; +    else if (case_->hidden) +        surf = hidden_surf; +    else if (case_->type) +        surf = bmb_surf; +    else +        surf = surf_number[case_->touch]; +    rect.x = case_->x; +    rect.y = case_->y; +    xSDL_BlitSurface(surf, NULL, scr, &rect); +    if (case_->selected) +        xSDL_BlitSurface(selection_surf, NULL, scr, &rect); +} + +void  show_map(map_t *map) { +    for (int j = 0; j < BLOCK_H; ++j) { +        for (int i = 0; i < BLOCK_W; ++i) { +            dsp_case(&map->tab[j][i]); +        } +    } + +    xSDL_Flip(scr); +} + +void  dsp_clock(Uint32 base_ticks) +{ +    static Uint32 previous = -1; + +    Uint32 ticks = (SDL_GetTicks() - base_ticks) / 1000; +    if (ticks != previous) +    { +        SDL_Surface *surf = SDL_CreateRGBSurface(SDL_HWSURFACE, 100, 40, 32, 0, 0, 0, 0); +        SDL_Rect rect; +        char str[256]; + +        rect.x = 0; +        rect.y = BLOCK_SIZE * BLOCK_H + 5; +        xSDL_BlitSurface(surf, NULL, scr, &rect); +        sprintf(str, "%d", ticks); +        draw_string(surf, NULL, (const char *)str, 0xff, 15); +        SDL_mutexP(mutex); +        SDL_BlitSurface(surf, NULL, scr, &rect); +        SDL_Flip(scr); +        SDL_mutexV(mutex); +        SDL_FreeSurface(surf); +    } +    previous = ticks; +} + +static void main_loop(void) +{ +    load_surfaces(); + +    while (game()); + +    for (int i = 0; i < 9; ++i) +        SDL_FreeSurface(surf_number[i]); + +    SDL_FreeSurface(hidden_surf); +    SDL_FreeSurface(selection_surf); +    SDL_FreeSurface(flag_surf); +    SDL_FreeSurface(bmb_surf); +    SDL_FreeSurface(wrong_flag); +} + +static char **parse_opts(int *argc, char **argv) +{ +    (void) argc; +    (void) argv; + +    return argv; +} + +int main(int argc, char **argv) +{ +    const char *arg0 = shift_args(--argc, argv); +    argv = parse_opts(&argc, argv); +    if (argc > 1) +        goto usage; +    if (SDL_Init(SDL_INIT_VIDEO) == -1) { +        fprintf(stderr, "SDL_Init fail: %s\n", SDL_GetError()); +        return (-1); +    } + +    atexit(SDL_Quit); + +    if ((scr = SDL_SetVideoMode(BLOCK_W * BLOCK_SIZE, BLOCK_H * BLOCK_SIZE + 50, 32, +                    SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL) { +        fprintf(stderr, "SDL_SetVideMode fail: %s\n", SDL_GetError()); +        return (-1); +    } +    srand(time(NULL)); +    SDL_EnableKeyRepeat(200, 50); +    SDL_WM_SetCaption("Minesweeper", "Minesweeper"); + +    main_loop(); + +    return 0; + +usage: +    printf("Usage: %s\n", arg0); +    printf("       %s --help\n", arg0); +    puts("Options:"); +    puts("--help   Display this help"); + +    exit(EX_USAGE); +} diff --git a/src/move.c b/src/move.c new file mode 100644 index 0000000..c14724c --- /dev/null +++ b/src/move.c @@ -0,0 +1,55 @@ +/* +** move.c for  in /home/gayot_o/prog/minesweeper +**  +** Made by olivier gayot +** Login   <gayot_o@epitech.net> +**  +** Started on  Sun Apr 22 17:08:59 2012 olivier gayot +** Last update Sun Apr 22 17:08:59 2012 olivier gayot +*/ + +#include	"minesweeper.h" + +static void	incr_selection(int incr, map_t *map, int *selection); + +int		move_left(map_t *map, int *selection) { +  if (*selection % BLOCK_W) +    incr_selection(-1, map, selection); +  else /* beginning of the line */ +    incr_selection(BLOCK_W - 1, map, selection); +  show_map(map); +  return 0; +} + +int		move_right(map_t *map, int *selection) { +  if (*selection % BLOCK_W != (BLOCK_W - 1)) +    incr_selection(+1, map, selection); +  else /* beginning of the line */ +    incr_selection(-(BLOCK_W - 1), map, selection); +  show_map(map); +  return 0; +} + +int		move_up(map_t *map, int *selection) { +  if (*selection / BLOCK_W) +    incr_selection(-BLOCK_W, map, selection); +  else /* beginning of the line */ +    incr_selection(BLOCK_W * (BLOCK_H - 1), map, selection); +  show_map(map); +  return 0; +} + +int		move_down(map_t *map, int *selection) { +  if (*selection / BLOCK_W != (BLOCK_H - 1)) +    incr_selection(BLOCK_W, map, selection); +  else /* beginning of the line */ +    incr_selection(-(BLOCK_W * (BLOCK_H - 1)), map, selection); +  show_map(map); +  return 0; +} + +static void	incr_selection(int incr, map_t *map, int *selection) { +  map->tab[*selection / BLOCK_W][*selection % BLOCK_W].selected = false; +  (*selection) += incr; +  map->tab[*selection / BLOCK_W][*selection % BLOCK_W].selected = true; +} diff --git a/src/xSDL.c b/src/xSDL.c new file mode 100644 index 0000000..3ee36cb --- /dev/null +++ b/src/xSDL.c @@ -0,0 +1,35 @@ +/* +** xSDL.c for  in /home/gayot_o/prog/minesweeper/src +**  +** Made by olivier gayot +** Login   <gayot_o@epitech.net> +**  +** Started on  Wed Apr 25 23:40:24 2012 olivier gayot +** Last update Wed Apr 25 23:40:24 2012 olivier gayot +*/ + +#include	"minesweeper.h" + +int	xSDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, +    SDL_Surface *dest, SDL_Rect *dstrect) { +  int	ret; +  if (dest != scr) +    ret = SDL_BlitSurface(src, srcrect, dest, dstrect); +  else +  { +    if (SDL_mutexP(mutex) == -1) +      fprintf(stderr, "Error during SDL_mutexP: %s\n", SDL_GetError()); +    ret = SDL_BlitSurface(src, srcrect, dest, dstrect); +    if (SDL_mutexV(mutex) == -1) +      fprintf(stderr, "Error during SDL_mutexV: %s\n", SDL_GetError()); +  } +  return (ret); +} + +void	xSDL_Flip(SDL_Surface *surf) { +  if (surf == scr) +    SDL_mutexP(mutex); +  SDL_Flip(surf); +  if (surf == scr) +    SDL_mutexV(mutex); +} | 
