summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael R Sweet <michael.r.sweet@gmail.com>2005-11-27 01:56:57 +0000
committerMichael R Sweet <michael.r.sweet@gmail.com>2005-11-27 01:56:57 +0000
commit0ca7b126e76c1fe88a55ffaff7b68fd941eb0530 (patch)
treeecac86add724c71e21a4e901abd64dd294658ca7
parentfd9a51e43b57b61ae1a321b6b4e627388b3179f7 (diff)
More improvements to game board generator.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.1@4658 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
-rw-r--r--test/sudoku.cxx133
1 files changed, 99 insertions, 34 deletions
diff --git a/test/sudoku.cxx b/test/sudoku.cxx
index f5a000505..515609352 100644
--- a/test/sudoku.cxx
+++ b/test/sudoku.cxx
@@ -217,6 +217,7 @@ class Sudoku : public Fl_Window {
static void diff_cb(Fl_Widget *widget, void *d);
static void new_cb(Fl_Widget *widget, void *);
static void reset_cb(Fl_Widget *widget, void *);
+ void set_title();
static void solve_cb(Fl_Widget *widget, void *);
static Fl_Preferences prefs_;
@@ -252,22 +253,20 @@ Sudoku::Sudoku()
{ "&Quit", FL_COMMAND | 'q', close_cb, 0, 0 },
{ 0 },
{ "&Difficulty", 0, 0, 0, FL_SUBMENU },
- { "&Easy", FL_COMMAND | '1', diff_cb, (void *)"40", FL_MENU_RADIO },
- { "&Medium", FL_COMMAND | '2', diff_cb, (void *)"32", FL_MENU_RADIO },
- { "&Hard", FL_COMMAND | '3', diff_cb, (void *)"24", FL_MENU_RADIO },
- { "&Impossible", FL_COMMAND | '4', diff_cb, (void *)"16", FL_MENU_RADIO },
+ { "&Easy", FL_COMMAND | '1', diff_cb, (void *)"0", FL_MENU_RADIO },
+ { "&Medium", FL_COMMAND | '2', diff_cb, (void *)"1", FL_MENU_RADIO },
+ { "&Hard", FL_COMMAND | '3', diff_cb, (void *)"2", FL_MENU_RADIO },
+ { "&Impossible", FL_COMMAND | '4', diff_cb, (void *)"3", FL_MENU_RADIO },
{ 0 },
{ 0 }
};
// Menubar...
- prefs_.get("difficulty", difficulty_, 40);
+ prefs_.get("difficulty", difficulty_, 0);
+ if (difficulty_ < 0 || difficulty_ > 3) difficulty_ = 0;
- if (difficulty_ == 16) items[10].flags |= FL_MENU_VALUE;
- else if (difficulty_ == 24) items[9].flags |= FL_MENU_VALUE;
- else if (difficulty_ == 32) items[8].flags |= FL_MENU_VALUE;
- else items[7].flags |= FL_MENU_VALUE;
+ items[7 + difficulty_].flags |= FL_MENU_VALUE;
menubar_ = new Fl_Sys_Menu_Bar(0, 0, 3 * GROUP_SIZE, 25);
menubar_->menu(items);
@@ -313,6 +312,7 @@ Sudoku::Sudoku()
// Load the previous game...
load_game();
+ set_title();
}
@@ -328,11 +328,11 @@ void
Sudoku::check_game(bool highlight) {
bool empty = false;
bool correct = true;
-
+ int i, j;
// Check the game for right/wrong answers...
- for (int i = 0; i < 9; i ++)
- for (int j = 0; j < 9; j ++) {
+ for (i = 0; i < 9; i ++)
+ for (j = 0; j < 9; j ++) {
SudokuCell *cell = grid_cells_[i][j];
int val = cell->value();
@@ -352,6 +352,32 @@ Sudoku::check_game(bool highlight) {
// Success!
solve_game();
fl_message("Congratulations, you solved the game!");
+ } else {
+ int k, m;
+
+ for (i = 0; i < 9; i += 3)
+ for (j = 0; j < 9; j += 3) {
+ correct = true;
+
+ for (k = 0; correct && k < 3; k ++)
+ for (m = 0; m < 3; m ++)
+ if (grid_cells_[i + k][j + m]->value() !=
+ grid_values_[i + k][j + m]) {
+ correct = false;
+ break;
+ }
+
+ if (correct) {
+ for (k = 0; k < 3; k ++)
+ for (m = 0; m < 3; m ++) {
+ SudokuCell *cell = grid_cells_[i + k][j + m];
+
+ cell->readonly(1);
+ cell->color(fl_color_average(FL_GRAY, FL_GREEN, 0.5f));
+ }
+ }
+
+ }
}
}
@@ -373,6 +399,9 @@ Sudoku::diff_cb(Fl_Widget *widget, void *d) {
s->difficulty_ = atoi((char *)d);
s->new_game();
+ s->set_title();
+
+ prefs_.set("difficulty", s->difficulty_);
}
@@ -493,8 +522,8 @@ Sudoku::new_game() {
cell->color(FL_LIGHT3);
}
- // Show N cells, starting with potential confusing ones...
- count = difficulty_;
+ // Show N cells...
+ count = 5 * (5 - difficulty_);
int numbers[9];
@@ -525,33 +554,55 @@ Sudoku::new_game() {
}
}
}
+ }
- if (count <= 0) break;
+ // Show additional cells as needed to avoid ambiguous solutions.
+ // The basic premise is to find all possible numbers for each hidden
+ // cell and show the cell if we have more than two possible solutions.
+ int possible;
- for (i = 0; i < 20; i ++) {
- k = rand() % 9;
- m = rand() % 9;
- t = numbers[k];
- numbers[k] = numbers[m];
- numbers[m] = t;
- }
+ count = 5 * (5 - difficulty_);
- for (j = 0; count > 0 && j < 9; j ++) {
- t = numbers[j];
+ while (count > 0) {
+ i = rand() % 9;
+ j = rand() % 9;
+ cell = grid_cells_[i][j];
- for (i = 0; count > 0 && i < 9; i ++) {
- cell = grid_cells_[i][j];
+ if (cell->readonly()) continue;
- if (grid_values_[i][j] == t && !cell->readonly()) {
- cell->value(grid_values_[i][j]);
- cell->readonly(1);
- cell->color(FL_GRAY);
+ possible = 9;
+ memset(numbers, 0, sizeof(numbers));
- count --;
- break;
- }
+ // Check vertical cells
+ for (k = 0; k < 9; k ++) {
+ cell = grid_cells_[k][j];
+ t = grid_values_[k][j] - 1;
+
+ if (i != k && !numbers[t] && cell->readonly()) {
+ possible --;
+ numbers[t] = 1;
+ }
+ }
+
+ // Check horizontal cells
+ for (m = 0; m < 9; m ++) {
+ cell = grid_cells_[i][m];
+ t = grid_values_[i][m] - 1;
+
+ if (j != m && !numbers[t] && cell->readonly()) {
+ possible --;
+ numbers[t] = 1;
}
}
+
+ // Now, if the count > 2, show this cell...
+ if (possible > 2) {
+ cell = grid_cells_[i][j];
+ cell->value(grid_values_[i][j]);
+ cell->readonly(1);
+ cell->color(FL_GRAY);
+ count --;
+ }
}
}
@@ -616,6 +667,20 @@ Sudoku::save_game() {
}
+// Set title of window...
+void
+Sudoku::set_title() {
+ static const char * const titles[] = {
+ "Sudoku - Easy",
+ "Sudoku - Medium",
+ "Sudoku - Hard",
+ "Sudoku - Impossible"
+ };
+
+ label(titles[difficulty_]);
+}
+
+
// Solve the puzzle...
void
Sudoku::solve_cb(Fl_Widget *widget, void *) {
@@ -634,7 +699,7 @@ Sudoku::solve_game() {
cell->value(grid_values_[i][j]);
cell->readonly(1);
- cell->color(FL_GRAY);
+ cell->color(fl_color_average(FL_GRAY, FL_GREEN, 0.5f));
}
}