#include "Lib.h"

#define MAT_SIZE 12
#define SIGN_UNCOVER '.'
#define ASCII_SPACE ' '
#define ASCII_ZERO '0'
#define STOP_GAME 999

//---------------------------------------------------------------------------------------
//                                InputString
//                                -----------
//
// General      : Input string from user.
//
// Parameters   :  
//          ptr_str - The pointer to save the string from user (char *).
//          size    - Amount of char to inputs from user (unsigned int).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void InputString(char * ptr_str, unsigned int size)
{
    fgets(ptr_str, size, stdin);
}

//---------------------------------------------------------------------------------------
//                                StringToValue
//                                -------------
//
// General      : Convert string to value like "12" to 12
//
// Parameters   :  
//          ptr_start_string - pointer of strat string (char *).
//          ptr_end_string   - pointer of end string (char *).
//
// Return value : The value (int).
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
unsigned int StringToValue(char * ptr_start_string, char * ptr_end_string)
{
    unsigned int value = ZERO;
    while (ptr_start_string < ptr_end_string)
    {
        value *= TEN;
        value += *ptr_start_string - ASCII_ZERO;
        ptr_start_string++;
    }
    
    return (value);
}

//---------------------------------------------------------------------------------------
//                                CheckLocationMatrix
//                                -------------------
//
// General      : Tests how many bombs are located one square away from the desired spot.
//
// Parameters   :  
//          loc_x        - Position on X axis (unsigned short).
//          lox_y        - Position on Y axis (unsigned short).
//          row_count    - Amount of matrix rows (unsigned short).
//          col_count    - Amount of matrix column (unsigned short).
//          ptr_bomb_vec - A string with all the locations of the mines (char *).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
short CheckLocationMatrix(unsigned short loc_x, unsigned short loc_y, unsigned int row_count, unsigned int col_count, char * ptr_bomb_vec)
{
    unsigned short bomb_x;
    unsigned short bomb_y;
    short count_bombs = ZERO;
    ptr_bomb_vec++;
    while (*(ptr_bomb_vec--) && count_bombs != -ONE)
    {
        bomb_x = StringToValue(ptr_bomb_vec, PtrCharInString(ptr_bomb_vec, ASCII_SPACE));
        ptr_bomb_vec = PtrCharInString(ptr_bomb_vec, ASCII_SPACE);
        bomb_y = StringToValue(ptr_bomb_vec, PtrCharInString(ptr_bomb_vec, ASCII_SPACE));
        ptr_bomb_vec = PtrCharInString(ptr_bomb_vec, ASCII_SPACE);
        (ABS(loc_x - bomb_x) <= ONE &&
            ABS(loc_y - bomb_y) <= ONE) ?
            count_bombs++ : ZERO;
        count_bombs = (loc_x == bomb_x && loc_y == bomb_y) ? -ONE : count_bombs;
    }
    
    return (count_bombs);
}

//---------------------------------------------------------------------------------------
//                                PrintChar
//                                ---------
//
// General      :  print char.
//
// Parameters   :  
//          c - pointer of char (char *).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void PrintChar(char * c)
{
    printf("%c", *c);
}

//---------------------------------------------------------------------------------------
//                                PrintMatrix
//                                -----------
//
// General      : Print matrix.
//
// Parameters   :  
//          ptr_mat - pointer of matrix (void *).
//          col     - Amount of matrix column (unsigned short).
//          row     - Amount of matrix rows (unsigned short).
//          print   - a function that print the type of matrix (void (void *)).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void PrintMatrix(void * ptr_mat, unsigned short col, unsigned short row, void print(void *))
{
    unsigned int length = col * row;
    unsigned int counter;
    for (counter = ZERO; counter < length; counter++)
    {
        (!(counter % col)) ? printf("\n") : ZERO;
        print(ptr_mat++);
        printf(" ");
    }
    printf("\n");
}

//---------------------------------------------------------------------------------------
//                                CopyChar
//                                --------
//
// General      : Copies the content from one character pointer to another character
//                pointer.
//
// Parameters   :  
//          ch   - pointer of char (char *).
//          copy - pointer of char with to save content of ch (char *).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void CopyChar(char * ch, char * copy)
{
    *copy = *ch;
}

//---------------------------------------------------------------------------------------
//                                ResetMatrix
//                                -----------
//
// General      : Initializes the matrix.
//
// Parameters   :  
//          ptr_mat - pointer of matrix (void *).
//          col     - Amount of matrix column (unsigned short).
//          row     - Amount of matrix rows (unsigned short).
//          type    - what to put in all the organs in the matrix (void *).
//          insert  - a function that copies from one pointer to another 
//                      pointer (void (void *, void *)).
//
// Return value : None.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void ResetMatrix(void * ptr_mat, unsigned short col, unsigned short row, void * type, void insert(void *, void *))
{
    unsigned int length = col * row;
    unsigned int counter;
    for (counter = ZERO; counter < length; counter++)
    {
        insert(type, ptr_mat++);
    }
}

//---------------------------------------------------------------------------------------
//                                      Minesweeper
//                                      -----------
//
// General : Minesweeper is a single-player puzzle computer game. The objective of the
//           game is to clear a rectangular board containing hidden "mines" or bombs
//           without detonating any of them, with help from clues about the number
//           of neighboring mines in each field.
//
// Input   : Strings of the points where the mines are. And throughout the game 
//           guessing points (X, Y).
//
// Process : The program initially receives a string of mines locations, then it receives
//           point X and Y, and it checks how many mines around the point or if the point
//           is at all a mine, if the player is able to discover all the points, he is a
//           winner and if he discovers a mine before then He loses.
//
// Output  : If the player is win or lose.
//
//---------------------------------------------------------------------------------------
// Programmer : Cohen Idan
// Student No : 211675038
// Date       : 30.12.2019
//---------------------------------------------------------------------------------------
void main(void)
{
    char mat[MAT_SIZE][MAT_SIZE];
    string bombs_string;
    unsigned short place_without_bombs;
    short count_bombs = ZERO;
    char sign_uncover = SIGN_UNCOVER;
    unsigned short x_point;
    unsigned short y_point;

    ResetMatrix(mat, MAT_SIZE, MAT_SIZE, &sign_uncover, CopyChar);

    // Example for input "1 1 2 1 3 3 "
    printf("Enter bombs (\"x y \"): ");
    InputString(bombs_string, MAX_SIZE_STRING);
    place_without_bombs = (MAT_SIZE * MAT_SIZE) - (StringLenght(bombs_string)) / FOUR;
    while (place_without_bombs-- && count_bombs != -ONE)
    {
        printf("Enter X point: ");
        scanf("%hu", &x_point);
        printf("Enter Y point: ");
        scanf("%hu", &y_point);
        if (y_point == STOP_GAME)
        {
            count_bombs = -ONE;
        }
        // if the point is uncover
        else if (mat[y_point][x_point] != SIGN_UNCOVER)
        {
            count_bombs = CheckLocationMatrix(x_point, y_point, MAT_SIZE, MAT_SIZE, bombs_string);
            mat[y_point][x_point] = count_bombs + ASCII_ZERO;
            PrintMatrix(mat, MAT_SIZE, MAT_SIZE, PrintChar);
        }
        else
        {
            printf("You was enter this point in past!\n");
        }
        
    }
    if (!place_without_bombs)
    {
        printf("You won!\n");
    }
    else
    {
        printf("You lose!\n");
    }
}