-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsudoku_board.c
145 lines (124 loc) · 4.31 KB
/
sudoku_board.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
/******************************************************************************
* Program: sudoku_board.c
*
* Purpose: Defines struct describing the state of a sudoku puzzle board, along
* with functions for initializing, loading, copying, displaying and
* freeing the board's contents
*
* Developer: Philip Ormand
*
* Date: 5/13/16
*
*****************************************************************************/
#include <ctype.h>
#include <memory.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "sudoku_board.h"
#include "sudoku_test_digits.h"
#include "sudoku_undo.h"
void initializeSudokuBoard(struct SudokuBoard *board)
{
// allocate new history stack for this fresh board
if (board->history)
{
// if there is an existing history, free it so it's not leaked
freeHistory(&board->history);
}
board->history = createHistory(board);
// initialize board contents to 0;
memset((void*)&(board->contents), 0, SUDOKU_ROW_COUNT * SUDOKU_COL_COUNT);
}
void freeSudokuBoardResources(struct SudokuBoard *board)
{
freeHistory(&board->history);
}
bool loadSudokuBoard(char *fileName, struct SudokuBoard* board)
{
FILE *file;
if (file = fopen(fileName, "r"))
{
// reset sudoku board
initializeSudokuBoard(board);
char *currentSquare = board->contents[0],
*boardEnd = board->contents[0] + SUDOKU_ROW_COUNT * SUDOKU_COL_COUNT,
input; // we can use char for input instead of int, because we're checking feof()
while (currentSquare < boardEnd && !feof(file))
{
// scan file stream until we encounter a digit
while (!isdigit(input = getc(file)) && !feof(file)) // break if EOF is encountered
{
;
}
if (!feof(file))
{
// convert ASCII digit to binary integer by subtracting the ASCII code for 0
*currentSquare++ = input - '0';
}
}
}
else {
printf("Sorry, file \"%s\" not found\n", fileName);
// return false instead of terminating. program might try to recover.
return false;
}
return true;
}
void copySudokuBoardContents(const char source[SUDOKU_ROW_COUNT][SUDOKU_COL_COUNT], char destination[SUDOKU_ROW_COUNT][SUDOKU_COL_COUNT])
{
const char *currentSourceSquare = source[0],
*sourceEnd = currentSourceSquare + SUDOKU_ROW_COUNT * SUDOKU_COL_COUNT;
char *currentDestinationSquare = destination[0];
while (currentSourceSquare < sourceEnd)
{
*currentDestinationSquare++ = *currentSourceSquare++;
}
}
void printSudokuBoard(struct SudokuBoard *board)
{
// strings, not #defines: reduce size of compiled code (due to macro expansions)
// static variables: only one copy of each string exists across all calls
static char *rowDivider = " ++---+---+---++---+---+---++---+---+---++\n",
*rowDividerThick = " ++===+===+===++===+===+===++===+===+===++\n",
*rowFormatString = " %d - || %d | %d | %d || %d | %d | %d || %d | %d | %d ||\n",
*xAxisLabel = " A B C D E F G H I\n";
int i, j;
fputs(xAxisLabel, stdout);
for (i = 0; i < SUDOKU_ROW_COUNT; ++i)
{
if ( (i % 3) == 0 )
{
fputs(rowDividerThick, stdout);
}
else
{
fputs(rowDivider, stdout);
}
// row label
printf(" %d - ", i + 1);
for (j = 0; j < SUDOKU_COL_COUNT; ++j)
{
// print "thick" border if on a block boundary
if ( (j % 3) == 0 )
{
fputs("||", stdout);
}
else
{
putchar('|');
}
// print blank if 0, otherwise print digit
if (board->contents[i][j] > 0)
{
printf(" %d ", board->contents[i][j]);
}
else
{
fputs(" ", stdout);
}
}
fputs("||\n", stdout);
}
fputs(rowDividerThick, stdout);
}