#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//gteet the user
void greetintmessage(void);

//state the rules of playing the game
void rules(void);

//ask the user to select level
int levelchoosing(void);

//verify the correctness of input(length and range)
int verifyinput(void);

//Put content of cell filled with 0 to be a space
void initboard(void);

//print out the game board 
void printboard(void);

//fill in some numbers as tips for user by open a sudoku file
int generatecontent(int);

//verify the correctness of option choenn(length and range)
int verifyoption(void);

//accept input from user and modify the array accorgingly
//also it checks wether the number is allowed to place at the cell or not
void acceptinput(void);

//enter row and check allowance
int enterrow(void);

//enter column and check allowance
int entercolumn(void);

//give hints to user when requested
void givehint(int);

//delete inputed number before
void deletenumber(int);

//check whether the user has finished the game
//by testing wether all the blankets are filled with number
//return '1' when all the cell is filled
//'o' when not yet finished
int checkgameend(void);

//check if the numbers in each row are unique and digits 1-9 are present 
//after the user had finished the game
int checkrow(void);

//compare the elements in the same row to check uniqueness
//used inside int checkrow
int comparerow(int,int a);

//check if the numbers in each column are unique and digits 1-9 are present
//after the user had finished the game
int checkcolumn(void);

//compare the elements in the same column to check uniqueness
//used inside int checkcolumn
int comparecolumn(int,int a);

//print out the correct solution if the user'solution is not correct
void printsolution(int);

//congratulation message to the user if solution is correct
void congratulation(void);

//ask wether the user want to play another game
int playothergame(void);

//array used to store value of the game
int gameboard[9][9];

//The following is the main part of this program
main()
{
        int level,option;//variable for receive levelchoosing
        int randnum;//variable for receive random number from generatecontent
        int crow,ccol;//variables for receive results from checkrow and checkcolumn
        
        greetintmessage();
        rules();
        do{    
            level = levelchoosing();
            initboard();
            printf("=================================================================\n\n");
            randnum = generatecontent(level);
            do{         
                printboard();
                printf("1.Enter number\n2.Give hints to current board\n3.Delete input before\n4.Generate new board\n5.Solution to current board\n");
                printf("Your choice: ");
                option = verifyoption();
                if(option == '1')
                    {
                        printf("\nPlease choose the grid you want and input number.");
                        acceptinput();
                        system("CLS");
                    }
                else if(option == '2')
                    {
                        givehint(randnum);
                    }
                else if(option == '3')
                    {
                        printf("\nPlease choose the grid you want to delete:");
                        deletenumber(randnum);
                    }
                else if(option == '4')
                    {
                        randnum = generatecontent(level);
                        system("CLS");
                    }
                else
                    {
                        printf("\nCorrect solution is:\n");
                        printsolution(randnum);       
                    }
            }while(checkgameend() != 1);     
            
            if(option != '5'){
                //after the user have completed the sudoku
                printf("Great!You have completed the sudoku!\n");
                printf("Let's check the answers now........\n\n");
                //check solution
                printboard();
                crow = checkrow();
                ccol = checkcolumn();
                if(crow == 1 && ccol == 1)
                    {
                        congratulation();
                    }
                else
                    {
                        printf("\nSorry,your solution is not correct.\n");
                        printf("The correct solution should be: \n");
                        printsolution(randnum);
                    }
            }
        }while(playothergame() == 1);
}

