[gnome-sudoku] Use QQwing for puzzle generation



commit 1fa0067afab1efae24892fea0f7e9535605c5129
Author: Parin Porecha <parinporecha gmail com>
Date:   Wed Aug 6 15:15:07 2014 +0200

    Use QQwing for puzzle generation
    
    At this point, only the SudokuPrinter depends on data files.
    Starting a new game doesn't take a puzzle from the Store,
    but requests QQwing to generate one of the selected difficulty.
    
    Also renamed our DifficultyCategory enum values
    to match with those of QQwing

 data/gnome-sudoku.ui      |   16 +++++-----
 data/print-games.ui       |    8 ++--
 lib/sudoku-board.vala     |   70 ++++++++++++++++++++++-----------------------
 lib/sudoku-generator.vala |    6 ++--
 lib/sudoku-saver.vala     |    8 ++---
 src/gnome-sudoku.vala     |   22 +++++---------
 src/sudoku-printer.vala   |   18 ++++++------
 src/sudoku-store.vala     |   58 ++++++++++++++++---------------------
 8 files changed, 94 insertions(+), 112 deletions(-)
---
diff --git a/data/gnome-sudoku.ui b/data/gnome-sudoku.ui
index fc866e3..9db7468 100644
--- a/data/gnome-sudoku.ui
+++ b/data/gnome-sudoku.ui
@@ -100,9 +100,9 @@
                             <object class="GtkButton" id="easy_button">
                                 <property name="visible">True</property>
                                 <property name="use_underline">True</property>
-                                <property name="label" translatable="yes">_Easy</property>
+                                <property name="label" translatable="yes">_Simple</property>
                                 <property name="action-name">app.start-game</property>
-                                <property name="action-target">0</property>  <!-- 0 corresponds to enum 
DifficultyCategory.EASY -->
+                                <property name="action-target">1</property>  <!-- 1 corresponds to enum 
DifficultyCategory.SIMPLE -->
                             </object>
                             <packing>
                                 <property name="expand">True</property>
@@ -114,9 +114,9 @@
                             <object class="GtkButton" id="medium_button">
                                 <property name="visible">True</property>
                                 <property name="use_underline">True</property>
-                                <property name="label" translatable="yes">_Medium</property>
+                                <property name="label" translatable="yes">_Easy</property>
                                 <property name="action-name">app.start-game</property>
-                                <property name="action-target">1</property>  <!-- 1 corresponds to enum 
DifficultyCategory.MEDIUM -->
+                                <property name="action-target">2</property>  <!-- 2 corresponds to enum 
DifficultyCategory.EASY -->
                             </object>
                             <packing>
                                 <property name="expand">True</property>
@@ -128,9 +128,9 @@
                             <object class="GtkButton" id="hard_button">
                                 <property name="visible">True</property>
                                 <property name="use_underline">True</property>
-                                <property name="label" translatable="yes">_Hard</property>
+                                <property name="label" translatable="yes">_Intermediate</property>
                                 <property name="action-name">app.start-game</property>
-                                <property name="action-target">2</property>  <!-- 2 corresponds to enum 
DifficultyCategory.HARD -->
+                                <property name="action-target">3</property>  <!-- 3 corresponds to enum 
DifficultyCategory.INTERMEDIATE -->
                             </object>
                             <packing>
                                 <property name="expand">True</property>
@@ -142,9 +142,9 @@
                             <object class="GtkButton" id="very_hard_button">
                                 <property name="visible">True</property>
                                 <property name="use_underline">True</property>
-                                <property name="label" translatable="yes">_Very Hard</property>
+                                <property name="label" translatable="yes">_Expert</property>
                                 <property name="action-name">app.start-game</property>
-                                <property name="action-target">3</property>  <!-- 3 corresponds to enum 
DifficultyCategory.VERY_HARD -->
+                                <property name="action-target">4</property>  <!-- 4 corresponds to enum 
DifficultyCategory.EXPERT -->
                             </object>
                             <packing>
                                 <property name="expand">True</property>
diff --git a/data/print-games.ui b/data/print-games.ui
index 72a2ab1..dd10823 100644
--- a/data/print-games.ui
+++ b/data/print-games.ui
@@ -142,7 +142,7 @@
                     <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | 
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
                     <child>
                       <object class="GtkRadioButton" id="easyRadioButton">
