I know it's inefficient, but I'm new at C, so I want to wrap my head around the procedure before worrying about optimizing my code. Basically I'm working on a Sudoku Solver. I have made multiple .c files for each function I intend to employ, all under the same project folder. Here's how it goes:
Setup.h - defines a nested structure. Inside the nested structure is a 9x9 array, and structures which reference each row, column, and box within that array.
typedef struct puzzle
{
int Sudoku[9][9];
int * pSudoku;
struct Rows
{
int * pRowValues[9][9];
int RowNumber[9];
} Row;
struct Columns
{
int * pColumnValues[9][9];
int ColumnNumber[9];
} Column;
struct Boxes
{
int * pBoxValues[9][9];
int BoxNumber[9];
} Box;
} Puzzle;
Setup.c - initializes the nested structure to all 0's. Creates pointers in the structure to use later.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
struct Puzzle Setup()
{
/*
*************************
First, set up the problem
*************************
*/
int NullMatrix[9][9] = {0};
int ThisIsHowCountingWorks[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(Puzzle1.Sudoku, NullMatrix, sizeof(Puzzle1.Sudoku));
memcpy(Puzzle1.Row.RowNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Row.RowNumber));
memcpy(Puzzle1.Column.ColumnNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Column.ColumnNumber));
memcpy(Puzzle1.Box.BoxNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Box.BoxNumber));
Puzzle1.pSudoku = &Puzzle1.Sudoku[0][0];
/*
************************************************
Define pointers for the values and the Structure
************************************************
*/
//Rows
for(int Set=0; Set<9; Set )
{
for(int Value=0; Value<9; Value )
{
Puzzle1.Row.pRowValues[Value][Set] = &Puzzle1.Sudoku[Value][Set];
}
}
//Columns
for(int Set=0; Set<9; Set )
{
for(int Value=0; Value<9; Value )
{
Puzzle1.Column.pColumnValues[Value][Set] = &Puzzle1.Sudoku[Set][Value];
}
}
//Boxes
for(int Set=0; Set<3; Set )
{
for(int Bump=0; Bump<3; Bump )
{
for(int Value=0; Value<9; Value )
{
if(Value<3)
{
Puzzle1.Box.pBoxValues[Value][Bump 3*Set] = &Puzzle1.Sudoku[3*Bump Value-0][0 3*Set];
}
else if(Value>=3&&Value<6)
{
Puzzle1.Box.pBoxValues[Value][Bump 3*Set] = &Puzzle1.Sudoku[3*Bump Value-3][1 3*Set];
}
else if(Value>=6)
{
Puzzle1.Box.pBoxValues[Value][Bump 3*Set] = &Puzzle1.Sudoku[3*Bump Value-6][2 3*Set];
}
}
}
}
return Puzzle1;
}
Input.c - asks the user for the given values, and assigns them to the correct place in the 9x9 array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
/*
********************************************
In this bit, we get some info from the user
and then assign that cleverly to the puzzle.
********************************************
*/
struct Puzzle Input(Puzzle Puzzle1)
{
printf(
"*************************************\n"
"Welcome to the Super Sudoku Solver!!!\n"
" I am your host, Puzzle Pat!\n"
"*************************************\n"
"\n"
"\n"
"\n"
"Before we begin, may I get your name?\n"
);
char name[50];
scanf("0s", name);
printf(
"Hello, %s!\n"
"It's good to see you!\n"
"\n"
"I would like you to enter the values\n"
"given in your Sudoku puzzle.\n"
"\n"
"Please give them to me in this format:\n"
"Row Number, Column Number, Value Number\n"
"\n"
"So for example, if there's a 3 on row 2,\n"
"column 5, you'd type in '2, 5, 3'\n\n",
name
);
char spot1[8];
scanf("[a-z | A-Z | 0-9/,.-]", spot1[8]);
int assignment[3];
assignment[0] = (int)spot1[0]-1;
assignment[1] = (int)spot1[3]-1;
assignment[2] = (int)spot1[6];
Puzzle1.Sudoku[assignment[0]][assignment[1]] = assignment[2];
printf("Great! Are there any more entries you want to record?\n");
char more;
scanf("s", more);
int loop = 0;
while(more=="Yes"||more=="yes"||more=="Y"||more||"y")
{
char Support[10][15] =
{
"Cool"
"Awesome"
"Nice"
"Alright"
"Sweet"
"Great"
"Excellent"
"Wonderful"
"Heck yeah"
"Gnarly"
};
printf("\nOkay, add the next number the same way you did the last one.\n\n");
char spot2[8];
scanf("[a-z | A-Z | 0-9/,.-]", spot2[8]);
int assignment2[3];
assignment2[0] = (int)spot2[0]-1;
assignment2[1] = (int)spot2[3]-1;
assignment2[2] = (int)spot2[6];
Puzzle1.Sudoku[assignment[0]][assignment[1]] = assignment[2];
printf("%s! Are there any more entries you want to record?\n", Support[loop]);
scanf("s", more);
if(loop<9)
{
loop = loop 1;
}
else
{
loop = 0;
}
}
return Puzzle1;
}
Calculate.c - checks each slot of the array if a 1-9 can go there. If only one number can go there, it assigns it there. If multiple can, it skips it. And it stops if nothing can go there.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
/*
****************************************
Here, we will calculate the empty blanks
****************************************
*/
struct Puzzle Calculate(Puzzle Puzzle1)
{
/*
************************************************************
First, we need to see if there are any zeroes to begin with.
************************************************************
*/
int Yes=0;
int look, here;
int count = 0;
for(look=0; look<9; look )
{
for(here=0; here<9; here )
{
if(Puzzle1.Sudoku[look][here] == 0)
{
Yes=1;
}
}
}
/*
***************************************************************
If there aren't, it's good to send a sassy message to the user.
***************************************************************
*/
if(Yes==0)
{
printf("You gave me an already solved Sudoku, baka!!!\n");
}
/*
******************************************************
If there are, we need to set up a loop with a counter.
******************************************************
*/
Freedom:
while(Yes==1)
{
count = count 1;
/*
********************************************************************************
In case there aren't enough given values, we need to avoid an infinite loop. We
choose 82, because in the worst case, the Sudoku will need to be solved from the
last value to the first, and will require 81 loops if blank. This loop variable
can also be returned if we want, to see how many loops it took to solve it.
********************************************************************************
*/
if(count==82)
{
printf("Error, there are multiple possible solutions for this Sudoku,\nAnd thus it is invalid.\n");
Yes = 0;
break;
}
// This is the normal case.
else
{
/*
*****************************************************************************************
We need to start by verifying that the puzzle isn't solved already, since we are looping.
*****************************************************************************************
*/
for(look=0; look<9; look )
{
for(here=0; here<9; here )
{
if(Puzzle1.Sudoku[look][here] == 0) // If any value in this entire matrix is still 0, go to the calculation portion.
{
goto NotSolved;
}
else // If every value is non-zero, change Yes to 0 to nullify the while loop.
{
Yes = 0;
}
}
}
/*
************************************************************************************************
Once we have solved the Sudoku, it's time to send the victory message and break out of the loop.
************************************************************************************************
*/
if(Yes==0)
{
printf("Congratulations, we've solved the Sudoku!\n");
break;
}
/*
**********************************************************
If we haven't solved the Sudoku, it's time to get solving.
**********************************************************
*/
else
{
NotSolved:
/*
*****************************************************************
Since there are zeroes left, we need to find them and solve them.
*****************************************************************
*/
for(look=0; look<9; look )
{
for(here=0; here<9; here )
{
if(Puzzle1.Sudoku[look][here] == 0)
{
/*
****************************************************************************************
Since we are inside the same iteration machine as before, we are already where the 0 is.
Now we need to find what numbers it can be. If it can be one number, we need to assign
that number to that spot; if it can be multiple numbers, we need to skip that space for
now and move on; and if it can be no numbers, we have an unsolvable Sudoku.
****************************************************************************************
*/
int a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0, i=0; // Initialize number-specific variables
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 1's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==1)
{
a=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==1)
{
a=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==1)
{
a=0;
}
else
{
a=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 2's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==2)
{
b=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==2)
{
b=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==2)
{
b=0;
}
else
{
b=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 3's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==3)
{
c=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==3)
{
c=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==3)
{
c=0;
}
else
{
c=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 4's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==4)
{
d=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==4)
{
d=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==4)
{
d=0;
}
else
{
d=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 5's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==5)
{
e=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==5)
{
e=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==5)
{
e=0;
}
else
{
e=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 6's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==6)
{
f=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==6)
{
f=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==6)
{
f=0;
}
else
{
f=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 7's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==7)
{
g=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==7)
{
g=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==7)
{
g=0;
}
else
{
g=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 8's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==8)
{
h=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==8)
{
h=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==8)
{
h=0;
}
else
{
h=1;
}
}
for(int scan=0; scan<9; scan ) // Check Row-Column-Box for 9's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==9)
{
i=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==9)
{
i=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==9)
{
i=0;
}
else
{
i=1;
}
}
if((a b c d e f g h i)<1) // If that space can't be anything, we've hit a dead end and need to break free.
{
printf("Error, this puzzle is unsolvable,\nAnd is therefore invalid");
Yes=0;
goto Freedom;
}
else if((a b c d e f g h i)==1) // If that space can be only one number, change it to that number.
{
if(a==1)
{
Puzzle1.Sudoku[look][here] = 1;
}
else if(b==1)
{
Puzzle1.Sudoku[look][here] = 2;
}
else if(c==1)
{
Puzzle1.Sudoku[look][here] = 3;
}
else if(d==1)
{
Puzzle1.Sudoku[look][here] = 4;
}
else if(e==1)
{
Puzzle1.Sudoku[look][here] = 5;
}
else if(f==1)
{
Puzzle1.Sudoku[look][here] = 6;
}
else if(g==1)
{
Puzzle1.Sudoku[look][here] = 7;
}
else if(h==1)
{
Puzzle1.Sudoku[look][here] = 8;
}
else if(i==1)
{
Puzzle1.Sudoku[look][here] = 9;
}
}
else if((a b c d e f g h i)>1) // If that space can be multiple numbers, move on. The looping should eventually solve it.
{
continue;
}
}
}
}
}
}
}
return Puzzle1;
}
main.c - calls each of these functions, and then prints the output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
struct Puzzle Setup(Puzzle);
struct Puzzle Input(Puzzle);
struct Puzzle Calculate(Puzzle);
int main()
{
/*
********************
First, run the Setup
********************
*/
Puzzle Setup();
/*
*****************************************
Then get input about this specific puzzle
*****************************************
*/
Puzzle Input(Puzzle1);
/*
********************************************
After that, run Calculate to get the answers
********************************************
*/
printf("Alright, leave the rest to me!\n\n");
Puzzle Calculate(Puzzle1);
/*
***************************
Finally, output the results
***************************
*/
printf("The solution is\n");
for(int r=0; r<9; r )
{
if(r==3||r==6)
{
printf("---------\n");
}
for(int c=0; c<9; c )
{
if(c==3||c==6)
{
printf("|");
}
printf("%d", Puzzle1.Sudoku[c][r]);
if(c==8)
{
printf("\n");
}
}
}
return(0);
}
Now what I'm trying to do is to #include the Setup.h, give the function prototypes, initialize the nested structure in Setup.c (takes no argument, returns the struct), then pass that struct to Input. Input changes the values in the struct and returns them to main with the new values. Main sends it to Calculate, then Calculate returns the final struct to main to be output.
Again, I know the struct is copied each time, and it's horribly inefficient, plus stupidly long, but for now it's the easiest way for me to keep track of what the program is doing. The specific error messages I'm getting repeatedly are "unknown type name", "expected declaration specifiers before 'Puzzle' ", and "return type is an incomplete type". And the vast majority of the time, it flags the first line of the Calculate.c file, "struct Puzzle Calculate(Puzzle Puzzle1){"
I added the code so that you all could see specifics, but I do apologize for how long it is... Any help would be appreciated, because I can't seem to track down the root of the problem. I've tried with and without typedef-ing it in the header file, I've tried all kinds of syntax, I've tried putting it all into one file, I've tried having the #include "Setup.h" in just one file or in all of them, and I've tried passing pointers instead of the structs themselves. So any suggestions are welcome!
CodePudding user response:
I think your problem comes from your return types, for exemple struct Puzzle Setup(Puzzle);
Your structure is named struct puzzle
(with a lower case "p") and Puzzle
is an alias for it.
Either use the return type Puzzle
or struct puzzle
and it should be fine.