uni

University stuff
git clone git://git.christosmarg.xyz/uni-assignments.git
Log | Files | Refs | README | LICENSE

commit 295be380a13d62923b87d52c96429e07af7e0630
parent c72a977ac3ef5bb40c43398b0b1b11bb0746f540
Author: Christos Margiolis <christos@margiolis.net>
Date:   Wed, 18 Mar 2020 03:01:43 +0200

updated submodule

Diffstat:
M.gitmodules | 6+++---
Aassignment-1.5-arrays-pointers-files/minecurses/Makefile | 36++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/README.md | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/audio/detective-8bit.wav | 0
Aassignment-1.5-arrays-pointers-files/minecurses/bin/minesweeper | 0
Aassignment-1.5-arrays-pointers-files/minecurses/include/audio.h | 15+++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/gameplay.h | 16++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/minesweeper.h | 47+++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/navigation.h | 15+++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/outputs.h | 18++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/settings.h | 16++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/include/wins.h | 12++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/obj/audio.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/gameplay.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/main.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/minesweeper.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/navigation.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/outputs.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/settings.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/obj/wins.o | 0
Aassignment-1.5-arrays-pointers-files/minecurses/src/audio.c | 38++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/gameplay.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/main.c | 30++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/minesweeper.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/navigation.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/outputs.c | 143+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/settings.c | 49+++++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/src/wins.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/txt/mnsout.txt | 9+++++++++
Aassignment-1.5-arrays-pointers-files/minecurses/txt/scorelog.txt | 9+++++++++
Dassignment-1.5-arrays-pointers-files/ncurses-minesweeper | 1-
31 files changed, 838 insertions(+), 4 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -1,3 +1,3 @@ -[submodule "assignment-1.5-arrays-pointers-files/ncurses-minesweeper"] - path = assignment-1.5-arrays-pointers-files/ncurses-minesweeper - url = https://github.com/christosmarg/ncurses-minesweeper +[submodule "assignment-1.5-arrays-pointers-files/minecurses"] + path = assignment-1.5-arrays-pointers-files/minecurses + url = https://github.com/christosmarg/minecurses diff --git a/assignment-1.5-arrays-pointers-files/minecurses/Makefile b/assignment-1.5-arrays-pointers-files/minecurses/Makefile @@ -0,0 +1,36 @@ +TARGET = minecurses + +SRC_DIR = src +OBJ_DIR = obj +BIN_DIR = bin + +SRC = $(wildcard $(SRC_DIR)/*.c) +OBJ = $(SRC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o) + +CC = gcc +CPPFLAGS += -Iinclude +CFLAGS += -Wall +LDFLAGS += -Llib +LDLIBS += -lm -lncurses -lSDL2 -lSDL2_mixer -pthread + +MOVE = mv +MKDIR_P = mkdir -p + +.PHONY: all clean + +all: $(TARGET) + +$(TARGET): $(OBJ) + $(MKDIR_P) $(BIN_DIR) + $(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@ + $(MOVE) $(TARGET) $(BIN_DIR) + +$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c + $(MKDIR_P) $(OBJ_DIR) + $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +run: + ./$(BIN_DIR)/$(TARGET) + +clean: + $(RM) $(OBJ) $(BIN_DIR)/$(TARGET) diff --git a/assignment-1.5-arrays-pointers-files/minecurses/README.md b/assignment-1.5-arrays-pointers-files/minecurses/README.md @@ -0,0 +1,56 @@ +# minescurses + +A simplistic minesweeper game using the `ncurses` and `SDL2` libraries. The game was originally made as a university assignment of mine, but I decided to take it a bit further afterwards. + +## How to play + +* Enter number of columns +* Enter number of rows +* Enter number of mines +* Move with `w`/`s`/`a`/`d` or Vim keys (`k`/`j`/`h`/`l`) +* Open cell with `[ENTER]`, or `o` +* Flag cell with `f` +* Defuse mine (only if flagged) with `g` +* You win if you defuse all the mines +* You lose in case you open a mine or you try to defuse a flagged cell not containing a mine + +Additional controls + +* `p`: Pause audio +* `+`: Volume up +* `-`: Volume down +* `q`: Quit + +## To Do + +* Handle resizing +* Add restart option +* Add quit option right when game opens +* Load score log to ui +* Improve score log +* Add macros for the scaled board dimensions +* Add colors +* Fix curs_set +* Add echo during setup +* Add unicode support + +## Execution + +### Linux / Unix / macOS + +**Dependencies** +* `make` +* `ncurses` +* `SDL2` +* `SDL2_mixer` + +```shell +$ cd path_to/minesweeper +$ make +$ make run +$ make clean # optional +``` + +## Preview + +![MinesweeperScr](https://user-images.githubusercontent.com/54286563/73931645-4d4db080-48e1-11ea-981b-e9b028d34c41.png) diff --git a/assignment-1.5-arrays-pointers-files/minecurses/audio/detective-8bit.wav b/assignment-1.5-arrays-pointers-files/minecurses/audio/detective-8bit.wav Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/bin/minesweeper b/assignment-1.5-arrays-pointers-files/minecurses/bin/minesweeper Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/audio.h b/assignment-1.5-arrays-pointers-files/minecurses/include/audio.h @@ -0,0 +1,14 @@ +#ifndef AUDIO_H +#define AUDIO_H + +#include <SDL2/SDL.h> +#include <SDL2/SDL_mixer.h> +#include "minesweeper.h" + +#define AUDIO_PATH "audio/detective-8bit.wav" + +void *play_audio(void *); +void volume(char); +void pause_audio(); + +#endif+ \ No newline at end of file diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/gameplay.h b/assignment-1.5-arrays-pointers-files/minecurses/include/gameplay.h @@ -0,0 +1,16 @@ +#ifndef GAMEPLAY_H +#define GAMEPLAY_H + +#include "minesweeper.h" + +void play_minesweeper(struct _win_st*, char **, char **, int, int, int); +bool open_cell(struct _win_st*, char **, char **, int, int, bool); +void handle_flags(struct _win_st*, char **, char **, int, int); +void defuse_mine(struct _win_st*, char **, char **, int, int); +void transfer(char **, char **, int, int); +void reveal(struct _win_st*, char **, int, int, int, int); +bool is_defused(char **, char **, int, int); +void handle_gameover(struct _win_st*, char **, int, int, int, int, int, int); +void handle_win(struct _win_st*, char **, int, int, int, int, int, int, int); + +#endif diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/minesweeper.h b/assignment-1.5-arrays-pointers-files/minecurses/include/minesweeper.h @@ -0,0 +1,47 @@ +#ifndef MINESWEEPER_H +#define MINESWEEPER_H + +#if defined linux || defined __unix__ || defined __APPLE__ +#include <ncurses.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "settings.h" +#include "gameplay.h" +#include "navigation.h" +#include "outputs.h" +#include "wins.h" +#include "audio.h" + +#define BLANK ' ' +#define MINE '*' +#define CLEAR " " +#define ENTER '\n' +#define OPEN_LOWER 'o' +#define OPEN_UPPER 'O' +#define FLAG 'F' +#define FLAG_LOWER 'f' +#define FLAG_UPPER 'F' +#define DEFUSE_LOWER 'g' +#define DEFUSE_UPPER 'G' +#define DEFUSED 'D' +#define PAUSE_AUDIO 'p' +#define VOLUME_UP '+' +#define VOLUME_DOWN '-' +#define QUIT 'q' + +char **init_dispboard(struct _win_st*, int, int); +void fill_dispboard(char **, int, int); +char **init_mineboard(struct _win_st*, int, int, int); + +void place_mines(char **, int, int, int); +void add_adj(char **, int, int); +bool is_mine(char **, int, int); +bool outof_bounds(int, int, int, int); +int8_t adj_mines(char **, int, int, int, int); +void fill_spaces(char **, int, int, int); + +#endif diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/navigation.h b/assignment-1.5-arrays-pointers-files/minecurses/include/navigation.h @@ -0,0 +1,14 @@ +#ifndef NAVIGATION_H +#define NAVIGATION_H + +#include "minesweeper.h" + +void navigate(struct _win_st*, char **, char *, int *, int *); +void getmv(struct _win_st*, char *, int *, int *, int, int); +void mvup(int *); +void mvdown(int *, int); +void mvleft(int *); +void mvright(int *, int); +void update_curs(struct _win_st*, int, int); + +#endif+ \ No newline at end of file diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/outputs.h b/assignment-1.5-arrays-pointers-files/minecurses/include/outputs.h @@ -0,0 +1,18 @@ +#ifndef OUTPUTS_H +#define OUTPUTS_H + +#include "minesweeper.h" + +#define SESSION_PATH "txt/mnsout.txt" +#define SCORE_LOG_PATH "txt/scorelog.txt" + +void print_grid(struct _win_st*, int, int); +void print_board(struct _win_st*, char **, int, int); +void game_won(struct _win_st*, int, int); +void game_over(struct _win_st*, char **, int, int); +void session_write(char **, int, int, int, int, const char *); +void score_write(int, int, int); +char *get_pname(); +void sort_scorelog(FILE *); + +#endif diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/settings.h b/assignment-1.5-arrays-pointers-files/minecurses/include/settings.h @@ -0,0 +1,15 @@ +#ifndef SETTINGS_H +#define SETTINGS_H + +#include "minesweeper.h" + +#define COLS_CHAR_LENGTH strlen("Columns (Min = 5, Max = XXX): ") + 1 +#define ROWS_CHAR_LENGTH strlen("Rows (Min = 5, Max = YYY): ") + 1 +#define NMINES_CHAR_LENGTH strlen("Mines (Max = MMM): ") + 1 + +int set_cols(struct _win_st*, int); +int set_rows(struct _win_st*, int); +int set_nmines(struct _win_st*, int); +void init_colors(); + +#endif+ \ No newline at end of file diff --git a/assignment-1.5-arrays-pointers-files/minecurses/include/wins.h b/assignment-1.5-arrays-pointers-files/minecurses/include/wins.h @@ -0,0 +1,12 @@ +#ifndef WINS_H +#define WINS_H + +#include "minesweeper.h" + +void main_win(); +WINDOW *menu_win(int *, int *); +WINDOW *game_win(int, int, int); +void options_menu(); +void options_win(); + +#endif diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/audio.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/audio.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/gameplay.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/gameplay.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/main.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/main.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/minesweeper.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/minesweeper.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/navigation.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/navigation.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/outputs.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/outputs.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/settings.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/settings.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/obj/wins.o b/assignment-1.5-arrays-pointers-files/minecurses/obj/wins.o Binary files differ. diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/audio.c b/assignment-1.5-arrays-pointers-files/minecurses/src/audio.c @@ -0,0 +1,38 @@ +#include "audio.h" + +void *play_audio(void *threadID) +{ + int tID = (long)threadID; + Mix_Music *music = NULL; + SDL_Init(SDL_INIT_AUDIO); + Mix_OpenAudio(44100, MIX_DEFAULT_FORMAT, 1, 4096); + music = Mix_LoadMUS(AUDIO_PATH); + + Mix_PlayMusic(music, -1); + while (Mix_PlayingMusic()) ; + Mix_FreeMusic(music); + Mix_CloseAudio(); +} + +void volume(char option) +{ + static int volume = MIX_MAX_VOLUME; + + switch (option) + { + case '+': + if (volume == MIX_MAX_VOLUME) break; + else Mix_VolumeMusic(volume += 10); + break; + case '-': + if (volume == 0) break; + else Mix_VolumeMusic(volume -= 10); + break; + } +} + +void pause_audio() +{ + if(Mix_PausedMusic() == 1) Mix_ResumeMusic(); + else Mix_PauseMusic(); +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/gameplay.c b/assignment-1.5-arrays-pointers-files/minecurses/src/gameplay.c @@ -0,0 +1,100 @@ +#include "gameplay.h" + +void play_minesweeper(WINDOW *gameWin, char **dispboard, char **mineboard, int COLS, int ROWS, int NMINES) +{ + int mbx = 0, mby = 0; + bool gameOver = false; + int numDefused = 0; + int yMax, xMax, yMiddle, xMiddle; + char move; + getmaxyx(stdscr, yMax, xMax); + yMiddle = yMax/2; + xMiddle = xMax/2; + + print_board(gameWin, dispboard, COLS, ROWS); + + do + { + navigate(gameWin, dispboard, &move, &mbx, &mby); + + if (move == ENTER || move == OPEN_LOWER || move == OPEN_UPPER) // handle cell opening + gameOver = open_cell(gameWin, dispboard, mineboard, mby, mbx, gameOver); + else if (move == FLAG_LOWER || move == FLAG_UPPER) // handle falgs + handle_flags(gameWin, dispboard, mineboard, mby, mbx); + else if (move == DEFUSE_LOWER || move == DEFUSE_UPPER) // check for defuse + { + if (dispboard[mby][mbx] == FLAG && mineboard[mby][mbx] == MINE) + { + numDefused++; + defuse_mine(gameWin, dispboard, mineboard, mby, mbx); + } + else if (dispboard[mby][mbx] == FLAG && mineboard[mby][mbx] != MINE) gameOver = true; + } + else if (move == PAUSE_AUDIO) pause_audio(); // handle audio + else if (move == VOLUME_UP || move == VOLUME_DOWN) volume(move); + + mvprintw(1, xMiddle-8, "Defused mines: %d/%d", numDefused, NMINES); + + } while (((mby >= 0 && mby < ROWS) && (mbx >= 0 && mbx < COLS)) && + numDefused < NMINES && !gameOver && move != QUIT); + + if (gameOver == true) + handle_gameover(gameWin, mineboard, yMiddle, xMiddle, COLS, ROWS, mby, mbx); + if (numDefused == NMINES) + handle_win(gameWin, mineboard, yMiddle, xMiddle, COLS, ROWS, mby, mbx, numDefused); +} + +bool open_cell(WINDOW *gameWin, char **dispboard, char **mineboard, int mby, int mbx, bool gameOver) +{ + transfer(dispboard, mineboard, mby, mbx); + reveal(gameWin, dispboard, mby, mbx, mby+1, 3*mbx+2); + if (dispboard[mby][mbx] == MINE) gameOver = true; + return gameOver; +} + +void handle_flags(WINDOW *gameWin, char **dispboard, char **mineboard, int mby, int mbx) +{ + if (dispboard[mby][mbx] == FLAG) dispboard[mby][mbx] = BLANK; // undo flag + else if (dispboard[mby][mbx] != FLAG && dispboard[mby][mbx] != BLANK) return; // dont flag an already opened mine + else dispboard[mby][mbx] = FLAG; // flag if not flagged already + reveal(gameWin, dispboard, mby, mbx, mby+1, 3*mbx+2); +} + +void defuse_mine(WINDOW *gameWin, char **dispboard, char **mineboard, int mby, int mbx) +{ + refresh(); + dispboard[mby][mbx] = mineboard[mby][mbx] = DEFUSED; + reveal(gameWin, dispboard, mby, mbx, mby+1, 3*mbx+2); +} + +void transfer(char **dispboard, char **mineboard, int mby, int mbx) +{ + dispboard[mby][mbx] = mineboard[mby][mbx]; +} + +void reveal(WINDOW *gameWin, char **dispboard, int mby, int mbx, int yLoc, int xLoc) +{ + mvwaddch(gameWin, yLoc, xLoc, dispboard[mby][mbx]); + wrefresh(gameWin); +} + +bool is_defused(char **dispboard, char **mineboard, int mby, int mbx) +{ + return ((dispboard[mby][mbx] == DEFUSED)) ? true : false; +} + +void handle_gameover(WINDOW *gameWin, char **mineboard, int yMiddle, int xMiddle, int COLS, int ROWS, int mby, int mbx) +{ + game_over(gameWin, mineboard, yMiddle, xMiddle); + getchar(); + print_board(gameWin, mineboard, COLS, ROWS); + session_write(mineboard, COLS, ROWS, mbx, mby, "lost"); +} + +void handle_win(WINDOW *gameWin, char **mineboard, int yMiddle, int xMiddle, int COLS, int ROWS, int mby, int mbx, int numDefused) +{ + game_won(gameWin, yMiddle, xMiddle); + getchar(); + session_write(mineboard, COLS, ROWS, mbx, mby, "won"); + score_write(numDefused, COLS, ROWS); +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/main.c b/assignment-1.5-arrays-pointers-files/minecurses/src/main.c @@ -0,0 +1,30 @@ +#include "minesweeper.h" +#include <pthread.h> + +int main(int argc, char **argv) +{ + main_win(); + options_menu(); + + int yMax, xMax; + WINDOW *menuWin = menu_win(&yMax, &xMax); + int COLS = set_cols(menuWin, xMax); + int ROWS = set_rows(menuWin, yMax); + int NMINES = set_nmines(menuWin, COLS*ROWS); + + WINDOW *gameWin = game_win(COLS, ROWS, NMINES); + char **dispboard = init_dispboard(gameWin, COLS, ROWS); + char **mineboard = init_mineboard(gameWin, COLS, ROWS, NMINES); + + pthread_t audioThread; + long threadID = 1; + pthread_create(&audioThread, NULL, play_audio, (void *)threadID); + play_minesweeper(gameWin, dispboard, mineboard, COLS, ROWS, NMINES); + + pthread_cancel(audioThread); + free(dispboard); + free(mineboard); + endwin(); + + return 0; +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/minesweeper.c b/assignment-1.5-arrays-pointers-files/minecurses/src/minesweeper.c @@ -0,0 +1,111 @@ +#include "minesweeper.h" + +char **init_dispboard(WINDOW *gameWin, int COLS, int ROWS) +{ + int i; + char **dispboard = (char **)malloc(ROWS * sizeof(char *)); + for (i = 0; i < ROWS; i++) + dispboard[i] = (char *)malloc(COLS); + + if (dispboard == NULL) + { + mvprintw(1, 1, "Error, not enough memory, exiting..."); + refresh(); + exit(EXIT_FAILURE); + } + else fill_dispboard(dispboard, COLS, ROWS); + + return dispboard; +} + +void fill_dispboard(char **dispboard, int COLS, int ROWS) +{ + int i, j; + + for (i = 0; i < ROWS; i++) + for (j = 0; j < COLS; j++) + dispboard[i][j] = BLANK; +} + +char **init_mineboard(WINDOW *gameWin, int COLS, int ROWS, int NMINES) +{ + int i; + char **mineboard = (char **)malloc(ROWS * sizeof(char *)); + for (i = 0; i < ROWS; i++) + mineboard[i] = (char *)malloc(COLS); + + if (mineboard == NULL) + { + mvprintw(1, 1, "Error, not enough memory, exiting..."); + refresh(); + exit(EXIT_FAILURE); + } + else + { + place_mines(mineboard, COLS, ROWS, NMINES); + add_adj(mineboard, COLS, ROWS); + fill_spaces(mineboard, COLS, ROWS, NMINES); + } + + return mineboard; +} + +void place_mines(char **mineboard, int COLS, int ROWS, int NMINES) +{ + int i, wRand, hRand; + + srand(time(NULL)); + + for (i = 0; i < NMINES; i++) + { + wRand = rand() % ROWS; + hRand = rand() % COLS; + mineboard[wRand][hRand] = MINE; + } +} + +void add_adj(char **mineboard, int COLS, int ROWS) +{ + int i, j; + + for (i = 0; i < ROWS; i++) + for (j = 0; j < COLS; j++) + if (!is_mine(mineboard, i, j)) + mineboard[i][j] = adj_mines(mineboard, i, j, COLS, ROWS) + '0'; +} + +bool is_mine(char **mineboard, int row, int col) +{ + return (mineboard[row][col] == MINE) ? true : false; +} + +bool outof_bounds(int row, int col, int COLS, int ROWS) +{ + return (row < 0 || row > ROWS-1 || col < 0 || col > COLS-1) ? true : false; +} + +int8_t adj_mines(char **mineboard, int row, int col, int COLS, int ROWS) +{ + int8_t numAdj = 0; + + if (!outof_bounds(row, col-1, COLS, ROWS) && mineboard[row][col-1] == MINE) numAdj++; // North + if (!outof_bounds(row, col+1, COLS, ROWS) && mineboard[row][col+1] == MINE) numAdj++; // South + if (!outof_bounds(row+1, col, COLS, ROWS) && mineboard[row+1][col] == MINE) numAdj++; // East + if (!outof_bounds(row-1, col, COLS, ROWS) && mineboard[row-1][col] == MINE) numAdj++; // West + if (!outof_bounds(row+1, col-1, COLS, ROWS) && mineboard[row+1][col-1] == MINE) numAdj++; // North-East + if (!outof_bounds(row-1, col-1, COLS, ROWS) && mineboard[row-1][col-1] == MINE) numAdj++; // North-West + if (!outof_bounds(row+1, col+1, COLS, ROWS) && mineboard[row+1][col+1] == MINE) numAdj++; // South-East + if (!outof_bounds(row-1, col+1, COLS, ROWS) && mineboard[row-1][col+1] == MINE) numAdj++; // South-West + + return numAdj; +} + +void fill_spaces(char **mineboard, int COLS, int ROWS, int NMINES) +{ + int i, j; + + for (i = 0; i < ROWS; i++) + for (j = 0; j < COLS; j++) + if (mineboard[i][j] != MINE && mineboard[i][j] == '0') + mineboard[i][j] = '-'; +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/navigation.c b/assignment-1.5-arrays-pointers-files/minecurses/src/navigation.c @@ -0,0 +1,68 @@ +#include "navigation.h" + +void navigate(WINDOW *gameWin, char **mineboard, char *move, int *mboardXLoc, int *mboardYLoc) +{ + int yMax, xMax; + static int yLoc = 1, xLoc = 2; + getmaxyx(gameWin, yMax, xMax); + + update_curs(gameWin, yLoc, xLoc); + *mboardXLoc = (xLoc-2)/3; + *mboardYLoc = yLoc-1; + mvprintw(1, 1, "Current position: (%d, %d) ", *mboardXLoc, *mboardYLoc); + refresh(); + getmv(gameWin, move, &yLoc, &xLoc, yMax, xMax); +} + +void getmv(WINDOW *gameWin, char *move, int *yLoc, int *xLoc, int yMax, int xMax) +{ + *move = wgetch(gameWin); + switch (*move) // vim keys support!! + { + case 'k': case 'K': + case 'w': case 'W': + mvup(yLoc); + break; + case 'j': case 'J': + case 's': case 'S': + mvdown(yLoc, yMax); + break; + case 'h': case 'H': + case 'a': case 'A': + mvleft(xLoc); + break; + case 'l': case 'L': + case 'd': case 'D': + mvright(xLoc, xMax); + break; + } +} + +void mvup(int *yLoc) +{ + (*yLoc)--; + if (*yLoc < 1) *yLoc = 1; +} + +void mvdown(int *yLoc, int yMax) +{ + (*yLoc)++; + if (*yLoc > yMax-2) *yLoc = yMax-2; +} + +void mvleft(int *xLoc) +{ + *xLoc -= 3; + if (*xLoc < 2) *xLoc = 2; +} + +void mvright(int *xLoc, int xMax) +{ + *xLoc += 3; + if (*xLoc > xMax-3) *xLoc = xMax-3; +} + +void update_curs(WINDOW *gameWin, int yLoc, int xLoc) +{ + wmove(gameWin, yLoc, xLoc); +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/outputs.c b/assignment-1.5-arrays-pointers-files/minecurses/src/outputs.c @@ -0,0 +1,143 @@ +#include "outputs.h" + +void print_board(WINDOW *gameWin, char **board, int COLS, int ROWS) +{ + int i, j, x, y = 1; + + print_grid(gameWin, ROWS, COLS); + + for (i = 0; i < ROWS; i++) + { + x = 2; + for (j = 0; j < COLS; j++) + { + wattron(gameWin, A_BOLD); + mvwaddch(gameWin, y, x, board[i][j]); + x += 3; + } + y++; + } + + wrefresh(gameWin); + wattron(gameWin, A_BOLD); +} + +void print_grid(WINDOW *gameWin, int ROWS, int COLS) +{ + int i, j; + + for (i = 1; i <= ROWS; i++) + { + wmove(gameWin, i, 1); + for (j = 0; j < COLS; j++) + wprintw(gameWin, "[ ]"); + } + + wrefresh(gameWin); +} + +void session_write(char **mineboard, int COLS, int ROWS, int hitRow, int hitCol, const char *status) +{ + int i, j; + FILE *mnsOut = fopen(SESSION_PATH, "w"); + + if (mnsOut == NULL) + { + mvprintw(1, 1, "Error opening file, exiting..."); + refresh(); + exit(EXIT_FAILURE); + } + else + { + strcmp(status, "won") + ? fprintf(mnsOut, "Mine hit at position (%d, %d)\n\n", hitRow+1, hitCol+1) + : fprintf(mnsOut, "Last mine defused at position (%d, %d)\n\n", hitRow+1, hitCol+1); + fprintf(mnsOut, "Board overview\n\n"); + + for (i = 0; i < ROWS; i++) + { + for (j = 0; j < COLS; j++) + fprintf(mnsOut, "%c ", mineboard[i][j]); + fprintf(mnsOut, "\n"); + } + + mvprintw(1, 1, "Session written to file "); + refresh(); + getchar(); + } + + fclose(mnsOut); +} + +void score_write(int numDefused, int COLS, int ROWS) +{ + FILE *scoreLog = fopen(SCORE_LOG_PATH, "a"); + char *playerName = get_pname(); + + // add titles etc + + if (scoreLog == NULL) + { + mvprintw(1, 1, "Error opening file, exiting..."); + refresh(); + exit(EXIT_FAILURE); + } + else + { + fprintf(scoreLog, "\n%s\t\t\t\t%d\t\t\t\t\t%dx%d", playerName, numDefused, COLS, ROWS); + sort_scorelog(scoreLog); // pending + mvprintw(1, 1, "New score written to score log"); + refresh(); + getchar(); + } + + fclose(scoreLog); + free(playerName); +} + +char *get_pname() +{ + char buffer[20]; + char *playerName; + + move(1, 1); + echo(); + clrtoeol(); + printw("Your name: "); + refresh(); + scanw("%s", buffer); + noecho(); + refresh(); + + playerName = (char *)malloc(strlen(buffer) + 1); + return (strcpy(playerName, buffer)); +} + +void sort_scorelog(FILE *scoreLog) +{ + +} + +void game_won(WINDOW *gameWin, int yMiddle, int xMiddle) +{ + wclear(gameWin); + wrefresh(gameWin); + wattron(stdscr, A_BOLD); + mvwprintw(stdscr, yMiddle-2, xMiddle-11, "You defused all the mines!"); + mvwprintw(stdscr, yMiddle-1, xMiddle-3, "You won :)"); + mvwprintw(stdscr, yMiddle, xMiddle-11, "Press any key to continue"); + refresh(); + wattroff(stdscr, A_BOLD); +} + +void game_over(WINDOW *gameWin, char **mineboard, int yMiddle, int xMiddle) +{ + wclear(gameWin); + wrefresh(gameWin); + wattron(stdscr, A_BOLD); + mvwprintw(stdscr, yMiddle-2, xMiddle-24, "You hit a mine! (or tried to defuse the wrong cell)"); + mvwprintw(stdscr, yMiddle-1, xMiddle-4, "Game over :("); + mvwprintw(stdscr, yMiddle, xMiddle-11, "Press any key to continue"); + refresh(); + wattroff(stdscr, A_BOLD); +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/settings.c b/assignment-1.5-arrays-pointers-files/minecurses/src/settings.c @@ -0,0 +1,49 @@ +#include "settings.h" + +int set_cols(WINDOW *menuWin, int xMax) +{ + int COLS; + + do + { + mvwprintw(menuWin, 1, 1, "Columns (Min = 5, Max = %d): ", (xMax-2)/3-2); + wrefresh(menuWin); + scanw("%d", &COLS); + mvwprintw(menuWin, 1, COLS_CHAR_LENGTH, "%d", COLS); + wrefresh(menuWin); + } while (COLS < 5 || COLS > (xMax-2)/3-2); + + return COLS; +} + +int set_rows(WINDOW *menuWin, int yMax) +{ + int ROWS; + + do + { + mvwprintw(menuWin, 2, 1, "Rows (Min = 5, Max = %d): ", yMax-14); + wrefresh(menuWin); + scanw("%d", &ROWS); + mvwprintw(menuWin, 2, ROWS_CHAR_LENGTH, "%d", ROWS); + wrefresh(menuWin); + } while (ROWS < 5 || ROWS > yMax - 14); + + return ROWS; +} + +int set_nmines(WINDOW *menuWin, int DIMENSIONS) +{ + int NMINES; + + do + { + mvwprintw(menuWin, 3, 1, "Mines (Max = %d): ", DIMENSIONS-15); // -10 so the player has a chance to win + wrefresh(menuWin); + scanw("%d", &NMINES); + mvwprintw(menuWin, 3, NMINES_CHAR_LENGTH, "%d", NMINES); + wrefresh(menuWin); + } while (NMINES < 1 || NMINES > DIMENSIONS-15); + + return NMINES; +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/src/wins.c b/assignment-1.5-arrays-pointers-files/minecurses/src/wins.c @@ -0,0 +1,47 @@ +#include "wins.h" + +void main_win() +{ + initscr(); + noecho(); + cbreak(); + + WINDOW *mainWin = newwin(0, 0, 0, 0); + wattron(mainWin, A_BOLD); + box(mainWin, 0, 0); + refresh(); + wrefresh(mainWin); + wattroff(mainWin, A_BOLD); +} + +WINDOW *menu_win(int *yMax, int *xMax) +{ + int numSettings = 3; + getmaxyx(stdscr, *yMax, *xMax); + WINDOW *menuWin = newwin(numSettings+2, *xMax-8, *yMax-8, 4); + wattron(menuWin, A_BOLD); + box(menuWin, 0, 0); + wrefresh(menuWin); + wattroff(menuWin, A_BOLD); + return menuWin; +} + +WINDOW *game_win(int COLS, int ROWS, int NMINES) +{ + int winRows = ROWS+2; + int winCols = COLS*3+2; + WINDOW *gameWin = newwin(winRows, winCols, 2, 4); + wattron(gameWin, A_BOLD); + box(gameWin, 0, 0); + wrefresh(gameWin); + wattroff(gameWin, A_BOLD); + return gameWin; +} + +void options_menu() +{ + int yMax = getmaxy(stdscr); + mvprintw(yMax-3, 5, "q Quit w/k Move up s/j Move down a/h Move Left d/l Move Right [ENTER]/o Open cell"); + mvprintw(yMax-2, 5, "f Flag cell g Defuse (if flagged only) p Pause music + Volume up - Volume down"); + refresh(); +} diff --git a/assignment-1.5-arrays-pointers-files/minecurses/txt/mnsout.txt b/assignment-1.5-arrays-pointers-files/minecurses/txt/mnsout.txt @@ -0,0 +1,9 @@ +Mine hit at position (1, 1) + +Board overview + +* 1 - - - +1 1 - - - +- - - - - +- - - - - +- - - - - diff --git a/assignment-1.5-arrays-pointers-files/minecurses/txt/scorelog.txt b/assignment-1.5-arrays-pointers-files/minecurses/txt/scorelog.txt @@ -0,0 +1,9 @@ +---------- +Score log +---------- + +------------------------------------------------------ +Player Mines Defused Dimensions +------------------------------------------------------ +christos 1 5x5 +christos 1 5x5 diff --git a/assignment-1.5-arrays-pointers-files/ncurses-minesweeper b/assignment-1.5-arrays-pointers-files/ncurses-minesweeper @@ -1 +0,0 @@ -Subproject commit c31c83368cf6f7af8ed5b24841d9dbc345edb5ba