-                        <property name="label" translatable="yes">_Easy</property>
+                        <property name="label" translatable="yes">_Simple</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
@@ -158,7 +158,7 @@
                     </child>
                     <child>
                       <object class="GtkRadioButton" id="mediumRadioButton">
-                        <property name="label" translatable="yes">_Medium</property>
+                        <property name="label" translatable="yes">_Easy</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
@@ -174,7 +174,7 @@
                     </child>
                     <child>
                       <object class="GtkRadioButton" id="hardRadioButton">
-                        <property name="label" translatable="yes">_Hard</property>
+                        <property name="label" translatable="yes">_Intermediate</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
@@ -190,7 +190,7 @@
                     </child>
                     <child>
                       <object class="GtkRadioButton" id="very_hardRadioButton">
-                        <property name="label" translatable="yes">_Very Hard</property>
+                        <property name="label" translatable="yes">_Expert</property>
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="receives_default">False</property>
diff --git a/lib/sudoku-board.vala b/lib/sudoku-board.vala
index 04547ca..88cb8ff 100644
--- a/lib/sudoku-board.vala
+++ b/lib/sudoku-board.vala
@@ -12,17 +12,12 @@ public class SudokuBoard : Object
     private bool[,] possible_in_col;            /* if specific value is possible in specific col */
     private bool[,,] possible_in_block;         /* if specific value is possible in specific block */
 
-    private const float[] VERY_HARD_RANGE = { 0.75f, 10 };
-    private const float[] HARD_RANGE = { 0.6f, 0.75f };
-    private const float[] MEDIUM_RANGE = { 0.45f, 0.6f };
-    private const float[] EASY_RANGE = { -10, 0.45f };
-
-    public double difficulty_rating;
-
     public bool[,,] earmarks;                  /* Earmarks set by the user */
 
     public double previous_played_time { set; get; default = 0; }
 
+    public DifficultyCategory difficulty_category { set; get; default = DifficultyCategory.UNKNOWN; }
+
     /* Number of rows in one block */
     public int block_rows { get; private set; }
 
@@ -62,25 +57,6 @@ public class SudokuBoard : Object
         return filled == fixed;
     }
 
-    private bool in_range (float[] range)
-    {
-        return (difficulty_rating >= range[0] && difficulty_rating < range[1]);
-    }
-
-    public DifficultyCategory get_difficulty_category ()
-    {
-        if (in_range(EASY_RANGE))
-            return DifficultyCategory.EASY;
-        else if (in_range(MEDIUM_RANGE))
-            return DifficultyCategory.MEDIUM;
-        else if (in_range(HARD_RANGE))
-            return DifficultyCategory.HARD;
-        else if (in_range(VERY_HARD_RANGE))
-            return DifficultyCategory.VERY_HARD;
-        else
-            return DifficultyCategory.EASY;
-    }
-
     public signal void completed ();
 
     /* The set of coordinates on the board which are invalid */
@@ -189,6 +165,7 @@ public class SudokuBoard : Object
         board.fixed = fixed;
         board.broken_coords.add_all (broken_coords);
         board.earmarks = earmarks;
+        board.difficulty_category = difficulty_category;
 
         return board;
     }
@@ -203,7 +180,6 @@ public class SudokuBoard : Object
 
         string[] rating = cells[cells.length -1].split (rating_delimiter, 2);
         cells[cells.length - 1] = rating[0];