/*The following is the detail part of all funtions*/
/*gteet the user*/
void greetintmessage()
{
    printf("\n+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
    printf("%18cWelcome to play S-U-D-O-K-U game!\n",' ');
    printf("+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n");
    printf("\n");
}

/*state the rules of playing the game*/
void rules()
{   
    printf("%32cRules :\n",' ');
    printf("\n%5cFill in all the cells so that every column, row and 3 x 3\n",' '); 
    printf("%5cboxes contains each of the digits 1 to 9 without repetition.\n",' ');
}

/*ask the user to select level*/
int levelchoosing()
{
    char input[10];
    printf("\n=================================================================\n");
    printf("Please choose the level you want( 1-easy  2-medium  3-hard ) : ");
    do{
        scanf("%s",input);
        if ((strlen(input) != 1) || !( (input[0]<'4') && (input[0]>'0') ))
            {
                printf("Input out of range!Input again please: ");
            }
    } while ((strlen(input) != 1) || !( (input[0]<'4') && (input[0]>'0') ));
    
    printf("You have choose level %d\n",input[0]-48);
    printf("Game start!\nChoose the following options please.\n");
    
    return input[0];
}

/*verify the correctness of input(length and range)*/
int verifyinput()
{
    char input[10];
    do{
        scanf("%s",input);
        if ((strlen(input) != 1) || !( (input[0]<'2') && (input[0]>='0') ))
            {
                printf("Input out of range!Input again please: ");
            }
    } while ((strlen(input) != 1) || !( (input[0]<'2') && (input[0]>='0') ));      
    return input[0];
}

/*Put content of cell filled with 0 to be a space*/
void initboard()
{
    int i,j;
    for(i = 0;i < 9;i++){
            for(j = 0;j < 9;j++){
                        gameboard[i][j] = ' ';
                    }//for i
             }//for j
}

/*print out the game board */
void printboard()
{
        char space = ' ';
        char separator[] = "+- - - -+- - - -+- - - -+";
        char row = 'a';
        int i, j;
    
        printf("%20c  1 2 3   4 5 6   7 8 9\n",space);
        for (i=0;i<9;i++)
            {
   		        if(i%3 ==0)
                    {   
                        printf("%20c%s\n",space,separator);
                    }
                printf("%18c%c | %c %c %c | %c %c %c | %c %c %c |\n",space,row+i,gameboard[i][0],gameboard[i][1],gameboard[i][2],gameboard[i][3],gameboard[i][4],gameboard[i][5],gameboard[i][6],gameboard[i][7],gameboard[i][8]);
            }
        printf("%20c%s\n",space,separator);
}

/*fill in some numbers by open a sudoku file*/
int generatecontent(level)
{
    int i,j,randnum;
    char readchar,filename[20],string[10] = ".txt";
    FILE *fp;
    srand(time(NULL));
    //randomly genereta a game for users according to their request level
    if(level == '1')
         {
            randnum = (rand() %10) + 1;
            sprintf(filename,"%d%s",randnum,string);//group number and string together
         }
    else if(level == '2')
         {    
            randnum = (rand() %10) + 11;
            sprintf(filename,"%d%s",randnum,string);
         }
    else if(level == '3')
         {    
            randnum = (rand() %10) + 21;
            sprintf(filename,"%d%s",randnum,string);
         }
    //open file
    fp=fopen(filename,"r");
    if(fp==NULL)
        {
            printf("cannot open the file!\n");//when failed to open file
            exit(1);
        }
    //read character from the file
    readchar = fgetc(fp);
    while(readchar != EOF) {
        for(i=0;i<9;i++)
            {
               for(j=0;j<=9;j++)
                    {
                        gameboard[i][j] = readchar;
                        readchar = fgetc(fp);
                    }//for i
            }//for j
    }//for while loop
    fclose(fp);
    
    return randnum;
}

/*verify the correctness of option chosen(length and range)*/
int verifyoption(void)
{
    char option[10];
    do{
        scanf("%s",option);
        if ((strlen(option) != 1) || !( (option[0]<'6') && (option[0]>'0') ))
            {
                printf("Input out of range!Input again please: ");
            }
    }while((strlen(option) != 1) || !( (option[0]<'6') && (option[0]>'0') ));    
    return option[0];
}

//accept input from user and modify the array accorgingly
//accept input from user and modify the array accorgingly 
//it checks wether the number is allowed to place at the cell or not*/
void acceptinput()
{
    int i , j,row, col, number;
    char input[20];
    int count1 = 0,count2 = 0; 
    int startingrow,startingcol;
    
    //repeatly ask to do input if the cell being chosen is occupied
    do{
        //ask to enter column
        col = entercolumn() - 49;                
        //ask to enter row
        row = enterrow() - 97;
        //check wether the cell chosen is already filled or not
        //if yes,print warning message
        //if not,fill the cell with number assigned by user
        if (gameboard[row][col] !='.')
            {
                printf("The cell is already occupied!\n");
                printf("Input again please.");
            }
    }while(gameboard[row][col] !='.');
    //ask to enter number
    printf("Which number(1-9)do you want to type in? ");
    do {
        scanf("%s",input);
        if ((strlen(input) != 1) || !( (input[0]<='9') && (input[0]>'0') ))
            {
                printf("Input out of range! Input again please: ");
            }
    } while ((strlen(input) != 1) || !( (input[0]<='9') && (input[0]>'0') ));
    number = input[0];
    //checks wether the number is allowed to place at the cell or not
    //check row and cloumn
    //by testing wether the same number is presented
    for(i = 0;i < 9;i++)
        {
            if(gameboard[row][i] == number)
                {
                    count1++;
                }
            if(gameboard[i][col] == number)
                {
                    count1++;
                }
        }
    //check 3x3 boxes
    //check by dividing the game board into 9 small boxes
    //after detecting which small box the chosen grid lying on
    //it test wether same number is presented in other grids within the same box
    if(row < 3)
        {
            startingrow = 0;
        }
    else if((row > 2) && (row < 6))
        {
            startingrow = 3;
        }
    else if((row > 5) && (row < 9))
        {
            startingrow = 6;
        } 
    if(col < 3)
        {
            startingcol = 0;
        }
    else if((col > 2) && (col < 6))
        {
            startingcol = 3;
        }
    else if((col > 5) && (col < 9))
        {
            startingcol = 6;
        }
    for(i = 0;i < 3;i++)
        {
            for(j = 0;j < 3;j++)
                {
                    if(gameboard[startingrow+i][startingcol+j] == number)
                        {   
                            count2++;
                        }
                }
        }
    //assign value to the cell
    if((count1 == 0) && (count2 == 0))
        {
            gameboard[row][col] = number;
        }
    else
        {
            printf("=================================================================\n");
            printf("Sorry,input number is repeated either in row,column or 3x3 box\n");
            printf("Do you really want to input(1-yes 0-no)? ");
            input[0] = verifyinput();
            if(input[0] == '1' )
                {
                    gameboard[row][col] = number;
                }
        }
    //restore value of two counter
    count1 = 0;
    count2 = 0;
}

//enter row and check allowance
int enterrow(void)
{
    char input[10];
    printf("Which row do you want to choose(e.g.a)? ");
                do {
                    scanf("%s",input);
                    if ((strlen(input) != 1) || !( (input[0]<'j') && (input[0]>='a') ))
                        {
                            printf("Input out of range! Input again please: ");
                        }
                } while ((strlen(input) != 1) || !( (input[0]<'j') && (input[0]>='a') ));  
    return input[0];
}

//enter column and check allowance
int entercolumn(void)
{
    char input[10];
    printf("\nWhich column do you want to choose(e.g.1)? ");
                do {
                    scanf("%s",input);
                    if ((strlen(input) != 1) || !( (input[0]<='9') && (input[0]>'0') ))
                        {
                            printf("Input out of range! Input again please: ");
                        }
                } while ((strlen(input) != 1) || !( (input[0]<='9') && (input[0]>'0') ));    
    return input[0];
}

//give hints to user when requested
void givehint(randnum)
{
    int i,j,row,col;
    char space = ' ';
    char readchar,filename[20],string[10] = "s.txt";
    FILE *fp;
    //ask to enter column
    col = entercolumn() - 49;                
    //ask to enter row
    row = enterrow() - 97;
    sprintf(filename,"%d%s",randnum,string);
    fp=fopen(filename,"r");
    if(fp==NULL)
        {
            printf("cannot open the file!\n");
            exit(1);
        }
    readchar = fgetc(fp);
    while(readchar != EOF) {
        for(i=0;i<9;i++)
            {
               for(j=0;j<=9;j++)
                    {
                        if(i ==row && j == col)
                             {
                                   if(gameboard[row][col] == '.')
                                        {
                                             gameboard[i][j] = readchar;
                                             printf("=================================================================\n");
                                        }
                                   else 
                                        {
                                             printf("=================================================================\n");
                                             printf("%23c####################\n",space);
                                             printf("%23cNumber is presented!\n",space);
                                             printf("%23c####################\n",space);
                                        } 
                             }
                        readchar = fgetc(fp);
                    }//for i
            }//for j
    }//for while loop
    fclose(fp);       
}

//delete inputed number before
void deletenumber(randnum)
{
    int i,j,row,col;
    char space = ' ';
    char readchar,filename[20],string[10] = ".txt";
    FILE *fp;
    
    //ask to enter column
    col = entercolumn() - 49;                
    //ask to enter row
    row = enterrow() - 97;
    sprintf(filename,"%d%s",randnum,string);
    fp=fopen(filename,"r");
    if(fp==NULL)
        {
            printf("cannot open the file!\n");
            exit(1);
        }
    readchar = fgetc(fp);
    while(readchar != EOF) {
        for(i=0;i<9;i++)
            {
               for(j=0;j<=9;j++)
                    {
                        if(i ==row && j == col)
                            {
                                if(readchar == '.' && gameboard[row][col] != '.')
                                    {
                                        gameboard[row][col] = '.'; 
                                        printf("=================================================================\n");
                                    }
                                else if(readchar == '.' && gameboard[row][col] == '.')
                                    {
                                        printf("=================================================================\n");
                                        printf("%21c#######################\n",space);
                                        printf("%21cNothing can be deleted!\n",space);
                                        printf("%21c#######################\n",space);
                                    }
                                else
                                    {
                                        printf("=================================================================\n");
                                        printf("%8c########################################################\n",space);
                                        printf("%8cThe number can't be cancelled.It is provided originally!\n");
                                        printf("%8c########################################################\n",space);
                                    }                                        
                            }
                        readchar = fgetc(fp);
                    }//for i
            }//for j
    }//for while loop    
    fclose(fp);
}

/*check whether the user has finished the game
by testing wether all the blankets are filled
with number*/
//return '1' when all the cell is filled
//'o' when not yet finished
int checkgameend()
{
    int i,j;
    int counter = 0;
    for(i = 0;i < 9;i++){
            for(j = 0;j < 9;j++){
                        if(gameboard[i][j] != '.'){
                            counter ++;
                        }
                    }//for i
             }//for j
   
   if(counter == 81)
        { 
            return 1;
        }
   else
        {
            return 0;
        }     
}

//check if the numbers in each row are unique and digits 1-9 are present
int checkrow(void)
{
    int i,j;
    int sum,counter1 = 0,counter2 = 0,counter3 = 0;
    for(i = 0;i < 9;i++)
        {
            sum = (gameboard[i][0]+gameboard[i][1]+gameboard[i][2]+gameboard[i][3]+gameboard[i][4]+gameboard[i][5]+gameboard[i][6]+gameboard[i][7]+gameboard[i][8])-48*9;
            if(sum == 45)
                {
                    counter1 ++;
                } 
        }
    //check uniqueness
    for(i = 0;i < 9;i++){
            for(j = 1;j < 9;j++){
            counter3 = comparerow(i,j);
            counter2 += counter3;
            counter3 = 0;
            }//for j
    }//for i  
    if((counter1 == 9) && (counter2 == 324))//The total combination in comparison is 324(36x9)
        {                                   
            return 1;
        }
    else
        {
            return 0;
        }
}

//compare the elements in the same row to check uniqueness
//used inside int checkrow
int comparerow(i,a)
{
    int j,counter = 0;
    for(j = a;j < 9;j++)
        {
            if(gameboard[i][a-1] != gameboard[i][j])
                    {
                        counter ++;
                    }      
            else
                    {
                        printf("More than one %c are found in row %d!\n",gameboard[i][a-1],i+1);
                    } 
        }
    return counter;
}

//check if the numbers in each column are unique and digits 1-9 are present
int checkcolumn(void)
{
    int i,j;
    int sum,counter1 = 0,counter2 = 0,counter3 = 0;
    for(i = 0;i < 9;i++)
        {
            sum = (gameboard[0][i]+gameboard[1][i]+gameboard[2][i]+gameboard[3][i]+gameboard[4][i]+gameboard[5][i]+gameboard[6][i]+gameboard[7][i]+gameboard[8][i])-48*9;
            if(sum == 45)
                {
                    counter1 ++;
                } 
        }
    //check uniqueness
    for(i = 0;i < 9;i++){
            for(j = 1;j < 9;j++){
            counter3 = comparecolumn(i,j);
            counter2 += counter3;
            counter3 = 0;
            }//for j
    }//for i 
    if((counter1 == 9) && (counter2 == 324))//The total combination in comparison is 324(36x9)
        {                                   
            return 1;
        }
    else
        {
            return 0;
        }
} 

//compare the elements in the same column to check uniqueness
//used inside int checkcolumn
int comparecolumn(i,a)
{
    int j,counter = 0;
    for(j = a;j < 9;j++)
                {
                    if(gameboard[a-1][i] != gameboard[j][i])
                            {
                            counter ++;
                            }
                    else
                            {
                            printf("More than one %c are found in column %d!\n",gameboard[a-1][i],i+1);
                            }
                }
    return counter;
}

/*print out the correct solution if the user'solution is not correct*/
void printsolution(randnum)
{
    
    int i,j;
    char readchar,filename[20],string[10] = "s.txt";
    FILE *fp;
    
    sprintf(filename,"%d%s",randnum,string);
    fp=fopen(filename,"r");
    if(fp==NULL)
        {
            printf("cannot open the file!\n");
            exit(1);
        }
    readchar = fgetc(fp);
    while(readchar != EOF) {
        for(i=0;i<9;i++)
            {
               for(j=0;j<=9;j++)
                    {
                        gameboard[i][j] = readchar;
                        readchar = fgetc(fp);
                    }//for i
            }//for j
    
    }//for while loop
    fclose(fp);        
    printboard();
}

/*congratulation message to the user if solution is correct*/
void congratulation()
{
    char space = ' ';
    printf("%8c+++++++++++++++++++++++++++++++++++++++++++++++++++\n",space);
    printf("%8cCONGRATULATION!!You have done the sudoku correctly!\n",space);
    printf("%8c+++++++++++++++++++++++++++++++++++++++++++++++++++\n",space);
}

/*ask wether the user want to play another game*/
int playothergame()
{
    char input[10];
    printf("=================================================================\n");
    printf("Do you want to play another game(1-yes 0-no)? ");
    input[0] = verifyinput();
    if(input[0] == '1')
        {
            return 1;
        }
    else if(input[0] == '0')
        {
            return 0;
        }          
}

