File indexing completed on 2024-04-28 04:05:21
0001 /* 0002 SPDX-FileCopyrightText: 2015 Jakob Gruber <jakob.gruber@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "boardstate.h" 0008 0009 #include <algorithm> 0010 #include <assert.h> 0011 0012 BoardState::BoardState(int width, int height) : Board(width, height), m_box_count(0) 0013 { 0014 } 0015 0016 void BoardState::set(int x, int y, State state) { 0017 assertInbounds(x, y); 0018 0019 const int i = xy_to_i(x, y); 0020 0021 if (m_state[i] == state) { 0022 return; 0023 } 0024 0025 UndoAction undo; 0026 undo.x = x; 0027 undo.y = y; 0028 undo.state = m_state[i]; 0029 m_undo_queue.push(undo); 0030 Q_EMIT undoStackSizeChanged(m_undo_queue.size()); 0031 0032 updateBoxCount(m_state[i], state); 0033 m_state[i] = state; 0034 } 0035 0036 void BoardState::updateBoxCount(Board::State prev, Board::State next) { 0037 if (prev == Board::Box && next != Board::Box) { 0038 m_box_count--; 0039 } else if (prev != Board::Box && next == Board::Box) { 0040 m_box_count++; 0041 } 0042 } 0043 0044 QPoint BoardState::undo() { 0045 if (m_undo_queue.empty()) { 0046 return QPoint(); 0047 } 0048 0049 UndoAction undo = m_undo_queue.pop(); 0050 Q_EMIT undoStackSizeChanged(m_undo_queue.size()); 0051 0052 const int i = xy_to_i(undo.x, undo.y); 0053 0054 updateBoxCount(m_state[i], undo.state); 0055 m_state[i] = undo.state; 0056 0057 /* if we undo past a saved state, remove it */ 0058 0059 if (!m_saved_states.isEmpty() 0060 && m_undo_queue.size() < m_saved_states.top()) { 0061 (void)m_saved_states.pop(); 0062 Q_EMIT saveStackSizeChanged(m_saved_states.size()); 0063 } 0064 0065 return QPoint(undo.x, undo.y); 0066 } 0067 0068 void BoardState::saveState() { 0069 0070 /* a saved state consists only of the size of 0071 the undo queue to rewind to to restore a specific state */ 0072 0073 int size = m_undo_queue.size(); 0074 if (!m_saved_states.isEmpty() && m_saved_states.top() == size) { 0075 return; 0076 } 0077 m_saved_states.push(size); 0078 Q_EMIT saveStackSizeChanged(m_saved_states.size()); 0079 } 0080 0081 void BoardState::loadState() { 0082 0083 if (m_saved_states.isEmpty()) { 0084 return; 0085 } 0086 0087 /* rewind the undo queue until its size equals 0088 the saved queue size */ 0089 0090 int size = m_saved_states.pop(); 0091 assert(size <= m_undo_queue.size()); 0092 Q_EMIT saveStackSizeChanged(m_saved_states.size()); 0093 0094 while (size < m_undo_queue.size()) { 0095 (void)undo(); 0096 } 0097 } 0098 0099 int BoardState::currentStateAge() const { 0100 if (m_saved_states.isEmpty()) { 0101 return m_undo_queue.size(); 0102 } 0103 return m_undo_queue.size() - m_saved_states.top(); 0104 } 0105 0106 void BoardState::replace(State prev, State next) { 0107 for (int i = 0; i < m_state.size(); i++) { 0108 if (m_state[i] == prev) { 0109 m_state[i] = next; 0110 } 0111 } 0112 } 0113 0114 void BoardState::solve(const Board *board) { 0115 assert(board->width() == width()); 0116 assert(board->height() == height()); 0117 0118 for (int y = 0; y < height(); y++) { 0119 for (int x = 0; x < width(); x++) { 0120 m_state[xy_to_i(x, y)] = board->get(x, y); 0121 } 0122 } 0123 0124 replace(Board::Nothing, Board::Cross); 0125 } 0126 0127 #include "moc_boardstate.cpp"