-        difficulty_rating = double.parse (rating[1]);
 
         for (int i = 0; i < number_of_cells; i++)
         {
@@ -581,23 +557,45 @@ public struct Cell
 }
 
 public enum DifficultyCategory {
+    UNKNOWN,
+    SIMPLE,
     EASY,
-    MEDIUM,
-    HARD,
-    VERY_HARD;
+    INTERMEDIATE,
+    EXPERT;
 
     public string to_string ()
     {
         switch (this)
         {
+            case UNKNOWN:
+                return _("Unknown Difficulty");
+            case SIMPLE:
+                return _("Simple Difficulty");
             case EASY:
                 return _("Easy Difficulty");
-            case MEDIUM:
-                return _("Medium Difficulty");
-            case HARD:
-                return _("Hard Difficulty");
-            case VERY_HARD:
-                return _("Very Hard Difficulty");
+            case INTERMEDIATE:
+                return _("Intermediate Difficulty");
+            case EXPERT:
+                return _("Expert Difficulty");
+            default:
+                assert_not_reached ();
+        }
+    }
+
+    public static DifficultyCategory from_string (string input)
+    {
+        switch (input)
+        {
+            case "Unknown Difficulty":
+                return UNKNOWN;
+            case "Simple Difficulty":
+                return SIMPLE;
+            case "Easy Difficulty":
+                return EASY;
+            case "Intermediate Difficulty":
+                return INTERMEDIATE;
+            case "Expert Difficulty":
+                return EXPERT;
             default:
                 assert_not_reached ();
         }
diff --git a/lib/sudoku-generator.vala b/lib/sudoku-generator.vala
index 3558090..e5707f7 100644
--- a/lib/sudoku-generator.vala
+++ b/lib/sudoku-generator.vala
@@ -5,10 +5,10 @@ public class SudokuGenerator : Object
     public SudokuGenerator () {
     }
 
-    public SudokuBoard generate (DifficultyCategory category)
+    public SudokuBoard generate_board (DifficultyCategory category)
     {
         var board = new SudokuBoard ();
-        int[] puzzle = QQwing.generate_puzzle ((int) category + 1);
+        int[] puzzle = QQwing.generate_puzzle ((int) category);
 
         for (var row = 0; row < board.rows; row++)
             for (var col = 0; col < board.cols; col++)
@@ -17,7 +17,7 @@ public class SudokuGenerator : Object
                 if (val != 0)
                     board.insert (row, col, val, true);
             }
-        board.difficulty_rating = 0;
+        board.difficulty_category = category;
 
         return board;
     }
diff --git a/lib/sudoku-saver.vala b/lib/sudoku-saver.vala
index d9a4883..a162ba6 100644
--- a/lib/sudoku-saver.vala
+++ b/lib/sudoku-saver.vala
@@ -85,10 +85,8 @@ public class SudokuSaver : Object
         Json.Builder builder = new Json.Builder ();
 
         builder.begin_object ();
-        builder.set_member_name ("difficulty_rating");
-        builder.add_double_value (board.difficulty_rating);
         builder.set_member_name ("difficulty_category");
-        builder.add_string_value (board.get_difficulty_category ().to_string ());
+        builder.add_string_value (board.difficulty_category.to_string ());
         builder.set_member_name ("time_elapsed");
         builder.add_double_value (game.get_total_time_played ());
 
@@ -207,9 +205,9 @@ public class SudokuSaver : Object
         board.previous_played_time = reader.get_double_value ();
         reader.end_member ();
 
-        reader.read_member ("difficulty_rating");
+        reader.read_member ("difficulty_category");
         return_val_if_fail (reader.is_value (), null);
-        board.difficulty_rating = reader.get_double_value ();
+        board.difficulty_category = DifficultyCategory.from_string (reader.get_string_value ());
         reader.end_member ();
 
         return new SudokuGame (board);
diff --git a/src/gnome-sudoku.vala b/src/gnome-sudoku.vala
index 0ff3599..a5c8724 100644
--- a/src/gnome-sudoku.vala
+++ b/src/gnome-sudoku.vala
@@ -151,7 +151,7 @@ public class Sudoku : Gtk.Application
         else
         {
             var random_difficulty = (DifficultyCategory) Random.int_range (0, 4);
-            start_game (sudoku_store.get_random_board (random_difficulty));
+            start_game (generator.generate_board (random_difficulty));
         }
 
         window.show ();
@@ -166,13 +166,6 @@ public class Sudoku : Gtk.Application
 
     private void start_game (SudokuBoard board)
     {
-        var gen_board = generator.generate (board.get_difficulty_category ());
-        var gen_cells = gen_board.get_cells ();
-
-        gen_board.print ();
-        generator.print_stats (gen_board);
-
-        var difficulty_category = board.get_difficulty_category ();
         undo_action.set_enabled (false);
         redo_action.set_enabled (false);
         clear_action.set_enabled (!board.is_empty ());
@@ -181,7 +174,7 @@ public class Sudoku : Gtk.Application
             grid_box.remove (view);
         }
 
-        header_bar_subtitle = difficulty_category.to_string ();
+        header_bar_subtitle = board.difficulty_category.to_string ();
         back_cb ();
 
         game = new SudokuGame (board);
@@ -225,15 +218,16 @@ public class Sudoku : Gtk.Application
                 switch (response_id)
                 {
                     case 0:
-                        start_game (sudoku_store.get_random_board (difficulty_category));
+                        start_game (generator.generate_board (board.difficulty_category));
                         break;
                     case 1:
+                        // FIXME - This looks hack-ish
                         DifficultyCategory[] new_range = {};
-                        for (var i = 0; i < 4; i++)
-                            if (i != (int) difficulty_category)
+                        for (var i = 1; i < 5; i++)
+                            if (i != (int) board.difficulty_category)
                                 new_range += (DifficultyCategory) i;
 
-                        start_game (sudoku_store.get_random_board (new_range[Random.int_range (0, 3)]));
+                        start_game (generator.generate_board (new_range[Random.int_range (0, 3)]));
                         break;
                 }
                 dialog.destroy ();
@@ -260,7 +254,7 @@ public class Sudoku : Gtk.Application
         // has been set to integers corresponding to the enums.
         // Following line converts those ints to their DifficultyCategory
         var selected_difficulty = (DifficultyCategory) difficulty.get_int32 ();
-        start_game (sudoku_store.get_random_board (selected_difficulty));
+        start_game (generator.generate_board (selected_difficulty));
     }
 
     private void reset_cb ()
