File indexing completed on 2024-04-28 04:04:48

0001 /***************************************************************************
0002  *   Copyright 2007      Francesco Rossi <redsh@email.it>                  *
0003  *   Copyright 2006-2007 Mick Kappenburg <ksudoku@kappendburg.net>         *
0004  *   Copyright 2006-2007 Johannes Bergmeier <johannes.bergmeier@gmx.net>   *
0005  *   Copyright 2015      Ian Wadham <iandw.au@gmail.com>                   *
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or modify  *
0008  *   it under the terms of the GNU General Public License as published by  *
0009  *   the Free Software Foundation; either version 2 of the License, or     *
0010  *   (at your option) any later version.                                   *
0011  *                                                                         *
0012  *   This program is distributed in the hope that it will be useful,       *
0013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0015  *   GNU General Public License for more details.                          *
0016  *                                                                         *
0017  *   You should have received a copy of the GNU General Public License     *
0018  *   along with this program; if not, write to the                         *
0019  *   Free Software Foundation, Inc.,                                       *
0020  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
0021  ***************************************************************************/
0022 
0023 #ifndef _KSUDOKUGAME_H_
0024 #define _KSUDOKUGAME_H_
0025 
0026 #include <QObject>
0027 #include <QUrl>
0028 #include "history.h"
0029 
0030 class SKGraph;
0031 
0032 class QWidget;
0033 
0034 namespace ksudoku {
0035 
0036 class Puzzle ;
0037 
0038 /**
0039  * The interface of a game. Since the game itself is a shared class you cannot connect to
0040  * the game. Use game->interface() to get a interface instance which you can use to connect
0041  * to.
0042  */
0043 class GameIFace : public QObject {
0044     Q_OBJECT
0045 
0046 public Q_SLOTS:
0047     virtual void undo() = 0;
0048     virtual void redo() = 0;
0049     virtual void addCheckpoint() = 0;
0050     virtual void undo2Checkpoint() = 0;
0051     
0052 Q_SIGNALS:
0053     void modified(bool isModified);
0054     void completed(bool isCorrect, const QTime& required, bool withHelp);
0055     void cellChange(int index);
0056     void fullChange();
0057     void cageChange(int cageNum, bool showLabel);
0058 };
0059 
0060 /**
0061  * @author Johannes Bergmeier
0062  *
0063  * A Game instance represents a interactive game.
0064  *
0065  * For simple puzzles use @c ksudoku::Puzzle.
0066  *
0067  * @see ksudoku::Puzzle
0068  */
0069 class Game {
0070 public:
0071     /**
0072      * Creates an invalid game
0073      */
0074     Game();
0075     
0076     /**
0077      * @param[in] puzzle The puzzle for this game
0078      * @note The Game takes ownership on @p puzzle
0079      */
0080     explicit Game(Puzzle* puzzle);
0081     
0082     /**
0083      * Copy constructor
0084      */
0085     Game(const Game& game);
0086     ~Game();
0087     
0088 public:
0089     // TODO improve this
0090     inline bool isValid() const { return static_cast<bool>(m_private); }
0091     
0092     /**
0093      * The nubmer of cells of the puzzle
0094      */
0095     int size() const;
0096     
0097     /**
0098      * Checks whether a set contains obvious errors
0099      *
0100      * @returns True when no error against the rules of the graph exists. This doesn't mean,
0101      *          that the values are suitable to solve the puzzle.
0102      */
0103     bool simpleCheck() const;
0104     
0105     ///@return pointer to current puzzle
0106     Puzzle* puzzle() const;
0107     
0108     /**
0109      * Gets the interface of the game. Use this if for connecting to signals or
0110      * slots of the game
0111      */
0112     GameIFace* interface() const;
0113     
0114     Game& operator=(const Game& game);
0115     
0116 public:
0117     /**
0118      * Restarts the game and marks it as unfinished
0119      */
0120     void restart();
0121 
0122     int order() const;
0123 
0124     int  value(int index) const;
0125     int  solution(int index) const;
0126     bool given(int index) const;
0127     bool marker(int index, int value) const;
0128     
0129     /**
0130      * Returns the state of a cell
0131      * @param[in] index The index of the cell
0132      */
0133     ksudoku::ButtonState buttonState(int index) const;
0134     CellInfo cellInfo(int index) const;
0135     
0136     /**
0137      * Sets one marker in a cell
0138      * @param[in] index The index of the cell
0139      * @param[in] val   The value of the marker
0140      * @param[in] state Whether the marker should be set or unset
0141      * @return Whether this function was executed successfully
0142      */
0143     bool setMarker(int index, int val, bool state);
0144     inline bool flipMarker(int index, int val);
0145     
0146     /**
0147      * @brief Sets the value of a cell
0148      * @param[in] index The index of the cell
0149      * @param[in] val   The new value of the cell
0150      */
0151     void setValue(int index, int val);
0152     
0153     /**
0154      * Sets whether cell @p index is @p given (A given cell is not changeable by the player).
0155      */
0156     void setGiven(int index, bool given);
0157 
0158     /**
0159      * Constructs a cage for a Mathdoku or Killer Sudoku puzzle which is
0160      * being entered in. Proceeds in steps of one keystroke at a time.
0161      *
0162      * @param[in] index The position of a cell.
0163      * @param[in] val   A digit for the value, an operator for the cage or
0164      *                  a code, e.g. add a cell to the cage or finish it.
0165      *
0166      * @return          True if the value was handled by addToCage(), false
0167      *                  if it should be processed by setValue(), as for a
0168      *                  Sudoku or Roxdoku puzzle.
0169      */
0170     bool addToCage (int pos, int val);
0171 
0172     /**
0173      * Gets the all current values of the game
0174      */
0175     const BoardContents allValues() const;
0176     
0177     /**
0178      * Gives one value in a randomly chosen cell.
0179      */
0180     bool giveHint();
0181 
0182     /**
0183      * Makes the whole puzzle given.
0184      */
0185     bool autoSolve();
0186 
0187     /**
0188      * Returns the time since game start, as a QTime object.
0189      */
0190     QTime time() const;
0191 
0192     /**
0193      * Returns the time since game start, as milliseconds. Used when saving
0194      * the elapsed time during a break in play.
0195      */
0196     int   msecsElapsed() const;
0197 
0198     /**
0199      * Sets the time since game start and restarts the clock. Used after a
0200      * break in play, e.g. when loading a saved game.
0201      */
0202     void  setTime(int msecs) const;
0203     
0204     /**
0205      * Sets the URL. Game itself doesn't use the URL, but remembers it for other users.
0206      */
0207     void setUrl(const QUrl& url);
0208     
0209     /**
0210      * Gets the URL. Game itself doesn't use the URL, but remembers it for other users.
0211      */
0212     QUrl getUrl() const;
0213     
0214     /**
0215      * Returns whether the user requested some hint.
0216      * @see giveHint(), autoSolve()
0217      */
0218     bool userHadHelp() const;
0219 
0220     /**
0221      * Returns whether the game was already solved.
0222      */
0223     bool wasFinished() const;
0224     
0225     /**
0226      * Sets whether the user had requested some hint.
0227      * @note This method is for loading/saving only
0228      * @see userHadHelp(), giveHint(), autoSolve()
0229      */
0230     void setUserHadHelp(bool hadHelp);
0231     
0232     // History
0233     
0234     bool canUndo() const;
0235     bool canRedo() const;
0236     
0237     /**
0238      * Adds an event to the history and performs it
0239      */
0240     void doEvent(const HistoryEvent& event);
0241     
0242     /**
0243      * Returns count of history events
0244      */
0245     int historyLength() const;
0246     
0247     /**
0248      * Returns the history event at position @p i
0249      */
0250     HistoryEvent historyEvent(int i) const;
0251 
0252     /**
0253      * Set the parent of message-box dialogs (used in data-entry of cages).
0254      */
0255     void setMessageParent (QWidget * messageParent);
0256     QWidget * messageParent();
0257 
0258     /*
0259      * Returns true if all values are filled in (not empty)
0260      * and in usable areas (as in Samurai); false otherwise
0261      */
0262     bool allValuesSetAndUsable() const;
0263 
0264 private:
0265     /**
0266      * When the game was finished this function emits a @c completed()
0267      */
0268     void checkCompleted();
0269 
0270     void finishCurrentCage (SKGraph * graph);
0271     void deleteCageAt (int pos, SKGraph * graph);
0272     bool validCell (int pos, SKGraph * graph);
0273     
0274 private:
0275     class Private;
0276     
0277     Private* m_private;
0278 };
0279 
0280 inline bool Game::flipMarker(int index, int val) {
0281     return setMarker(index, val, !marker(index, val));
0282 }
0283 
0284 }
0285 
0286 #endif