1 | /* |
2 | Copyright 2007 Dmitry Suzdalev <dimsuz@gmail.com> |
3 | Copyright 2010 Brian Croom <brian.s.croom@gmail.com> |
4 | |
5 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by |
7 | the Free Software Foundation; either version 2 of the License, or |
8 | (at your option) any later version. |
9 | |
10 | This program is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU General Public License |
16 | along with this program; if not, write to the Free Software |
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | */ |
19 | #ifndef MINEFIELDITEM_H |
20 | #define MINEFIELDITEM_H |
21 | |
22 | #include <QVector> |
23 | #include <QGraphicsObject> |
24 | #include <QPair> |
25 | #include <KRandomSequence> |
26 | |
27 | class KGameRenderer; |
28 | class CellItem; |
29 | class BorderItem; |
30 | |
31 | typedef QPair<int,int> FieldPos; |
32 | |
33 | /** |
34 | * Graphics item that represents MineField. |
35 | * It is composed of many (or little) of CellItems. |
36 | * This class is responsible of generation game field |
37 | * with given properties (num rows, num cols, num mines) and |
38 | * handling resizes |
39 | */ |
40 | class MineFieldItem : public QGraphicsObject |
41 | { |
42 | Q_OBJECT |
43 | public: |
44 | /** |
45 | * Constructor. |
46 | */ |
47 | explicit MineFieldItem(KGameRenderer* renderer); |
48 | /** |
49 | * Initializes game field: creates items, places them on positions, |
50 | * (re)sets some variables |
51 | * |
52 | * @param numRows number of rows |
53 | * @param numCols number of columns |
54 | * @param numMines number of mines |
55 | */ |
56 | void initField( int numRows, int numCols, int numMines ); |
57 | /** |
58 | * Resizes this graphics item so it fits in given rect |
59 | */ |
60 | void resizeToFitInRect(const QRectF& rect); |
61 | /** |
62 | * Reimplemented from QGraphicsItem |
63 | */ |
64 | QRectF boundingRect() const;// reimp |
65 | /** |
66 | * @return num rows in field |
67 | */ |
68 | int rowCount() const { return m_numRows; } |
69 | /** |
70 | * @return num columns in field |
71 | */ |
72 | int columnCount() const { return m_numCols; } |
73 | /** |
74 | * @return num mines in field |
75 | */ |
76 | int minesCount() const { return m_minesCount; } |
77 | |
78 | /** |
79 | * Minimal number of free positions on a field |
80 | */ |
81 | static const int MINIMAL_FREE = 10; |
82 | |
83 | signals: |
84 | void flaggedMinesCountChanged(int); |
85 | void firstClickDone(); |
86 | void gameOver(bool won); |
87 | private: |
88 | // reimplemented |
89 | virtual void mousePressEvent( QGraphicsSceneMouseEvent * ); |
90 | // reimplemented |
91 | virtual void mouseReleaseEvent( QGraphicsSceneMouseEvent * ); |
92 | // reimplemented |
93 | virtual void mouseMoveEvent( QGraphicsSceneMouseEvent * ); |
94 | |
95 | /** |
96 | * Returns cell item at (row,col). |
97 | * Always use this function instead hand-computing index in m_cells |
98 | */ |
99 | inline CellItem* itemAt(int row, int col) { return m_cells.at( row*m_numCols + col ); } |
100 | /** |
101 | * Overloaded one, which takes QPair |
102 | */ |
103 | inline CellItem* itemAt( const FieldPos& pos ) { return itemAt(pos.first,pos.second); } |
104 | /** |
105 | * Calculates (row,col) from given index in m_cells and returns them in QPair |
106 | */ |
107 | inline FieldPos rowColFromIndex(int idx) |
108 | { |
109 | int row = idx/m_numCols; |
110 | return qMakePair(row, idx - row*m_numCols); |
111 | } |
112 | /** |
113 | * Generates game field ensuring that cell at clickedIdx |
114 | * will be empty to allow the player quickly jump into the game. |
115 | * |
116 | * @param clickedIdx specifies index which should NOT have mine and be empty |
117 | */ |
118 | void generateField(int clickedIdx); |
119 | /** |
120 | * Returns all adjasent items for item at row, col |
121 | */ |
122 | QList<CellItem*> adjasentItemsFor(int row, int col); |
123 | /** |
124 | * Returns all valid adjasent row,col pairs for row, col |
125 | */ |
126 | QList<FieldPos> adjasentRowColsFor(int row, int col); |
127 | /** |
128 | * Checks if player lost the game |
129 | */ |
130 | void checkLost(); |
131 | /** |
132 | * Checks if player won the game |
133 | */ |
134 | void checkWon(); |
135 | /** |
136 | * Reveals all unmarked items containing mines |
137 | */ |
138 | void revealAllMines(); |
139 | /** |
140 | * Reimplemented from QGraphicsItem |
141 | */ |
142 | void paint( QPainter * painter, const QStyleOptionGraphicsItem*, QWidget * widget = 0 ); |
143 | /** |
144 | * Repositions all child cell items upon resizes |
145 | */ |
146 | void adjustItemPositions(); |
147 | /** |
148 | * Reveals all empty cells around cell at (row,col), |
149 | * until it found cells with digits (which are also revealed) |
150 | */ |
151 | void revealEmptySpace(int row, int col); |
152 | /** |
153 | * Sets up border items (positions and properties) |
154 | */ |
155 | void setupBorderItems(); |
156 | |
157 | void onItemRevealed(int row, int col); |
158 | // overload |
159 | void onItemRevealed(CellItem* item); |
160 | |
161 | // note: in member functions use itemAt (see above ) |
162 | // instead of hand-computing index from row & col! |
163 | // => not depend on how m_cells is represented |
164 | /** |
165 | * Array which holds all child cell items |
166 | */ |
167 | QVector<CellItem*> m_cells; |
168 | /** |
169 | * Array which holds border items |
170 | */ |
171 | QVector<BorderItem*> m_borders; |
172 | /** |
173 | * The width and height of minefield cells in scene coordinates |
174 | */ |
175 | int m_cellSize; |
176 | /** |
177 | * Number of field rows |
178 | */ |
179 | int m_numRows; |
180 | /** |
181 | * Number of field columns |
182 | */ |
183 | int m_numCols; |
184 | /** |
185 | * Number of mines in field |
186 | */ |
187 | int m_minesCount; |
188 | /** |
189 | * Number of flagged mines |
190 | */ |
191 | int m_flaggedMinesCount; |
192 | /** |
193 | * Random sequence used to generate mine positions |
194 | */ |
195 | KRandomSequence m_randomSeq; |
196 | /** |
197 | * row and column where mouse was pressed. |
198 | * (-1,-1) if it is already released |
199 | */ |
200 | FieldPos m_leftButtonPos; |
201 | FieldPos m_midButtonPos; |
202 | bool m_firstClick; |
203 | bool m_gameOver; |
204 | bool m_emulatingMidButton; |
205 | int m_numUnrevealed; |
206 | |
207 | KGameRenderer* m_renderer; |
208 | }; |
209 | |
210 | #endif |
211 | |