Implement board value placement heuristics

This commit is contained in:
Gabriel Tofvesson 2020-02-28 00:47:15 +01:00
parent bfd509f660
commit ac5de85171
2 changed files with 109 additions and 0 deletions

74
board.c
View File

@ -209,3 +209,77 @@ board_is_valid (struct board *board)
return false;
return true;
}
void
board_update_marks (
struct board *board,
board_pos x,
board_pos y
)
{
if (is_in_bounds (x, y))
{
struct board_element *elem = BOARD_ELEM (board, x, y);
/* Mark all values as impossible */
elem->potential = 0;
/* Check x-axis */
for (board_pos check_x = 0; check_x < 9; ++check_x)
if (check_x != x && board_has_value (board, check_x, y))
elem->potential |= 1 << BOARD_ELEM (board, check_x, y)->value;
/* Check y-axis */
for (board_pos check_y = 0; check_y < 9; ++check_y)
if (check_y != y && board_has_value (board, x, check_y))
elem->potential |= 1 << BOARD_ELEM (board, x, check_y)->value;
/* Invert matches */
elem->potential ^= 0x1FF;
}
else ERROR("Invalid parameters to function board_update_marks()");
}
void
board_update_all_marks (struct board *board)
{
for (board_pos y = 0; y < 9; ++y)
for (board_pos x = 0; x < 9; ++x)
if (! board_has_value (board, x, y))
board_update_marks (board, x, y);
}
bool
board_place (
struct board *board,
board_pos x,
board_pos y,
element_value value
)
{
if (is_in_bounds (x, y) && is_valid_value (value))
{
if (board_can_place_value (board, x, y, value))
{
/* Unmark x-axis */
for (board_pos unmark_x = 0; unmark_x < 9; ++unmark_x)
if (unmark_x != x && ! board_has_value (board, unmark_x, y))
board_unmark (board, unmark_x, y, value);
/* Unmark y-axis */
for (board_pos unmark_y = 0; unmark_y < 9; ++unmark_y)
if (unmark_y != y && ! board_has_value (board, x, unmark_y))
board_unmark (board, x, unmark_y, value);
/* Set value */
board_set (board, x, y, value);
return true;
}
else return false;
}
else ERROR("Invalid parameters to function board_place()");
}

35
board.h
View File

@ -142,3 +142,38 @@ board_can_place_value (
*/
bool
board_is_valid (struct board *board);
/**
* Check row and column of given position and mark potential values that could
* be set at that position and still leave the board in a valid state
*/
void
board_update_marks (
struct board *board,
board_pos x,
board_pos y
);
/**
* Refreshes marks of all board elements without a value
*/
void
board_update_all_marks (struct board *board);
/**
* Attempt to set value at the given position
* If value can be placed, this updates all elements without a value on the
* same row or column that do not have a value so that their markers reflect
* the addition of this value and returns true
* If value cannot be placed, just return false
*/
bool
board_place (
struct board *board,
board_pos x,
board_pos y,
element_value value
);