diff --git a/src/sudoku-printer.vala b/src/sudoku-printer.vala
index a6867a7..a184d43 100644
--- a/src/sudoku-printer.vala
+++ b/src/sudoku-printer.vala
@@ -71,7 +71,7 @@ public class SudokuPrinter : GLib.Object {
 
         foreach (SudokuBoard sudoku in sudokus_on_page)
         {
-            var label = sudoku.get_difficulty_category ().to_string ();
+            var label = sudoku.difficulty_category.to_string ();
             cr.set_font_size (12);
             cr.select_font_face ("Sans", Cairo.FontSlant.NORMAL, Cairo.FontWeight.BOLD);
             cr.set_source_rgb (0, 0, 0);
@@ -270,13 +270,13 @@ public class GamePrinter: GLib.Object {
 
         var saved_difficulty = (DifficultyCategory) settings.get_enum (DIFFICULTY_KEY_NAME);
 
-        if (saved_difficulty == DifficultyCategory.EASY)
+        if (saved_difficulty == DifficultyCategory.SIMPLE)
             easy_button.set_active (true);
-        else if (saved_difficulty == DifficultyCategory.MEDIUM)
+        else if (saved_difficulty == DifficultyCategory.EASY)
             medium_button.set_active (true);
-        else if (saved_difficulty == DifficultyCategory.HARD)
+        else if (saved_difficulty == DifficultyCategory.INTERMEDIATE)
             hard_button.set_active (true);
-        else if (saved_difficulty == DifficultyCategory.VERY_HARD)
+        else if (saved_difficulty == DifficultyCategory.EXPERT)
             very_hard_button.set_active (true);
 
         nsudokus_button = builder.get_object ("sudokusToPrintSpinButton") as SpinButton;
@@ -301,13 +301,13 @@ public class GamePrinter: GLib.Object {
         DifficultyCategory level;
 
         if (easy_button.get_active ())
-            level = DifficultyCategory.EASY;
+            level = DifficultyCategory.SIMPLE;
         else if (medium_button.get_active ())
-            level = DifficultyCategory.MEDIUM;
+            level = DifficultyCategory.EASY;
         else if (hard_button.get_active ())
-            level = DifficultyCategory.HARD;
+            level = DifficultyCategory.INTERMEDIATE;
         else if (very_hard_button.get_active ())
-            level = DifficultyCategory.VERY_HARD;
+            level = DifficultyCategory.EXPERT;
         else
             assert_not_reached ();
 
diff --git a/src/sudoku-store.vala b/src/sudoku-store.vala
index 8541e65..f306a89 100644
--- a/src/sudoku-store.vala
+++ b/src/sudoku-store.vala
@@ -4,10 +4,10 @@ using Gee;
 
 public class SudokuStore : Object
 {
+    private ArrayList<SudokuBoard> simple_boards = new ArrayList<SudokuBoard> ();
     private ArrayList<SudokuBoard> easy_boards = new ArrayList<SudokuBoard> ();
-    private ArrayList<SudokuBoard> medium_boards = new ArrayList<SudokuBoard> ();
-    private ArrayList<SudokuBoard> hard_boards = new ArrayList<SudokuBoard> ();
-    private ArrayList<SudokuBoard> very_hard_boards = new ArrayList<SudokuBoard> ();
+    private ArrayList<SudokuBoard> intermediate_boards = new ArrayList<SudokuBoard> ();
+    private ArrayList<SudokuBoard> expert_boards = new ArrayList<SudokuBoard> ();
 
     public SudokuStore () {
         try {
@@ -22,7 +22,7 @@ public class SudokuStore : Object
                     SudokuBoard board = new SudokuBoard();
                     board.set_from_string(line, " ");
 
-                    easy_boards.add(board);
+                    simple_boards.add(board);
                 }
             }
 
@@ -37,7 +37,7 @@ public class SudokuStore : Object
                     SudokuBoard board = new SudokuBoard();
                     board.set_from_string(line, " ");
 
-                    medium_boards.add(board);
+                    easy_boards.add(board);
                 }
             }
 
@@ -52,7 +52,7 @@ public class SudokuStore : Object
                     SudokuBoard board = new SudokuBoard();
                     board.set_from_string(line, " ");
 
-                    hard_boards.add(board);
+                    intermediate_boards.add(board);
                 }
             }
 
@@ -67,7 +67,7 @@ public class SudokuStore : Object
                     SudokuBoard board = new SudokuBoard();
                     board.set_from_string(line, " ");
 
-                    very_hard_boards.add(board);
+                    expert_boards.add(board);
                 }
             }
         } catch (Error e) {
@@ -75,36 +75,36 @@ public class SudokuStore : Object
         }
     }
 
