summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY4
-rw-r--r--README2
-rw-r--r--commands.cpp4
-rw-r--r--history.cpp124
-rw-r--r--history.h117
-rw-r--r--menu.cpp66
-rw-r--r--menu.h16
-rw-r--r--puzzle.cpp158
-rw-r--r--puzzle.h70
-rw-r--r--sudoku.cpp12
-rw-r--r--sudoku.h27
-rw-r--r--tools/Makefile6
12 files changed, 521 insertions, 85 deletions
diff --git a/HISTORY b/HISTORY
index 78ca753..c04d755 100644
--- a/HISTORY
+++ b/HISTORY
@@ -49,3 +49,7 @@ VDR plug-in 'Sudoku' Revision History
- Updated Italian language texts (thanks to Diego Pierotto).
- Set default values for "Show possible numbers as pattern/digits" to No,
because of problems with DXR3 (thanks to Ville Skyttä for reporting this).
+
+____-__-__: Version 0.3.0
+
+- Added history function.
diff --git a/README b/README
index 473773e..c093972 100644
--- a/README
+++ b/README
@@ -129,6 +129,8 @@ Commands menu:
descriptions.
- Save the puzzle Add the puzzle to the sudoku list, together with an
optional description.
+- Undo last action Go one step backward in the history.
+- Redo last action Go one step forward in the history.
- Reset the puzzle Reset the numbers in all cells, excluding the givens.
- Open setup menu Open the setup menu of the plug-in.
- Exit Quit the plug-in.
diff --git a/commands.cpp b/commands.cpp
index f95ad2a..029978c 100644
--- a/commands.cpp
+++ b/commands.cpp
@@ -17,7 +17,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: commands.cpp 116 2008-03-21 16:41:20Z tom $
+ * $Id: commands.cpp 140 2008-06-30 22:10:38Z tom $
*/
#include "commands.h"
@@ -41,6 +41,8 @@ CommandMenu::CommandMenu() :
Add(new Command(hk(tr("Generate a new puzzle")), &Menu::generate));
Add(new Command(hk(tr("Load a puzzle")), &Menu::load));
Add(new Command(hk(tr("Save the puzzle")), &Menu::save));
+ Add(new Command(hk(tr("Undo last action")), &Menu::undo));
+ Add(new Command(hk(tr("Redo last action")), &Menu::redo));
Add(new Command(hk(tr("Reset the puzzle")), &Menu::reset));
Add(new Command(hk(tr("Open setup menu")), &Menu::open_setup));
Add(new Command(hk(tr("Exit")), &Menu::exit));
diff --git a/history.cpp b/history.cpp
new file mode 100644
index 0000000..f715c1f
--- /dev/null
+++ b/history.cpp
@@ -0,0 +1,124 @@
+/*
+ * Sudoku: A plug-in for the Video Disk Recorder
+ *
+ * Copyright (C) 2008, Thomas Günther <tom@toms-cafe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id: history.cpp 140 2008-06-30 22:10:38Z tom $
+ */
+
+#include "history.h"
+#include "puzzle.h"
+
+using namespace Sudoku;
+
+
+//--- class Sudoku::History ----------------------------------------------------
+
+/** Constructor */
+History::History()
+{
+ executed = 0;
+}
+
+/** Destructor */
+History::~History()
+{
+ reset();
+}
+
+/** Reset the history. */
+void History::reset()
+{
+ for (unsigned int pos = history.size(); pos > 0; --pos)
+ {
+ // Remove object created outside of History
+ delete history.back();
+ history.pop_back();
+ }
+ executed = 0;
+}
+
+/** Current move in the history */
+Move* History::current()
+{
+ return history[executed - 1];
+}
+
+/** Add a new move */
+void History::add(Move* move)
+{
+ for (unsigned int pos = history.size(); pos > executed; --pos)
+ {
+ // Remove object created outside of History
+ delete history.back();
+ history.pop_back();
+ }
+ history.push_back(move);
+ ++executed;
+}
+
+/** Set previous move as current */
+void History::backward()
+{
+ if (movesExecuted())
+ --executed;
+}
+
+/** Set next move as current */
+void History::forward()
+{
+ if (movesToExecute())
+ ++executed;
+}
+
+/** Are there executed moves in the history */
+bool History::movesExecuted()
+{
+ return executed > 0;
+}
+
+/** Are there moves to execute in the history */
+bool History::movesToExecute()
+{
+ return executed < history.size();
+}
+
+
+//--- class Sudoku::SetMove ----------------------------------------------------
+
+/** Constructor */
+SetMove::SetMove(PuzzleGame& puzzle, unsigned int number) :
+ puzzle(puzzle)
+{
+ pos = puzzle.get_pos();
+ old_number = puzzle.get(pos);
+ new_number = number;
+}
+
+/** Do the move. */
+void SetMove::execute()
+{
+ puzzle.set(pos, new_number);
+ puzzle.set_pos(pos);
+}
+
+/** Undo the move. */
+void SetMove::takeBack()
+{
+ puzzle.set(pos, old_number);
+ puzzle.set_pos(pos);
+}
diff --git a/history.h b/history.h
new file mode 100644
index 0000000..f2af08f
--- /dev/null
+++ b/history.h
@@ -0,0 +1,117 @@
+/*
+ * Sudoku: A plug-in for the Video Disk Recorder
+ *
+ * Copyright (C) 2008, Thomas Günther <tom@toms-cafe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * $Id: history.h 140 2008-06-30 22:10:38Z tom $
+ */
+
+#ifndef VDR_SUDOKU_HISTORY_H
+#define VDR_SUDOKU_HISTORY_H
+
+#include "sudoku.h"
+
+
+namespace Sudoku
+{
+ class PuzzleGame;
+ class Pos;
+ class Move;
+ typedef Vector<Move*> Moves;
+
+
+ //--- class Sudoku::History --------------------------------------------------
+
+ class History
+ {
+ private:
+ Moves history;
+ unsigned int executed;
+
+ public:
+
+ /** Constructor */
+ History();
+
+ /** Destructor */
+ ~History();
+
+ /** Reset the history. */
+ void reset();
+
+ /** Current move in the history */
+ Move* current();
+
+ /** Add a new move */
+ void add(Move* move);
+
+ /** Set previous move as current */
+ void backward();
+
+ /** Set next move as current */
+ void forward();
+
+ /** Are there executed moves in the history */
+ bool movesExecuted();
+
+ /** Are there moves to execute in the history */
+ bool movesToExecute();
+ };
+
+
+ //--- class Sudoku::Move -----------------------------------------------------
+
+ class Move
+ {
+ public:
+
+ /** Destructor */
+ virtual ~Move() {};
+
+ /** Do the move */
+ virtual void execute() = 0;
+
+ /** Undo the move. */
+ virtual void takeBack() = 0;
+ };
+
+
+ //--- class Sudoku::SetMove --------------------------------------------------
+
+ class SetMove : public Move
+ {
+ private:
+ PuzzleGame& puzzle;
+ unsigned int pos;
+ unsigned int old_number;
+ unsigned int new_number;
+
+ public:
+
+ /** Constructor */
+ SetMove(PuzzleGame& puzzle, unsigned int number);
+
+ /** Do the move. */
+ void execute();
+
+ /** Undo the move. */
+ void takeBack();
+ };
+
+} // namespace Sudoku
+
+#endif // VDR_SUDOKU_HISTORY_H
diff --git a/menu.cpp b/menu.cpp
index 1954ef7..fcfdc92 100644
--- a/menu.cpp
+++ b/menu.cpp
@@ -17,7 +17,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: menu.cpp 124 2008-03-23 13:32:18Z tom $
+ * $Id: menu.cpp 140 2008-06-30 22:10:38Z tom $
*/
#include "menu.h"
@@ -65,9 +65,11 @@ using namespace Sudoku;
//--- class SudokuPlugin::Menu -------------------------------------------------
/** Constructor */
-Menu::Menu(cPlugin* plugin, const SetupData& setup, Puzzle& puzzle, Pos& curr) :
- cOsdObject(true), plugin(plugin), setup(setup), puzzle(puzzle), curr(curr)
+Menu::Menu(cPlugin* plugin, const SetupData& setup, PuzzleGame*& puzzle) :
+ cOsdObject(true), plugin(plugin), setup(setup), puzzle(puzzle)
{
+ if (puzzle == NULL)
+ puzzle = new PuzzleGame(setup.givens_count, setup.symmetric);
xPos = (720 - GRID_SIZE) / 2;
yPos = (576 - GRID_SIZE) / 2;
osd = NULL;
@@ -146,7 +148,7 @@ eOSState Menu::ProcessKey(eKeys key)
state = osContinue;
const char* sudoku = list_menu->get_selected_sudoku();
if (sudoku)
- puzzle = Puzzle(sudoku);
+ puzzle->load_from_dump(sudoku);
DELETENULL(list_menu);
Show();
}
@@ -187,23 +189,24 @@ eOSState Menu::ProcessKey(eKeys key)
}
else
{
+ Pos curr = puzzle->get_pos();
switch (key)
{
case kLeft:
case kLeft|k_Repeat:
- curr = curr.prev_col();
+ puzzle->set_pos(curr.prev_col());
break;
case kRight:
case kRight|k_Repeat:
- curr = curr.next_col();
+ puzzle->set_pos(curr.next_col());
break;
case kUp:
case kUp|k_Repeat:
- curr = curr.prev_row();
+ puzzle->set_pos(curr.prev_row());
break;
case kDown:
case kDown|k_Repeat:
- curr = curr.next_row();
+ puzzle->set_pos(curr.next_row());
break;
case k0:
case k1:
@@ -215,23 +218,23 @@ eOSState Menu::ProcessKey(eKeys key)
case k7:
case k8:
case k9:
- puzzle.set(curr, key - k0);
+ puzzle->set_with_history(key - k0);
break;
case kRed:
- puzzle.set(curr, puzzle.next_number(curr));
+ puzzle->set_with_history(puzzle->next_number(curr));
break;
case kGreen:
- puzzle.toggle_mark(curr);
+ puzzle->toggle_mark(curr);
break;
case kYellow:
- if (puzzle.next_free(curr) <= Pos::last())
- curr = puzzle.next_free(curr);
+ if (puzzle->next_free(curr) <= Pos::last())
+ puzzle->set_pos(puzzle->next_free(curr));
break;
default:
return osContinue;
}
}
- if (puzzle.solved())
+ if (puzzle->solved())
{
new_puzzle_request = true;
infoText = tr("Congratulations!\nPress OK to start a new puzzle");
@@ -245,7 +248,7 @@ eOSState Menu::ProcessKey(eKeys key)
/** Generate a new puzzle. */
eOSState Menu::generate()
{
- puzzle.generate(setup.givens_count, setup.symmetric);
+ puzzle->generate(setup.givens_count, setup.symmetric);
return osContinue;
}
@@ -266,15 +269,29 @@ eOSState Menu::save()
if (osd)
osd->Flush();
DELETENULL(osd);
- list_menu = new ListMenu(listfile, puzzle.get_dump());
+ list_menu = new ListMenu(listfile, puzzle->get_dump());
list_menu->Display();
return osUnknown;
}
+/** Undo last action. */
+eOSState Menu::undo()
+{
+ puzzle->backward();
+ return osContinue;
+}
+
+/** Redo last action. */
+eOSState Menu::redo()
+{
+ puzzle->forward();
+ return osContinue;
+}
+
/** Reset the puzzle. */
eOSState Menu::reset()
{
- puzzle.reset(setup.clear_marks);
+ puzzle->reset(setup.clear_marks);
return osContinue;
}
@@ -313,13 +330,13 @@ void Menu::paint()
for (Pos p = Pos::first(); p <= Pos::last(); p = p.next())
{
fg = NUMBER_FG, bg = NUMBER_BG;
- if (puzzle.given(p))
+ if (puzzle->given(p))
fg = GIVEN_FG, bg = GIVEN_BG;
- else if (puzzle.marked(p))
+ else if (puzzle->marked(p))
fg = MARKED_FG, bg = MARKED_BG;
- else if (setup.mark_errors && puzzle.error(p))
+ else if (setup.mark_errors && puzzle->error(p))
fg = ERROR_FG, bg = ERROR_BG;
- else if (setup.mark_ambiguous && puzzle.ambiguous(p))
+ else if (setup.mark_ambiguous && puzzle->ambiguous(p))
fg = AMBIG_FG, bg = AMBIG_BG;
fg = TRANS(fg, trans);
bg = TRANS(bg, trans);
@@ -330,9 +347,9 @@ void Menu::paint()
osd->DrawRectangle(x1, y1, x2, y2, bg);
// Paint the content of the cell.
- if (puzzle.get(p) != 0)
+ if (puzzle->get(p) != 0)
{
- char txt[2] = { '0' + puzzle.get(p), 0 };
+ char txt[2] = { '0' + puzzle->get(p), 0 };
osd->DrawText(x1, y1, txt, fg, bg, maxi_font,
CELL_SIZE, CELL_SIZE, taCenter);
}
@@ -340,7 +357,7 @@ void Menu::paint()
{
for (unsigned int n = 1; n <= DIM; ++n)
{
- if (puzzle.possible_number(p, n))
+ if (puzzle->possible_number(p, n))
{
int x3 = x1 + (((n - 1) % RDIM) * CELL_SIZE) / RDIM;
int y3 = y1 + (((n - 1) / RDIM) * CELL_SIZE) / RDIM;
@@ -368,6 +385,7 @@ void Menu::paint()
}
// Paint the cursor.
+ Pos curr = puzzle->get_pos();
bg = TRANS(CURSUR_COLOR, trans);
x1 = xPos + CELL_POS(curr.col()), y1 = yPos + CELL_POS(curr.row());
x2 = x1 + CELL_SIZE - 1, y2 = y1 + CELL_SIZE - 1;
diff --git a/menu.h b/menu.h
index c47f1b3..060b5dc 100644
--- a/menu.h
+++ b/menu.h
@@ -17,14 +17,14 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: menu.h 117 2008-03-21 17:57:50Z tom $
+ * $Id: menu.h 140 2008-06-30 22:10:38Z tom $
*/
#ifndef VDR_SUDOKU_MENU_H
#define VDR_SUDOKU_MENU_H
#include "sudoku.h"
-namespace Sudoku { class Puzzle; class Pos; }
+namespace Sudoku { class PuzzleGame; }
#include <vdr/config.h>
#include <vdr/osdbase.h>
#include <vdr/osd.h>
@@ -47,8 +47,7 @@ namespace SudokuPlugin
{
cPlugin* plugin;
const SetupData& setup;
- Sudoku::Puzzle& puzzle;
- Sudoku::Pos& curr;
+ Sudoku::PuzzleGame*& puzzle;
int xPos, yPos;
cOsd* osd;
Bitmap* info;
@@ -64,8 +63,7 @@ namespace SudokuPlugin
public:
/** Constructor */
- Menu(cPlugin* plugin, const SetupData& setup,
- Sudoku::Puzzle& puzzle, Sudoku::Pos& curr);
+ Menu(cPlugin* plugin, const SetupData& setup, Sudoku::PuzzleGame*& puzzle);
/** Destructor */
virtual ~Menu();
@@ -85,6 +83,12 @@ namespace SudokuPlugin
/** Save the puzzle. */
eOSState save();
+ /** Undo last action. */
+ eOSState undo();
+
+ /** Redo last action. */
+ eOSState redo();
+
/** Reset the puzzle. */
eOSState reset();
diff --git a/puzzle.cpp b/puzzle.cpp
index d0272fd..377de35 100644
--- a/puzzle.cpp
+++ b/puzzle.cpp
@@ -17,11 +17,12 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: puzzle.cpp 117 2008-03-21 17:57:50Z tom $
+ * $Id: puzzle.cpp 141 2008-07-05 14:52:52Z tom $
*/
#include "puzzle.h"
#include "generator.h"
+#include "history.h"
#include <string.h>
#include <assert.h>
@@ -34,14 +35,7 @@ using namespace Sudoku;
Numbers::Numbers(const char* dump) :
numbers_dump()
{
- reset();
-
- if (dump)
- for (unsigned int i = 0; *dump && *dump != ':' && i < SDIM; ++i, ++dump)
- if (*dump == '+')
- --i;
- else if (*dump > '0' && *dump - '0' <= DIM)
- content[i] = *dump - '0';
+ load_from_dump(dump);
assert(!numbers_dump);
}
@@ -102,6 +96,19 @@ unsigned int Numbers::get(Pos pos) const
return content[pos];
}
+/** Load numbers from a dump. */
+void Numbers::load_from_dump(const char* dump)
+{
+ reset();
+
+ if (dump)
+ for (unsigned int i = 0; *dump && *dump != ':' && i < SDIM; ++i, ++dump)
+ if (*dump == '+')
+ --i;
+ else if (*dump > '0' && *dump - '0' <= DIM)
+ content[i] = *dump - '0';
+}
+
//--- class Sudoku::Puzzle -----------------------------------------------------
@@ -109,26 +116,7 @@ unsigned int Numbers::get(Pos pos) const
Puzzle::Puzzle(const char* dump) :
puzzle_dump()
{
- // Set givens from the first part of the dump (before the first colon)
- givens = Numbers(dump);
- reset();
-
- // Set numbers from the second part (between the first and the second colon)
- if (dump)
- dump = strchr(dump, ':');
- if (dump)
- {
- Numbers numbers(++dump);
- for (unsigned int i = 0; i < SDIM; ++i)
- if (numbers.get(i) != 0)
- set(i, numbers.get(i));
- }
-
- // Set marks from the third part (behind the second colon)
- if (dump)
- dump = strchr(dump, ':');
- if (dump)
- marks = Numbers(++dump);
+ load_from_dump(dump);
assert(!puzzle_dump);
}
@@ -215,6 +203,31 @@ void Puzzle::set(Pos pos, unsigned int number)
}
}
+/** Load a puzzle from a dump. */
+void Puzzle::load_from_dump(const char* dump)
+{
+ // Set givens from the first part of the dump (before the first colon)
+ givens.load_from_dump(dump);
+ reset();
+
+ // Set numbers from the second part (between the first and the second colon)
+ if (dump)
+ dump = strchr(dump, ':');
+ if (dump)
+ {
+ Numbers numbers(++dump);
+ for (unsigned int i = 0; i < SDIM; ++i)
+ if (numbers.get(i) != 0)
+ set(i, numbers.get(i));
+ }
+
+ // Set marks from the third part (behind the second colon)
+ if (dump)
+ dump = strchr(dump, ':');
+ if (dump)
+ marks.load_from_dump(++dump);
+}
+
/** Generate a new puzzle. */
void Puzzle::generate(unsigned int givens_count, bool symmetric)
{
@@ -310,7 +323,7 @@ Pos Puzzle::next_free(Pos pos) const
}
/** Get the next possible number for this cell. */
-unsigned int Puzzle::next_number(Pos pos)
+unsigned int Puzzle::next_number(Pos pos) const
{
assert(pos <= Pos::last());
unsigned int n = get(pos);
@@ -325,14 +338,14 @@ unsigned int Puzzle::next_number(Pos pos)
}
/** Get the count of possible numbers for this cell. */
-unsigned int Puzzle::numbers_count(Pos pos)
+unsigned int Puzzle::numbers_count(Pos pos) const
{
assert(pos <= Pos::last());
return count[pos];
}
/** Is this number in this cell a possible number? */
-bool Puzzle::possible_number(Pos pos, unsigned int number)
+bool Puzzle::possible_number(Pos pos, unsigned int number) const
{
assert(pos <= Pos::last());
assert(0 <= number && number <= DIM);
@@ -371,3 +384,84 @@ bool Puzzle::correct(Pos pos) const
assert(pos <= Pos::last());
return count[pos] != 0 && numbers[pos][get(pos)];
}
+
+
+//--- class Sudoku::PuzzleGame -------------------------------------------------
+
+/** Constructor */
+PuzzleGame::PuzzleGame(const char* dump) :
+ Puzzle(dump), pos(Pos::center()), history(new History())
+{
+ assert(history);
+}
+
+/** Constructor with generation of a random puzzle */
+PuzzleGame::PuzzleGame(unsigned int givens_count, bool symmetric) :
+ Puzzle(givens_count, symmetric), pos(Pos::center()), history(new History())
+{
+ assert(history);
+}
+
+/** Destructor */
+PuzzleGame::~PuzzleGame()
+{
+ delete history;
+}
+
+/** Reset the puzzle (including marks). */
+void PuzzleGame::reset()
+{
+ reset(true);
+}
+
+/** Reset the puzzle (either with or without marks). */
+void PuzzleGame::reset(bool clear_marks)
+{
+ Puzzle::reset(clear_marks);
+ if (history)
+ history->reset();
+}
+
+/** Set the number into the current cell, write action into history. */
+void PuzzleGame::set_with_history(unsigned int number)
+{
+ if (history && !given(pos) && get(pos) != number)
+ {
+ history->add(new SetMove(*this, number));
+ history->current()->execute();
+ }
+ else
+ set(pos, number);
+}
+
+/** Get the position of the current cell. */
+Pos PuzzleGame::get_pos() const
+{
+ return pos;
+}
+
+/** Set the position of the current cell. */
+void PuzzleGame::set_pos(Pos new_pos)
+{
+ pos = new_pos;
+}
+
+/** Go one step backward in the history. */
+void PuzzleGame::backward()
+{
+ if (history->movesExecuted())
+ {
+ history->current()->takeBack();
+ history->backward();
+ }
+}
+
+/** Go one step forward in the history. */
+void PuzzleGame::forward()
+{
+ if (history->movesToExecute())
+ {
+ history->forward();
+ history->current()->execute();
+ }
+}
diff --git a/puzzle.h b/puzzle.h
index 201db86..78900c2 100644
--- a/puzzle.h
+++ b/puzzle.h
@@ -17,7 +17,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: puzzle.h 117 2008-03-21 17:57:50Z tom $
+ * $Id: puzzle.h 140 2008-06-30 22:10:38Z tom $
*/
#ifndef VDR_SUDOKU_PUZZLE_H
@@ -34,6 +34,8 @@
*/
namespace Sudoku
{
+ class History;
+
/** Regions, rows/columns and square dimension of the puzzle */
enum
@@ -82,6 +84,10 @@ namespace Sudoku
unsigned int content[SDIM];
mutable char* numbers_dump;
+ // prevent use of copy constructor and copy operator
+ Numbers(const Numbers& other);
+ Numbers& operator=(const Numbers& other);
+
public:
/** Constructor */
@@ -104,6 +110,9 @@ namespace Sudoku
/** Get the number from this cell. */
virtual unsigned int get(Pos pos) const;
+
+ /** Load numbers from a dump. */
+ virtual void load_from_dump(const char* dump);
};
@@ -118,6 +127,10 @@ namespace Sudoku
unsigned int count[SDIM];
mutable char* puzzle_dump;
+ // prevent use of copy constructor and copy operator
+ Puzzle(const Puzzle& other);
+ Puzzle& operator=(const Puzzle& other);
+
public:
/** Constructor */
@@ -141,6 +154,9 @@ namespace Sudoku
/** Set the number into this cell. */
virtual void set(Pos pos, unsigned int number);
+ /** Load a puzzle from a dump. */
+ virtual void load_from_dump(const char* dump);
+
/** Generate a new puzzle. */
void generate(unsigned int givens_count, bool symmetric = true);
@@ -175,13 +191,13 @@ namespace Sudoku
Pos next_free(Pos pos = Pos::last()) const;
/** Get the next possible number for this cell. */
- unsigned int next_number(Pos pos);
+ unsigned int next_number(Pos pos) const;
/** Get the count of possible numbers for this cell. */
- unsigned int numbers_count(Pos pos);
+ unsigned int numbers_count(Pos pos) const;
/** Is this number in this cell a possible number? */
- bool possible_number(Pos pos, unsigned int number);
+ bool possible_number(Pos pos, unsigned int number) const;
private:
@@ -192,6 +208,52 @@ private:
bool correct(Pos pos) const;
};
+
+ //--- class Sudoku::PuzzleGame -----------------------------------------------
+
+ /** Sudoku puzzle game */
+ class PuzzleGame : public Puzzle
+ {
+ Pos pos;
+ History* history;
+
+ // prevent use of copy constructor and copy operator
+ PuzzleGame(const PuzzleGame& other);
+ PuzzleGame& operator=(const PuzzleGame& other);
+
+ public:
+
+ /** Constructor */
+ PuzzleGame(const char* dump = 0);
+
+ /** Constructor with generation of a random puzzle */
+ PuzzleGame(unsigned int givens_count, bool symmetric = true);
+
+ /** Destructor */
+ virtual ~PuzzleGame();
+
+ /** Reset the puzzle (including marks). */
+ virtual void reset();
+
+ /** Reset the puzzle (either with or without marks). */
+ virtual void reset(bool clear_marks);
+
+ /** Set the number into the current cell, write action into history. */
+ virtual void set_with_history(unsigned int number);
+
+ /** Get the position of the current cell. */
+ Pos get_pos() const;
+
+ /** Set the position of the current cell. */
+ void set_pos(Pos new_pos);
+
+ /** Go one step backward in the history. */
+ void backward();
+
+ /** Go one step forward in the history. */
+ void forward();
+ };
+
} // namespace Sudoku
#endif // VDR_SUDOKU_PUZZLE_H
diff --git a/sudoku.cpp b/sudoku.cpp
index 95f45ee..10823e5 100644
--- a/sudoku.cpp
+++ b/sudoku.cpp
@@ -17,11 +17,11 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: sudoku.cpp 136 2008-04-06 02:01:00Z tom $
+ * $Id: sudoku.cpp 140 2008-06-30 22:10:38Z tom $
*/
#include "sudoku.h"
-#include "puzzle.h"
+namespace Sudoku { class PuzzleGame; }
#include "menu.h"
#include "setup.h"
#include "i18n.h"
@@ -50,8 +50,7 @@ namespace SudokuPlugin
class Plugin : public cPlugin
{
SetupData setup;
- Sudoku::Puzzle puzzle;
- Sudoku::Pos curr;
+ Sudoku::PuzzleGame* puzzle;
public:
@@ -94,8 +93,7 @@ bool Plugin::Start()
#if VDRVERSNUM < 10507
RegisterI18n(Phrases);
#endif
- puzzle.generate(setup.givens_count, setup.symmetric);
- curr = curr.center();
+ puzzle = NULL;
return true;
}
@@ -105,7 +103,7 @@ bool Plugin::Start()
*/
cOsdObject* Plugin::MainMenuAction()
{
- return new Menu(this, setup, puzzle, curr);
+ return new Menu(this, setup, puzzle);
}
/** Setup menu page to adjust the setup parameters of the plugin
diff --git a/sudoku.h b/sudoku.h
index a80df3c..3958dff 100644
--- a/sudoku.h
+++ b/sudoku.h
@@ -1,7 +1,7 @@
/*
* Sudoku: A plug-in for the Video Disk Recorder
*
- * Copyright (C) 2005-2007, Thomas Günther <tom@toms-cafe.de>
+ * Copyright (C) 2005-2008, Thomas Günther <tom@toms-cafe.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,22 +17,33 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
- * $Id: sudoku.h 106 2007-12-03 23:28:24Z tom $
+ * $Id: sudoku.h 140 2008-06-30 22:10:38Z tom $
*/
#ifndef VDR_SUDOKU_H
#define VDR_SUDOKU_H
+#include <vector>
+
+
+namespace Sudoku
+{
+ //--- template class Vector --------------------------------------------------
+
+ template <class T> class Vector : public std::vector<T> {};
+
#ifdef USE_RAND
#include <stdlib.h>
#include <time.h>
-/** Random number 0 .. max-1 */
-static unsigned int rand(unsigned int max)
-{
- static unsigned int seed = time(NULL);
- return (unsigned int)((double)max * rand_r(&seed) / (RAND_MAX + 1.0));
-}
+ /** Random number 0 .. max-1 */
+ static unsigned int rand(unsigned int max)
+ {
+ static unsigned int seed = time(NULL);
+ return (unsigned int)((double)max * rand_r(&seed) / (RAND_MAX + 1.0));
+ }
#endif // USE_RAND
+} // namespace Sudoku
+
#endif // VDR_SUDOKU_H
diff --git a/tools/Makefile b/tools/Makefile
index ca9f65a..edd5432 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -1,7 +1,7 @@
#
# Sudoku: A plug-in for the Video Disk Recorder
#
-# Copyright (C) 2005-2007, Thomas Günther <tom@toms-cafe.de>
+# Copyright (C) 2005-2008, Thomas Günther <tom@toms-cafe.de>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
-# $Id: Makefile 106 2007-12-03 23:28:24Z tom $
+# $Id: Makefile 140 2008-06-30 22:10:38Z tom $
# Define STATIC_LINK=1 to force static linking
#STATIC_LINK = 1
@@ -27,7 +27,7 @@
PROGRAM = sudoku_generator
-SRCS = ../puzzle.cpp ../generator.cpp ../solver.cpp ../backtrack.cpp
+SRCS = ../puzzle.cpp ../generator.cpp ../solver.cpp ../backtrack.cpp ../history.cpp
VERSION = $(shell sed -ne '/static .* VERSION *=/s/^.*"\(.*\)".*$$/\1/p' \
../sudoku.cpp)