From 237c854e42efa729896a30408d48138c9e90bf09 Mon Sep 17 00:00:00 2001 From: Jeremy Rand Date: Thu, 23 Jul 2015 00:01:52 -0400 Subject: [PATCH] Do not check for saved games after the first game in a single session. Save the entire board for undo, not just the last modified square. When entering a value in a square, update all scratch values in the row, column and sub square. Fix a bug where some squares in a sub square were not being checked for invalid values. --- a2sudoku/game.c | 135 +++++++++++++++++++------------------- a2sudoku/make/V2Make.scpt | Bin 4714 -> 4710 bytes a2sudoku/ui.c | 55 ++++++++-------- 3 files changed, 95 insertions(+), 95 deletions(-) diff --git a/a2sudoku/game.c b/a2sudoku/game.c index 08657b2..e0d672e 100644 --- a/a2sudoku/game.c +++ b/a2sudoku/game.c @@ -17,6 +17,7 @@ // Macros #define SQUARE_XY(x, y) (theGame.squares[((y) * BOARD_SIZE) + (x)]) +#define PREV_SQUARE_XY(x, y) (theGame.prevSquares[((y) * BOARD_SIZE) + (x)]) #define SAVE_GAME_FILE "a2sudoku.game" @@ -31,19 +32,12 @@ typedef struct tGameSquare { } tGameSquare; -typedef struct tUndoMove { - tGameSquare oldSquare; - tPos x; - tPos y; - bool isValid; -} tUndoMove; - - typedef struct tGame { tGameSquare squares[BOARD_SIZE * BOARD_SIZE]; + tGameSquare prevSquares[BOARD_SIZE * BOARD_SIZE]; struct tPuzzle *puzzle; tUpdatePosCallback callback; - tUndoMove undo; + bool undoValid; } tGame; @@ -89,6 +83,8 @@ void restartGame(void) refreshPos(x, y); } } + + theGame.undoValid = false; } @@ -258,7 +254,7 @@ bool isSquareInvalid(tPos col, tPos row) for (x = subSquareXStart; x < subSquareXEnd; x++) { if (x == col) continue; - if (y == col) + if (y == row) continue; if (value == SQUARE_XY(x, y).value) @@ -272,11 +268,12 @@ bool isSquareInvalid(tPos col, tPos row) } -void refreshInvalid(tPos col, tPos row, tSquareVal oldValue) +void refreshNeighbours(tPos col, tPos row, tSquareVal newValue, tSquareVal oldValue) { tPos x, y; tGameSquare *square = &(SQUARE_XY(col, row)); bool newInvalid; + bool checkInvalid = true; tPos subSquareXStart, subSquareXEnd; tPos subSquareYStart, subSquareYEnd; @@ -293,7 +290,7 @@ void refreshInvalid(tPos col, tPos row, tSquareVal oldValue) // square. if ((oldValue == EMPTY_SQUARE) && (!newInvalid)) - return; + checkInvalid = false; for (y = 0; y < BOARD_SIZE; y++) { if (y == row) @@ -302,11 +299,18 @@ void refreshInvalid(tPos col, tPos row, tSquareVal oldValue) square = &(SQUARE_XY(col, y)); if (square->knownAtStart) continue; + if (checkInvalid) { + newInvalid = isSquareInvalid(col, y); + + if (newInvalid != square->invalid) { + square->invalid = newInvalid; + refreshPos(col, y); + } + } - newInvalid = isSquareInvalid(col, y); - - if (newInvalid != square->invalid) { - square->invalid = newInvalid; + if ((newValue != EMPTY_SQUARE) && + (SCRATCH_TEST(square->scratchValues, newValue))) { + square->scratchValues ^= (0x1 << newValue); refreshPos(col, y); } } @@ -319,10 +323,18 @@ void refreshInvalid(tPos col, tPos row, tSquareVal oldValue) if (square->knownAtStart) continue; - newInvalid = isSquareInvalid(x, row); + if (checkInvalid) { + newInvalid = isSquareInvalid(x, row); + + if (newInvalid != square->invalid) { + square->invalid = newInvalid; + refreshPos(x, row); + } + } - if (newInvalid != square->invalid) { - square->invalid = newInvalid; + if ((newValue != EMPTY_SQUARE) && + (SCRATCH_TEST(square->scratchValues, newValue))) { + square->scratchValues ^= (0x1 << newValue); refreshPos(x, row); } } @@ -336,17 +348,25 @@ void refreshInvalid(tPos col, tPos row, tSquareVal oldValue) for (x = subSquareXStart; x < subSquareXEnd; x++) { if (x == col) continue; - if (y == col) + if (y == row) continue; square = &(SQUARE_XY(x, y)); if (square->knownAtStart) continue; - newInvalid = isSquareInvalid(x, y); + if (checkInvalid) { + newInvalid = isSquareInvalid(x, y); + + if (newInvalid != square->invalid) { + square->invalid = newInvalid; + refreshPos(x, y); + } + } - if (newInvalid != square->invalid) { - square->invalid = newInvalid; + if ((newValue != EMPTY_SQUARE) && + (SCRATCH_TEST(square->scratchValues, newValue))) { + square->scratchValues ^= (0x1 << newValue); refreshPos(x, y); } } @@ -366,10 +386,8 @@ bool setValueAtPos(tPos x, tPos y, tSquareVal val) return false; } - theGame.undo.isValid = true; - memcpy(&(theGame.undo.oldSquare), square, sizeof(*square)); - theGame.undo.x = x; - theGame.undo.y = y; + theGame.undoValid = true; + memcpy(theGame.prevSquares, theGame.squares, sizeof(theGame.squares)); if (square->value != val) { oldValue = square->value; @@ -395,7 +413,7 @@ bool setValueAtPos(tPos x, tPos y, tSquareVal val) refreshPos(x,y); if (checkValues) - refreshInvalid(x, y, oldValue); + refreshNeighbours(x, y, val, oldValue); return true; } @@ -409,10 +427,8 @@ bool toggleScratchValueAtPos(tPos x, tPos y, tSquareVal val) return false; } - theGame.undo.isValid = true; - memcpy(&(theGame.undo.oldSquare), square, sizeof(*square)); - theGame.undo.x = x; - theGame.undo.y = y; + theGame.undoValid = true; + memcpy(theGame.prevSquares, theGame.squares, sizeof(theGame.squares)); square->scratchValues ^= (0x1 << val); refreshPos(x, y); @@ -424,49 +440,30 @@ bool toggleScratchValueAtPos(tPos x, tPos y, tSquareVal val) bool undoLastMove(void) { tGameSquare *square; - bool update = false; - bool checkValues = false; - tPos x = theGame.undo.x; - tPos y = theGame.undo.y; - bool correct; - tSquareVal oldValue = EMPTY_SQUARE; + tGameSquare *prevSquare; + tPos x, y; - if (!theGame.undo.isValid) + if (!theGame.undoValid) return false; - square = &(SQUARE_XY(x, y)); - - if (square->knownAtStart) { - return false; - } - - theGame.undo.isValid = false; - - if (square->value != theGame.undo.oldSquare.value) { - oldValue = square->value; - square->value = theGame.undo.oldSquare.value; - update = true; - checkValues = true; - } - - if (square->scratchValues != theGame.undo.oldSquare.scratchValues) { - square->scratchValues = theGame.undo.oldSquare.scratchValues; - update = true; - } - - if (checkValues) { - correct = checkValueAtPos(theGame.puzzle, square->value, x, y); - if (square->correct != correct) { - square->correct = correct; - update = true; + for (y = 0; y < BOARD_SIZE; y++) { + for (x = 0; x < BOARD_SIZE; x++) { + square = &(SQUARE_XY(x, y)); + + if (square->knownAtStart) + continue; + + prevSquare = &(PREV_SQUARE_XY(x, y)); + if ((square->value != prevSquare->value) || + (square->scratchValues != prevSquare->scratchValues) || + (square->invalid != prevSquare->invalid)) { + memcpy(square, prevSquare, sizeof(*square)); + refreshPos(x, y); + } } } - if (update) - refreshPos(x,y); - - if (checkValues) - refreshInvalid(x, y, oldValue); + theGame.undoValid = false; return true; } \ No newline at end of file diff --git a/a2sudoku/make/V2Make.scpt b/a2sudoku/make/V2Make.scpt index 16a76d6f6f97f3455a4e306aaab119ebcd32581e..bf6e81a370f4335f49807c0412d6da54df76f639 100644 GIT binary patch delta 190 zcmaE*@=RsJb#A5|9Fre%drkhp%`sVG?8G<*L^WJ2ZZDY`92xG`+$YCgD$Yn@nC>Feu<<>!>YEQWEh=Gkx-euk;g#yTol(-Tgn-Rzcs%4m(lL|E3 z6v^nxti0Nj^?6k#r5Jb^d>IlMk{L1?@)$}O@)?R5G8hyXJT^!3-el%2W6);^1q!7y k6fqP}4ixMbj^IrzEy_vD%t^J<*Vhj%PAw{){9P~~0JpI;;{X5v diff --git a/a2sudoku/ui.c b/a2sudoku/ui.c index 181c42f..b131999 100644 --- a/a2sudoku/ui.c +++ b/a2sudoku/ui.c @@ -516,6 +516,7 @@ void youWon(void) bool playGame(void) { + static bool firstGame = true; bool shouldSave = false; bool gameLoaded = false; char ch; @@ -523,33 +524,35 @@ bool playGame(void) initUI(); textMode(); - - printf("\n\nChecking for a saved puzzle..."); - - if (loadGame(updatePos)) { - bool gotAnswer = false; + if (firstGame) { + firstGame = false; + printf("\n\nChecking for a saved puzzle..."); - printf("\n\nYou have a saved puzzle!\n Would you like to continue it (Y/N)"); - - while (!gotAnswer) { - ch = cgetc(); - switch (ch) { - case 'y': - case 'Y': - printf("\n\nLoading your saved puzzle"); - gameLoaded = true; - gotAnswer = true; - shouldSave = true; - break; - - case 'n': - case 'N': - gotAnswer = true; - break; - - default: - printf("\007"); - break; + if (loadGame(updatePos)) { + bool gotAnswer = false; + + printf("\n\nYou have a saved puzzle!\n Would you like to continue it (Y/N)"); + + while (!gotAnswer) { + ch = cgetc(); + switch (ch) { + case 'y': + case 'Y': + printf("\n\nLoading your saved puzzle"); + gameLoaded = true; + gotAnswer = true; + shouldSave = true; + break; + + case 'n': + case 'N': + gotAnswer = true; + break; + + default: + printf("\007"); + break; + } } } }