File indexing completed on 2025-04-20 03:48:21
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