-    public SudokuBoard get_random_easy_board()
+    public SudokuBoard get_random_simple_board()
     {
-        return easy_boards[Random.int_range(0, easy_boards.size)];
+        return simple_boards[Random.int_range(0, simple_boards.size)];
     }
 
-    public SudokuBoard get_random_medium_board()
+    public SudokuBoard get_random_easy_board()
     {
-        return medium_boards[Random.int_range(0, medium_boards.size)];
+        return easy_boards[Random.int_range(0, easy_boards.size)];
     }
 
-    public SudokuBoard get_random_hard_board()
+    public SudokuBoard get_random_intermediate_board()
     {
-        return hard_boards[Random.int_range(0, hard_boards.size)];
+        return intermediate_boards[Random.int_range(0, intermediate_boards.size)];
     }
 
-    public SudokuBoard get_random_very_hard_board()
+    public SudokuBoard get_random_expert_board()
     {
-        return very_hard_boards[Random.int_range(0, very_hard_boards.size)];
+        return expert_boards[Random.int_range(0, expert_boards.size)];
     }
 
     public SudokuBoard get_random_board(DifficultyCategory category)
     {
-        if (category == DifficultyCategory.EASY)
+        if (category == DifficultyCategory.SIMPLE)
+            return get_random_simple_board();
+        else if (category == DifficultyCategory.EASY)
             return get_random_easy_board();
-        else if (category == DifficultyCategory.MEDIUM)
-            return get_random_medium_board();
-        else if (category == DifficultyCategory.HARD)
-            return get_random_hard_board();
-        else if (category == DifficultyCategory.VERY_HARD)
-            return get_random_very_hard_board();
+        else if (category == DifficultyCategory.INTERMEDIATE)
+            return get_random_intermediate_board();
+        else if (category == DifficultyCategory.EXPERT)
+            return get_random_expert_board();
         else
             assert_not_reached();
     }
@@ -114,7 +114,7 @@ public class SudokuStore : Object
     public SudokuBoard[] get_boards_sorted (int number_of_boards, DifficultyCategory level, bool 
exclude_finished = false)
     {
         var boards = new ArrayList<SudokuBoard> ();
-        SudokuBoard[] sorted_boards = {};
+        SudokuBoard[] boards_array = {};
 
         while (boards.size < number_of_boards)
         {
@@ -124,17 +124,9 @@ public class SudokuStore : Object
             boards.add (board);
         }
 
-        boards.sort ((a, b) => {
-            if (a.difficulty_rating > b.difficulty_rating)
-                return 1;
-            if (a.difficulty_rating == b.difficulty_rating)
-                return 0;
-            return -1;
-        });
-
         foreach (SudokuBoard board in boards)
-            sorted_boards += board;
+            boards_array += board;
 
-        return sorted_boards;
+        return boards_array;
     }
 }


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