1 /*************************************************************************** 2 * Copyright 2006-2007 Johannes Bergmeier <johannes.bergmeier@gmx.net> * 3 * * 4 * This program is free software; you can redistribute it and/or modify * 5 * it under the terms of the GNU General Public License as published by * 6 * the Free Software Foundation; either version 2 of the License, or * 7 * (at your option) any later version. * 8 * * 9 * This program is distributed in the hope that it will be useful, * 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 12 * GNU General Public License for more details. * 13 * * 14 * You should have received a copy of the GNU General Public License * 15 * along with this program; if not, write to the * 16 * Free Software Foundation, Inc., * 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * 18 ***************************************************************************/ 19 20 #ifndef _KSUDOKUHISTORY_H_ 21 #define _KSUDOKUHISTORY_H_ 22 23 #include <QBitArray> 24 #include <QVector> 25 26 #include "globals.h" 27 #include "ksudoku_types.h" 28 29 30 namespace ksudoku { 31 32 class CellInfo { 33 public: CellInfo()34 inline CellInfo() 35 : m_state(Marker), m_value(0), m_markers() 36 { } CellInfo(ButtonState state,int value)37 inline CellInfo(ButtonState state, int value) 38 : m_state(state), m_value(value), m_markers() 39 { } CellInfo(const QBitArray & markers)40 inline CellInfo(const QBitArray& markers) 41 : m_state(Marker), m_value(0), m_markers(markers) 42 { } CellInfo(const CellInfo & info)43 inline CellInfo(const CellInfo& info) 44 : m_state(info.m_state), m_value(info.m_value), m_markers(info.m_markers) 45 { } state()46 inline ButtonState state() const { return m_state; } value()47 inline int value() const { return m_value; } markers()48 inline const QBitArray markers() const { return m_markers; } marker(int value)49 inline bool marker(int value) const { 50 if(value > m_markers.size() || value == 0) return false; 51 return m_markers[value-1]; 52 } 53 inline CellInfo& operator=(const CellInfo& info) { 54 m_state = info.m_state; 55 m_value = info.m_value; 56 m_markers = info.m_markers; 57 return *this; 58 } 59 private: 60 ButtonState m_state; 61 int m_value; 62 QBitArray m_markers; 63 }; 64 65 class PuzzleState { 66 public: PuzzleState()67 PuzzleState() { 68 } PuzzleState(int size,int values)69 PuzzleState(int size, int values) 70 : m_markers(values), m_values(size, 0), m_given(size) 71 72 { 73 for(int i = 0; i < values; i++) { 74 m_markers[i] = QBitArray(size); 75 } 76 } 77 public: reset()78 void reset() { 79 for(int i = 0; i < m_markers.size(); i++) { 80 QBitArray &array = m_markers[i]; 81 for(int j = 0; j < array.size(); j++) 82 array.clearBit(j); 83 } 84 for(int i = 0; i < m_values.size(); i++) { 85 m_values[i] = 0; 86 m_given.clearBit(i); 87 } 88 } setMarker(int index,int value,bool status)89 inline void setMarker(int index, int value, bool status) 90 { 91 if(value == 0 || value > m_markers.size()) 92 return; 93 m_markers[value-1].setBit(index, status); 94 } resetMarkers(int index)95 inline void resetMarkers(int index) 96 { 97 for(int i = 0; i < m_markers.size(); i++) { 98 m_markers[i].clearBit(index); 99 } 100 } setMarkers(int index,const QBitArray & values)101 inline void setMarkers(int index, const QBitArray& values) { 102 if(values.size() == 0) { 103 resetMarkers(index); 104 return; 105 } 106 for(int i = 0; i < m_markers.size(); i++) { 107 m_markers[i].setBit(index, values[i]); 108 } 109 } marker(int index,int value)110 inline bool marker(int index, int value) const 111 { 112 if(value == 0 || value > m_markers.size()) 113 return false; 114 return m_markers[value-1][index]; 115 } markers(int index)116 inline QBitArray markers(int index) const { 117 QBitArray array(m_markers.size()); 118 for(int i = 0; i < m_markers.size(); i++) { 119 array.setBit(i, m_markers[i][index]); 120 } 121 return array; 122 } setGiven(int index,bool given)123 inline void setGiven(int index, bool given) 124 { 125 m_given.setBit(index, given); 126 } setValue(int index,int value)127 inline void setValue(int index, int value) 128 { 129 m_values[index] = value; 130 } setValue(int index,int value,bool given)131 inline void setValue(int index, int value, bool given) 132 { 133 m_given.setBit(index, given); 134 m_values[index] = value; 135 } given(int index)136 inline bool given(int index) const 137 { 138 return m_given[index]; 139 } value(int index)140 inline int value(int index) const 141 { 142 return m_values[index]; 143 } 144 // inline void operator=(const PuzzleState& state) { 145 // m_markers = state.m_markers; 146 // m_values = state.m_values; 147 // m_given = state.m_given; 148 // } detach()149 inline void detach() { 150 for(int i = 0; i < m_markers.size(); ++i) { 151 // Detach m_markers 152 // This actually is only needed once and not every loop 153 // However this way it's more secure (m_markers.size() might be 0) 154 m_markers[i] = m_markers[i]; 155 156 // Detach from shared bit array data 157 m_markers[i].detach(); 158 } 159 m_values.detach(); 160 m_given.detach(); 161 } allValues()162 inline const BoardContents allValues() const { 163 return m_values; 164 } 165 /** 166 *@note Use this method only to get size of puzzle when operating 167 * directly on the puzzle state. 168 */ size()169 inline int size() const { 170 return m_values.size(); 171 } 172 173 private: 174 QVector<QBitArray> m_markers; 175 BoardContents m_values; 176 QBitArray m_given; 177 }; 178 179 180 class HistoryEvent { 181 public: 182 HistoryEvent(); 183 HistoryEvent(int index, const CellInfo& changedCell); 184 explicit HistoryEvent(const PuzzleState& newState); 185 186 bool applyTo(PuzzleState& puzzle); 187 bool undoOn(PuzzleState& puzzle) const; 188 bool redoOn(PuzzleState& puzzle) const; 189 cellIndices()190 const QVector<int>& cellIndices() const { return m_cellsIndex; } cellChanges()191 const QVector<CellInfo>& cellChanges() const { return m_cellsAfter; } 192 193 private: 194 void setPuzzleCell(PuzzleState& puzzle, int index, const CellInfo& cell) const; 195 CellInfo getPuzzleCell(const PuzzleState& puzzle, int index) const; 196 197 private: 198 QVector<int> m_cellsIndex; 199 QVector<CellInfo> m_cellsBefore; 200 QVector<CellInfo> m_cellsAfter; 201 }; 202 203 } 204 205 #endif 206