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

0001 /***************************************************************************
0002  *   Copyright 2006-2007 Johannes Bergmeier <johannes.bergmeier@gmx.net>   *
0003  *                                                                         *
0004  *   This program is free software; you can redistribute it and/or modify  *
0005  *   it under the terms of the GNU General Public License as published by  *
0006  *   the Free Software Foundation; either version 2 of the License, or     *
0007  *   (at your option) any later version.                                   *
0008  *                                                                         *
0009  *   This program is distributed in the hope that it will be useful,       *
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0012  *   GNU General Public License for more details.                          *
0013  *                                                                         *
0014  *   You should have received a copy of the GNU General Public License     *
0015  *   along with this program; if not, write to the                         *
0016  *   Free Software Foundation, Inc.,                                       *
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
0018  ***************************************************************************/
0019 
0020 #ifndef _KSUDOKUHISTORY_H_
0021 #define _KSUDOKUHISTORY_H_
0022 
0023 #include <QBitArray>
0024 #include <QList>
0025 
0026 #include "globals.h"
0027 #include "ksudoku_types.h"
0028 
0029 
0030 namespace ksudoku {
0031     
0032 class CellInfo {
0033     public:
0034         inline CellInfo()
0035           : m_state(Marker), m_value(0), m_markers()
0036         { }
0037         inline CellInfo(ButtonState state, int value)
0038           : m_state(state), m_value(value), m_markers()
0039         { }
0040         inline CellInfo(const QBitArray& markers)
0041           : m_state(Marker), m_value(0), m_markers(markers)
0042         { }
0043         inline CellInfo(const CellInfo& info) 
0044           : m_state(info.m_state), m_value(info.m_value), m_markers(info.m_markers)
0045         { }
0046         inline ButtonState state() const { return m_state; }
0047         inline int value() const { return m_value; }
0048         inline const QBitArray markers() const { return m_markers; }
0049         inline bool marker(int value) const {
0050             if(value > m_markers.size() || value == 0) return false;
0051             return m_markers[value-1];
0052         }
0053         inline CellInfo& operator=(const CellInfo& info) {
0054             m_state = info.m_state;
0055             m_value = info.m_value;
0056             m_markers = info.m_markers;
0057             return *this;
0058         }
0059     private:
0060         ButtonState m_state;
0061         int m_value;
0062         QBitArray m_markers;
0063 };
0064 
0065 class PuzzleState {
0066 public:
0067     PuzzleState() {
0068     }
0069     PuzzleState(int size, int values)
0070       : m_markers(values), m_values(size, 0), m_given(size)
0071   
0072     {
0073         for(int i = 0; i < values; i++) {
0074             m_markers[i] = QBitArray(size);
0075         }
0076     }
0077 public:
0078     void reset() {
0079         for(int i = 0; i < m_markers.size(); i++) {
0080             QBitArray &array = m_markers[i];
0081             for(int j = 0; j < array.size(); j++)
0082                 array.clearBit(j);
0083         }
0084         for(int i = 0; i < m_values.size(); i++) {
0085             m_values[i] = 0;
0086             m_given.clearBit(i);
0087         }
0088     }
0089     inline void setMarker(int index, int value, bool status)
0090     {
0091         if(value == 0 || value > m_markers.size())
0092             return;
0093         m_markers[value-1].setBit(index, status);
0094     }
0095     inline void resetMarkers(int index)
0096     {
0097         for(int i = 0; i < m_markers.size(); i++) {
0098             m_markers[i].clearBit(index);
0099         }
0100     }
0101     inline void setMarkers(int index, const QBitArray& values) {
0102         if(values.size() == 0) {
0103             resetMarkers(index);
0104             return;
0105         }
0106         for(int i = 0; i < m_markers.size(); i++) {
0107             m_markers[i].setBit(index, values[i]);
0108         }
0109     }
0110     inline bool marker(int index, int value) const
0111     {
0112         if(value == 0 || value > m_markers.size())
0113             return false;
0114         return m_markers[value-1][index];
0115     }
0116     inline QBitArray markers(int index) const {
0117         QBitArray array(m_markers.size());
0118         for(int i = 0; i < m_markers.size(); i++) {
0119             array.setBit(i, m_markers[i][index]);
0120         }
0121         return array;
0122     }
0123     inline void setGiven(int index, bool given)
0124     {
0125         m_given.setBit(index, given);
0126     }
0127     inline void setValue(int index, int value)
0128     {
0129         m_values[index] = value;
0130     }
0131     inline void setValue(int index, int value, bool given)
0132     {
0133         m_given.setBit(index, given);
0134         m_values[index] = value;
0135     }
0136     inline bool given(int index) const
0137     {
0138         return m_given[index];
0139     }
0140     inline int value(int index) const
0141     {
0142         return m_values[index];
0143     }
0144 //  inline void operator=(const PuzzleState& state) {
0145 //      m_markers = state.m_markers;
0146 //      m_values = state.m_values;
0147 //      m_given = state.m_given;
0148 //  }
0149     inline void detach() {
0150         for(int i = 0; i < m_markers.size(); ++i) {
0151             // Detach m_markers
0152             // This actually is only needed once and not every loop
0153             // However this way it's more secure (m_markers.size() might be 0)
0154             m_markers[i] = m_markers[i];
0155             
0156             // Detach from shared bit array data
0157             m_markers[i].detach();
0158         }
0159         m_values.detach();
0160         m_given.detach();
0161     }
0162     inline const BoardContents allValues() const {
0163         return m_values;
0164     }
0165     /**
0166      *@note Use this method only to get size of puzzle when operating
0167      * directly on the puzzle state.
0168      */
0169     inline int size() const {
0170         return m_values.size();
0171     }
0172     
0173 private:
0174     QList<QBitArray> m_markers;
0175     BoardContents m_values;
0176     QBitArray m_given;
0177 };
0178 
0179 
0180 class HistoryEvent {
0181     public:
0182         HistoryEvent();
0183         HistoryEvent(int index, const CellInfo& changedCell);
0184         explicit HistoryEvent(const PuzzleState& newState);
0185         
0186         bool applyTo(PuzzleState& puzzle);
0187         bool undoOn(PuzzleState& puzzle) const;
0188         bool redoOn(PuzzleState& puzzle) const;
0189         
0190         const QList<int>& cellIndices() const { return m_cellsIndex; }
0191         const QList<CellInfo>& cellChanges() const { return m_cellsAfter; }
0192         
0193     private:
0194         void setPuzzleCell(PuzzleState& puzzle, int index, const CellInfo& cell) const;
0195         CellInfo getPuzzleCell(const PuzzleState& puzzle, int index) const;
0196         
0197     private:
0198         QList<int> m_cellsIndex;
0199         QList<CellInfo> m_cellsBefore;
0200         QList<CellInfo> m_cellsAfter;
0201 };
0202 
0203 }
0204 
0205 #endif