summaryrefslogtreecommitdiff
path: root/noncore/games/fifteen/fifteen.cpp
Unidiff
Diffstat (limited to 'noncore/games/fifteen/fifteen.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/fifteen/fifteen.cpp364
1 files changed, 364 insertions, 0 deletions
diff --git a/noncore/games/fifteen/fifteen.cpp b/noncore/games/fifteen/fifteen.cpp
new file mode 100644
index 0000000..293cd65
--- a/dev/null
+++ b/noncore/games/fifteen/fifteen.cpp
@@ -0,0 +1,364 @@
1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved.
3**
4** This file is part of Qtopia Environment.
5**
6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file.
10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15**
16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you.
18**
19**********************************************************************/
20
21#include "fifteen.h"
22
23#include <qpe/resource.h>
24#include <qpe/config.h>
25
26#include <qvbox.h>
27#include <qaction.h>
28#include <qlayout.h>
29#include <qpainter.h>
30#include <qpopupmenu.h>
31#include <qmessagebox.h>
32#include <qpe/qpetoolbar.h>
33#include <qpe/qpemenubar.h>
34#include <qstringlist.h>
35#include <qapplication.h>
36
37#include <stdlib.h>
38#include <time.h>
39
40FifteenMainWindow::FifteenMainWindow(QWidget *parent, const char* name)
41 : QMainWindow( parent, name )
42{
43 // random seed
44 srand(time(0));
45
46 setToolBarsMovable( FALSE );
47 QVBox *vbox = new QVBox( this );
48 PiecesTable *table = new PiecesTable( vbox );
49 setCentralWidget(vbox);
50
51 QPEToolBar *toolbar = new QPEToolBar(this);
52 toolbar->setHorizontalStretchable( TRUE );
53 addToolBar(toolbar);
54
55 QPEMenuBar *menubar = new QPEMenuBar( toolbar );
56 menubar->setMargin(0);
57
58 QPopupMenu *game = new QPopupMenu( this );
59
60 QWidget *spacer = new QWidget( toolbar );
61 spacer->setBackgroundMode( PaletteButton );
62 toolbar->setStretchableWidget( spacer );
63
64 QAction *a = new QAction( tr( "Randomize" ), Resource::loadPixmap( "new" ),
65 QString::null, 0, this, 0 );
66 connect( a, SIGNAL( activated() ), table, SLOT( slotRandomize() ) );
67 a->addTo( game );
68 a->addTo( toolbar );
69
70 a = new QAction( tr( "Solve" ), Resource::loadPixmap( "repeat" ),
71 QString::null, 0, this, 0 );
72 connect( a, SIGNAL( activated() ), table, SLOT( slotReset() ) );
73 a->addTo( game );
74 a->addTo( toolbar );
75
76 menubar->insertItem( tr( "Game" ), game );
77}
78
79PiecesTable::PiecesTable(QWidget* parent, const char* name )
80 : QTableView(parent, name), _menu(0), _randomized(false)
81{
82 // setup table view
83 setFrameStyle(StyledPanel | Sunken);
84 setBackgroundMode(NoBackground);
85 setMouseTracking(true);
86
87 setNumRows(4);
88 setNumCols(4);
89
90 // init arrays
91 initMap();
92 readConfig();
93 initColors();
94
95 // set font
96 QFont f = font();
97 f.setPixelSize(18);
98 f.setBold( TRUE );
99 setFont(f);
100}
101
102PiecesTable::~PiecesTable()
103{
104 writeConfig();
105}
106
107void PiecesTable::writeConfig()
108{
109 Config cfg("Fifteen");
110 cfg.setGroup("Game");
111 QStringList map;
112 for (unsigned int i = 0; i < 16; i++)
113 map.append( QString::number( _map[i] ) );
114 cfg.writeEntry("Map", map, '-');
115 cfg.writeEntry("Randomized", _randomized );
116}
117
118void PiecesTable::readConfig()
119{
120 Config cfg("Fifteen");
121 cfg.setGroup("Game");
122 QStringList map = cfg.readListEntry("Map", '-');
123 _randomized = cfg.readBoolEntry( "Randomized", FALSE );
124 unsigned int i = 0;
125 for ( QStringList::Iterator it = map.begin(); it != map.end(); ++it ) {
126 _map[i] = (*it).toInt();
127 i++;
128 if ( i > 15 ) break;
129 }
130}
131
132void PiecesTable::paintCell(QPainter *p, int row, int col)
133{
134 int w = cellWidth();
135 int h = cellHeight();
136 int x2 = w - 1;
137 int y2 = h - 1;
138
139 int number = _map[col + row * numCols()] + 1;
140
141 // draw cell background
142 if(number == 16)
143 p->setBrush(colorGroup().background());
144 else
145 p->setBrush(_colors[number-1]);
146 p->setPen(NoPen);
147 p->drawRect(0, 0, w, h);
148
149 // draw borders
150 if (height() > 40) {
151 p->setPen(colorGroup().text());
152 if(col < numCols()-1)
153 p->drawLine(x2, 0, x2, y2); // right border line
154
155 if(row < numRows()-1)
156 p->drawLine(0, y2, x2, y2); // bottom boder line
157 }
158
159 // draw number
160 if (number == 16) return;
161 p->setPen(black);
162 p->drawText(0, 0, x2, y2, AlignHCenter | AlignVCenter, QString::number(number));
163}
164
165void PiecesTable::resizeEvent(QResizeEvent *e)
166{
167 QTableView::resizeEvent(e);
168
169 setCellWidth(contentsRect().width()/ numRows());
170 setCellHeight(contentsRect().height() / numCols());
171}
172
173void PiecesTable::initColors()
174{
175 _colors.resize(numRows() * numCols());
176 for (int r = 0; r < numRows(); r++)
177 for (int c = 0; c < numCols(); c++)
178 _colors[c + r *numCols()] = QColor(255 - 70 * c,255 - 70 * r, 150);
179}
180
181void PiecesTable::initMap()
182{
183 _map.resize(16);
184 for (unsigned int i = 0; i < 16; i++)
185 _map[i] = i;
186
187 _randomized = false;
188}
189
190void PiecesTable::randomizeMap()
191{
192 initMap();
193 _randomized = true;
194 // find the free position
195 int pos = _map.find(15);
196
197 int move = 0;
198 while ( move < 333 ) {
199
200 int frow = pos / numCols();
201 int fcol = pos - frow * numCols();
202
203 // find click position
204 int row = rand()%4;
205 int col = rand()%4;
206
207 // sanity check
208 if ( row < 0 || row >= numRows() ) continue;
209 if ( col < 0 || col >= numCols() ) continue;
210 if ( row != frow && col != fcol ) continue;
211
212 move++;
213
214 // rows match -> shift pieces
215 if(row == frow) {
216
217 if (col < fcol) {
218 for(int c = fcol; c > col; c--) {
219 _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
220 }
221 }
222 else if (col > fcol) {
223 for(int c = fcol; c < col; c++) {
224 _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
225 }
226 }
227 }
228 // cols match -> shift pieces
229 else if (col == fcol) {
230
231 if (row < frow) {
232 for(int r = frow; r > row; r--) {
233 _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
234 }
235 }
236 else if (row > frow) {
237 for(int r = frow; r < row; r++) {
238 _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
239 }
240 }
241 }
242 // move free cell to click position
243 _map[pos=(col + row * numCols())] = 15;
244 repaint();
245 }
246}
247
248void PiecesTable::checkwin()
249{
250 if(!_randomized) return;
251
252 int i;
253 for (i = 0; i < 16; i++)
254 if(i != _map[i])
255 break;
256
257 if (i == 16) {
258 QMessageBox::information(this, tr("Fifteen Pieces"),
259 tr("Congratulations!\nYou win the game!"));
260 _randomized = FALSE;
261 }
262
263}
264
265void PiecesTable::slotRandomize()
266{
267 randomizeMap();
268}
269
270void PiecesTable::slotReset()
271{
272 initMap();
273 repaint();
274}
275
276void PiecesTable::mousePressEvent(QMouseEvent* e)
277{
278 QTableView::mousePressEvent(e);
279
280 if (e->button() == RightButton) {
281
282 // setup RMB pupup menu
283 if(!_menu) {
284 _menu = new QPopupMenu(this);
285 _menu->insertItem(tr("R&andomize Pieces"), mRandomize);
286 _menu->insertItem(tr("&Reset Pieces"), mReset);
287 _menu->adjustSize();
288 }
289
290 // execute RMB popup and check result
291 switch(_menu->exec(mapToGlobal(e->pos()))) {
292 case mRandomize:
293 randomizeMap();
294 break;
295 case mReset:
296 initMap();
297 repaint();
298 break;
299 default:
300 break;
301 }
302 }
303 else {
304 // GAME LOGIC
305
306 // find the free position
307 int pos = _map.find(15);
308 if(pos < 0) return;
309
310 int frow = pos / numCols();
311 int fcol = pos - frow * numCols();
312
313 // find click position
314 int row = findRow(e->y());
315 int col = findCol(e->x());
316
317 // sanity check
318 if (row < 0 || row >= numRows()) return;
319 if (col < 0 || col >= numCols()) return;
320 if ( row != frow && col != fcol ) return;
321
322 // valid move?
323 if(row != frow && col != fcol) return;
324
325 // rows match -> shift pieces
326 if(row == frow) {
327
328 if (col < fcol) {
329 for(int c = fcol; c > col; c--) {
330 _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
331 updateCell(row, c, false);
332 }
333 }
334 else if (col > fcol) {
335 for(int c = fcol; c < col; c++) {
336 _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
337 updateCell(row, c, false);
338 }
339 }
340 }
341 // cols match -> shift pieces
342 else if (col == fcol) {
343
344 if (row < frow) {
345 for(int r = frow; r > row; r--) {
346 _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
347 updateCell(r, col, false);
348 }
349 }
350 else if (row > frow) {
351 for(int r = frow; r < row; r++) {
352 _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
353 updateCell(r, col, false);
354 }
355 }
356 }
357 // move free cell to click position
358 _map[col + row * numCols()] = 15;
359 updateCell(row, col, false);
360
361 // check if the player wins with this move
362 checkwin();
363 }
364}