/* * File: sudoku.cpp * Descr: Implementation of sudoku generator and solver * Author: Mats Byggmastar * Date: 23.07.2005 */ #include "sudoku.h" #include #define VERSION_STR "Sudoku v1.0" static unsigned long seed = 0; static int get_random(int limit) { seed = 1664525 * seed + 1013904223; return (int) ((double)limit * seed / ((double) 0xFFFFFFFF + 1.0)); } static int get_bitcount(int choises) { int count = 0; for (int i=1; i <= 9; i++) { count += (choises >> i) & 1; } return count; } static int get_choises(int x, int y, int numbers[9][9]) { int bits = 0; if (numbers[y][x]) { return 0; // no choises, number already set } for (int i=0; i < 9; i++) { bits |= 1 << numbers[y][i]; // horizontal bits |= 1 << numbers[i][x]; // vertical bits |= 1 << numbers[(y/3)*3 + i/3][(x/3)*3 + i%3]; // 3x3 box } return ~bits & 0x3FE; } static int count_numbers(int numbers[9][9]) { int count = 0; for (int y=0; y < 9; y++) { for (int x=0; x < 9; x++) { if (numbers[y][x]) { count++; } } } return count; } static bool generate(int numbers[9][9]) { int bitcount, choises, pos, count, i; int least_bitcount, save_choises, save_pos; memset(numbers, 0, sizeof(int[9][9])); for (count=0; count < 9*9; count++) { // find cell with least choises least_bitcount = 10; pos = get_random(9*9); for (i=0; i < 9*9; i++) { choises = get_choises(pos % 9, pos / 9, numbers); bitcount = get_bitcount(choises); if (bitcount && (bitcount < least_bitcount)) { least_bitcount = bitcount; save_choises = choises; save_pos = pos; } pos = (pos + 1) % (9*9); } if (least_bitcount == 10) { // this game can not be solved return false; } for (;;) { // randomly select one of the choises, and set it i = 1 + get_random(9); if (save_choises & (1 << i)) { numbers[save_pos / 9][save_pos % 9] = i; break; } } } return true; } static void hide_numbers(int numbers[9][9]) { int box[3][3], temp_num[9][9], work_num[9][9], pos, i, min; int save_pos; memcpy(temp_num, numbers, sizeof(int[9][9])); memset(numbers, 0, sizeof(int[9][9])); memset(box, 0, sizeof(int[3][3])); do { // randomly select 3x3 box with least number of numbers min = 10; pos = get_random(3*3); for (i=0; i < 3*3; i++) { if (min > box[pos / 3][pos % 3]) { min = box[pos / 3][pos % 3]; save_pos = pos; } pos = (pos + 1) % (3*3); } box[save_pos / 3][save_pos % 3]++; // randomly add number to selected 3x3 box pos = get_random(3*3); for (i=0; i < 3*3; i++) { if (numbers[(save_pos/3)*3 + pos/3][(save_pos%3)*3 + pos%3] == 0) { numbers[(save_pos/3)*3 + pos/3][(save_pos%3)*3 + pos%3] = temp_num[(save_pos/3)*3 + pos/3][(save_pos%3)*3 + pos%3]; break; } pos = (pos + 1) % (3*3); } memcpy(work_num, numbers, sizeof(int[9][9])); } while (!solve_sudoku(work_num)); } bool solve_sudoku(int numbers[9][9]) { int bitcount, choises, pos, count, i; count = count_numbers(numbers); for (; count < 9*9; count++) { for (pos=0; pos < 9*9; pos++) { // find cell with only one choise choises = get_choises(pos % 9, pos / 9, numbers); bitcount = get_bitcount(choises); if (bitcount == 1) { for (i=1; i <= 9; i++) { if (choises & (1 << i)) { numbers[pos / 9][pos % 9] = i; break; } } break; } } if (pos >= 9*9) { // game can not be solved return false; } } return true; } bool generate_sudoku(int numbers[9][9], int game) { unsigned long old_seed, save_seed; int visible, i, least_visible, work_num[9][9]; seed = game; if (!generate(numbers)) { return false; } least_visible = 9*9+1; for (i=0; i < 200; i++) { memcpy(work_num, numbers, sizeof(int[9][9])); old_seed = seed; hide_numbers(work_num); visible = count_numbers(work_num); if (least_visible > visible) { least_visible = visible; save_seed = old_seed; } } seed = save_seed; hide_numbers(numbers); return true; } const char * sudoku_generator_version() { return VERSION_STR; }