Skip to content

Instantly share code, notes, and snippets.

@Hajto
Created January 21, 2018 14:38
Show Gist options
  • Save Hajto/ae0a3d509b50f4f6718f65099d440e1d to your computer and use it in GitHub Desktop.
Save Hajto/ae0a3d509b50f4f6718f65099d440e1d to your computer and use it in GitHub Desktop.
//
// Created by Haito on 19.01.2018.
//
#include <ncurses.h>
#include <unistd.h>
#include "minesweaper.h"
void initCurses() {
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
}
char stateToChar(int state) {
if (state == GAME_MINE) return '*';
if (state == GAME_UNALLOCATED) return '#';
else if (state == GAME_FLAGGED_MINE || state == GAME_FALSE_FLAG) return 'F';
else if (state == 0) return ' ';
else if (state > 0 && state <= 9) {
return (char) (state + 48); //48 is Asci of 0
} else return ' ';
}
void render_game(Game *game) {
mvaddch(0, 0, '+');
mvaddch(game->size_x + 1, 0, '+');
mvaddch(game->size_x + 1, game->size_y + 1, '+');
mvaddch(0, game->size_y + 1, '+');
for (int i = 1; i <= game->size_x; i++) {
mvaddch(0, i, '-');
mvaddch(game->size_y + 1, i, '-');
mvaddch(i, 0, '|');
mvaddch(i, game->size_x + 1, '|');
}
for (int i = 0; i < game->size_x; i++) {
for (int j = 0; j < game->size_y; j++) {
char display = stateToChar(game->game_board[i][j]);
mvaddch(j + 1, i + 1, display);
}
}
char status[128];
sprintf(status, "Bombs to go: %d", game->bombs_count - game->flags);
mvaddstr(game->size_y + 2, 1, status);
}
void move_in_bound(Game *game, int *x, int *y, int direction) {
if (direction == KEY_LEFT && *x > 1) {
*x = *x - 1;
} else if (direction == KEY_RIGHT && *x < game->size_x) {
*x = *x + 1;
} else if (direction == KEY_UP && *y > 1) {
*y = *y - 1;
} else if (direction == KEY_DOWN && *y < game->size_y) {
*y = *y + 1;
}
move(*y, *x);
}
int start_rendering_loop(Game *game) {
initCurses();
render_game(game);
int ch;
int x = 1, y = 1;
while ((ch = getch()) != KEY_F(1)) {
move_in_bound(game, &x, &y, ch);
if (ch == 10) { /* Enter */
int result = make_move(game, x - 1, y - 1);
if (result == GAME_STATUS_OK) {
render_game(game);
} else if (result == GAME_STATUS_BOOM) {
endwin();
return GAME_STATUS_BOOM;
}
} else if(ch == 102){ //TAB
mark_bomb(game, x-1, y-1);
if(game->bombs_count == 0)
return GAME_STATUS_OK;
render_game(game);
}
move(y,x);
refresh();
}
endwin();
return GAME_STATUS_OK;
}
//
// Created by Haito on 19.01.2018.
//
#include <menu.h>
#include "tt_menu.h"
#include "minesweaper.h"
#include "minesweaper_renderer.h"
#include "leaderboards.h"
#include <unistd.h>
#include <ncurses.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <memory.h>
#define SAVEFILE "data.dat"
void cycle_menu(MENU *menu);
int startGame();
int showLeaderBoards();
int exitGame();
int fetch_dim_until_valid(const char* message);
Game* build_game();
typedef int(*MenuCallback)();
static char *choices[] = {
"Play",
"Leaderboards",
"Exit",
};
static MenuCallback callbacks[] = {
startGame,
showLeaderBoards,
exitGame
};
void start_rendering_menu() {
ITEM **my_items;
MENU *my_menu;
int n_choices, i;
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
n_choices = ARRAY_SIZE(choices);
my_items = (ITEM **) calloc(n_choices + 1, sizeof(ITEM *));
for (i = 0; i < n_choices; ++i)
my_items[i] = new_item(choices[i], "");
my_items[n_choices] = (ITEM *) NULL;
my_menu = new_menu(my_items);
mvprintw(LINES - 2, 0, "F1 to Exit");
post_menu(my_menu);
refresh();
cycle_menu(my_menu);
free_item(my_items[0]);
free_item(my_items[1]);
free_menu(my_menu);
endwin();
}
void cycle_menu(MENU *menu) {
int c;
int running = 1;
while (running && (c = getch()) != KEY_F(1)) {
switch (c) {
case KEY_DOWN:
menu_driver(menu, REQ_DOWN_ITEM);
break;
case KEY_UP:
menu_driver(menu, REQ_UP_ITEM);
break;
case 10: /* Enter */
clrtoeol();
int selectedItem = item_index(current_item(menu));
running = callbacks[selectedItem]();
clear();
break;
}
}
}
int startGame() {
clear();
refresh();
Game* game = build_game();
// Game* game = start_game(10,10,1);
clear();
refresh();
int start_bomvs = game->bombs_count;
int result = start_rendering_loop(game);
if(result == GAME_STATUS_BOOM){
clear();
mvaddstr(0,0,"You lost!");
refresh();
sleep(10);
} else if(result == GAME_STATUS_OK){
clear();
refresh();
//TODO handle win
fflush(stdin);
char* question_result = NULL;
do {
if(question_result) free(question_result);
question_result = readline("Do you want to save your result? (only yes/no)\n");
} while(strcmp("yes", question_result) != 0 && strcmp("no", question_result) != 0);
if(strcmp("yes", question_result) == 0){
char* name = readline("What name you want to use for save?\n");
LeaderBoardEntry entry;
entry.points = 100;
strcpy(entry.name, name);
free(name);
sprintf(entry.dimms, "%d x %d - %d", game->size_x, game->size_y, start_bomvs);
appendToFile(entry, SAVEFILE);
}
if(question_result) free(question_result);
}
end_game(&game);
return 0;
}
int showLeaderBoards() {
int size = 0;
clear();
refresh();
LeaderBoardEntry* entries = readFromFile("data.dat", &size);
if(entries){
addstr("Leaderboard!\n");
for(int i = 0; i < size; i++) {
LeaderBoardEntry entry = entries[i];
char buffer[BUFSIZ];
sprintf(buffer,"%d. %s - %s -> %d", i+1, entry.name, entry.dimms, entry.points);
mvaddstr(i+1, 0, buffer);
}
} else {
printf("No records!");
}
getch();
return 0;
}
int exitGame(){
endwin();
exit(0);
}
Game *build_game() {
int x_dim = fetch_dim_until_valid("Please insert x dimension:\n");
int y_dim = fetch_dim_until_valid("Please insert y dimension:\n");
int bomb_count = fetch_dim_until_valid("Please type in how many bombs you want:\n");
return start_game(x_dim, y_dim, bomb_count);
}
int fetch_dim_until_valid(const char *message) {
int arg = 0;
char* fetched = NULL;
do {
fetched = readline(message);
arg = atoi(fetched);
free(fetched);
} while(arg <= 0);
return arg;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment