[gnome-sudoku] Add validity and uniqueness check to manually created puzzles



commit c5ce94ea6485740bc9e8b9a9c669cf789042822c
Author: Parin Porecha <parinporecha gmail com>
Date:   Tue Apr 21 22:45:49 2015 +0530

    Add validity and uniqueness check to manually created puzzles
    
    Also bump required QQwing version to 1.3.4

 configure.ac           |    2 +-
 lib/qqwing-wrapper.cpp |   14 ++++++++++++++
 lib/qqwing-wrapper.h   |    1 +
 lib/qqwing.vapi        |    1 +
 lib/sudoku-board.vala  |    5 +++++
 src/gnome-sudoku.vala  |   42 +++++++++++++++++++++++++++++++++++++++---
 6 files changed, 61 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 9b9f308..7661522 100644
--- a/configure.ac
+++ b/configure.ac
@@ -27,7 +27,7 @@ dnl ###########################################################################
 
 GLIB_REQUIRED=2.40.0
 GTK_REQUIRED=3.15.0
-QQWING_REQUIRED=1.2.0
+QQWING_REQUIRED=1.3.4
 
 PKG_CHECK_MODULES(GNOME_SUDOKU, [
   glib-2.0 >= $GLIB_REQUIRED
diff --git a/lib/qqwing-wrapper.cpp b/lib/qqwing-wrapper.cpp
index c1a453f..99c4562 100644
--- a/lib/qqwing-wrapper.cpp
+++ b/lib/qqwing-wrapper.cpp
@@ -64,6 +64,20 @@ int* qqwing_generate_puzzle(int difficulty)
 }
 
 /*
+ * Count the number of solutions of a puzzle
+ * but return 2 if there are multiple.
+ * Returns 0 if the puzzle is not valid.
+ */
+int qqwing_count_solutions_limited(int* puzzle)
+{
+    SudokuBoard board;
+    if (!board.setPuzzle(puzzle))
+        return 0;
+
+    return board.countSolutionsLimited();
+}
+
+/*
  * Print the stats gathered while solving the puzzle given as input.
  */
 void qqwing_print_stats(int* puzzle)
diff --git a/lib/qqwing-wrapper.h b/lib/qqwing-wrapper.h
index 345ab2c..4a4bfa0 100644
--- a/lib/qqwing-wrapper.h
+++ b/lib/qqwing-wrapper.h
@@ -27,6 +27,7 @@
 G_BEGIN_DECLS
 
 int *qqwing_generate_puzzle(int difficulty);
+int qqwing_count_solutions_limited(int *puzzle);
 void qqwing_print_stats(int *puzzle);
 char *qqwing_get_version(void);
 
diff --git a/lib/qqwing.vapi b/lib/qqwing.vapi
index 6b2f5d6..bea1f73 100644
--- a/lib/qqwing.vapi
+++ b/lib/qqwing.vapi
@@ -23,6 +23,7 @@
 namespace QQwing {
     [CCode (array_length=false)]
     int[] generate_puzzle (int difficulty);
+    int count_solutions_limited ([CCode (array_length = false)] int[] puzzle);
     void print_stats ([CCode (array_length = false)] int[] puzzle);
     string get_version ();
 }
diff --git a/lib/sudoku-board.vala b/lib/sudoku-board.vala
index 4507ac8..fbc206f 100644
--- a/lib/sudoku-board.vala
+++ b/lib/sudoku-board.vala
@@ -392,6 +392,11 @@ public class SudokuBoard : Object
             fixed--;
     }
 
+    public int count_solutions_limited ()
+    {
+        return QQwing.count_solutions_limited ((int[]) cells);
+    }
+
     public Set<Coord?> get_occurances(Gee.List<Coord?> coords, int val)
     {
         Set<Coord?> occurances = new HashSet<Coord?>((HashDataFunc<Coord>) Coord.hash, 
(EqualDataFunc<Coord>) Coord.equal);
diff --git a/src/gnome-sudoku.vala b/src/gnome-sudoku.vala
index 1ec9ed8..4a31d0e 100644
--- a/src/gnome-sudoku.vala
+++ b/src/gnome-sudoku.vala
@@ -293,9 +293,38 @@ public class Sudoku : Gtk.Application
 
     private void play_custom_game_cb ()
     {
-        current_game_mode = GameMode.PLAY;
-        game.stop_clock ();
-        start_game (game.board);
+        int solutions = game.board.count_solutions_limited ();
+        if (solutions == 1)
+        {
+            start_custom_game (game.board);
+        }
+        else if (solutions == 0)
+        {
+            // Error dialog shown when starting a custom game that is not valid.
+            var error_str = "%s\n%s".printf(_("The puzzle you have entered is not a valid Sudoku."), 
_("Please enter a valid puzzle."));
+            var dialog = new MessageDialog (window, DialogFlags.MODAL, MessageType.ERROR, ButtonsType.OK, 
error_str);
+
+            dialog.run ();
+            dialog.destroy ();
+        }
+        else
+        {
+            // Warning dialog shown when starting a custom game that has multiple solutions.
+            var warning_str = "%s\n%s".printf(_("The puzzle you have entered has multiple solutions."), 
_("Valid Sudoku puzzles have exactly one solution."));
+            var dialog = new MessageDialog (window, DialogFlags.MODAL, MessageType.WARNING, 
ButtonsType.NONE, warning_str);
+            dialog.add_button (_("_Back"), Gtk.ResponseType.REJECT);
+            dialog.add_button (_("Play _Anyway"), Gtk.ResponseType.ACCEPT);
+
+            dialog.response.connect ((response_id) => {
+                if (response_id == Gtk.ResponseType.ACCEPT)
+                {
+                    start_custom_game (game.board);
+                }
+                dialog.destroy ();
+            });
+
+            dialog.show ();
+        }
     }
 
     private void toggle_pause_cb ()
@@ -330,6 +359,13 @@ public class Sudoku : Gtk.Application
         play_pause_label.label = _("_Resume");
     }
 
+    private void start_custom_game (SudokuBoard board)
+    {
+        current_game_mode = GameMode.PLAY;
+        game.stop_clock ();
+        start_game (board);
+    }
+
     private void start_game (SudokuBoard board)
     {
         if (view != null)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]