summaryrefslogtreecommitdiff
Unidiff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/tictac/tictac.cpp282
1 files changed, 143 insertions, 139 deletions
diff --git a/noncore/games/tictac/tictac.cpp b/noncore/games/tictac/tictac.cpp
index 20cc942..3d727ac 100644
--- a/noncore/games/tictac/tictac.cpp
+++ b/noncore/games/tictac/tictac.cpp
@@ -1,377 +1,381 @@
1/**************************************************************************** 1/****************************************************************************
2** $Id$ 2 ** $Id$
3** 3 **
4** Copyright (C) 1992-2000 Trolltech AS. All rights reserved. 4 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
5** 5 **
6** This file is part of an example program for Qt. This example 6 ** This file is part of an example program for Qt. This example
7** program may be used, distributed and modified without limitation. 7 ** program may be used, distributed and modified without limitation.
8** 8 **
9*****************************************************************************/ 9 *****************************************************************************/
10 10
11#include "tictac.h" 11#include "tictac.h"
12#include <qpe/qpeapplication.h> 12#include <qpe/qpeapplication.h>
13#include <qpainter.h> 13#include <qpainter.h>
14#include <qdrawutil.h> 14#include <qdrawutil.h>
15#include <qcombobox.h> 15#include <qcombobox.h>
16#include <qcheckbox.h> 16#include <qcheckbox.h>
17#include <qlabel.h> 17#include <qlabel.h>
18#include <qlayout.h> 18#include <qlayout.h>
19 #include <stdlib.h> // rand() function 19#include <stdlib.h> // rand() function
20 #include <qdatetime.h> // seed for rand() 20#include <qdatetime.h> // seed for rand()
21#include <qstringlist.h> //needed for proper internationalization
21 22
22 23
23//*************************************************************************** 24//***************************************************************************
24//* TicTacButton member functions 25//* TicTacButton member functions
25//*************************************************************************** 26//***************************************************************************
26 27
27// -------------------------------------------------------------------------- 28// --------------------------------------------------------------------------
28// Creates a TicTacButton 29// Creates a TicTacButton
29// 30//
30 31
31TicTacButton::TicTacButton( QWidget *parent ) : QPushButton( parent ) 32TicTacButton::TicTacButton( QWidget *parent ) : QPushButton( parent )
32{ 33{
33 t = Blank; // initial type 34 t = Blank; // initial type
34} 35}
35 36
36// -------------------------------------------------------------------------- 37// --------------------------------------------------------------------------
37// Paints TicTacButton 38// Paints TicTacButton
38// 39//
39 40
40void TicTacButton::drawButtonLabel( QPainter *p ) 41void TicTacButton::drawButtonLabel( QPainter *p )
41{ 42{
42 QRect r = rect(); 43 QRect r = rect();
43 p->setPen( QPen( white,2 ) ); // set fat pen 44 p->setPen( QPen( white,2 ) ); // set fat pen
44 if ( t == Circle ) { 45 if ( t == Circle ) {
45 p->drawEllipse( r.left()+4, r.top()+4, r.width()-8, r.height()-8 ); 46 p->drawEllipse( r.left()+4, r.top()+4, r.width()-8, r.height()-8 );
46 } else if ( t == Cross ) { // draw cross 47 } else if ( t == Cross ) { // draw cross
47 p->drawLine( r.topLeft() +QPoint(4,4), r.bottomRight()-QPoint(4,4)); 48 p->drawLine( r.topLeft() +QPoint(4,4), r.bottomRight()-QPoint(4,4));
48 p->drawLine( r.bottomLeft()+QPoint(4,-4),r.topRight() -QPoint(4,-4)); 49 p->drawLine( r.bottomLeft()+QPoint(4,-4),r.topRight() -QPoint(4,-4));
49 } 50 }
50} 51}
51 52
52 53
53//*************************************************************************** 54//***************************************************************************
54//* TicTacGameBoard member functions 55//* TicTacGameBoard member functions
55//*************************************************************************** 56//***************************************************************************
56 57
57// -------------------------------------------------------------------------- 58// --------------------------------------------------------------------------
58// Creates a game board with N x N buttons and connects the "clicked()" 59// Creates a game board with N x N buttons and connects the "clicked()"
59// signal of all buttons to the "buttonClicked()" slot. 60// signal of all buttons to the "buttonClicked()" slot.
60// 61//
61 62
62TicTacGameBoard::TicTacGameBoard( int n, QWidget *parent, const char *name ) 63TicTacGameBoard::TicTacGameBoard( int n, QWidget *parent, const char *name )
63 : QWidget( parent, name ) 64 : QWidget( parent, name )
64{ 65{
65showMaximized(); 66 showMaximized();
66 st = Init; // initial state 67 st = Init; // initial state
67 nBoard = n; 68 nBoard = n;
68 n *= n; // make square 69 n *= n; // make square
69 comp_starts = FALSE; // human starts 70 comp_starts = FALSE; // human starts
70 buttons = new TicTacButtons(n); // create real buttons 71 buttons = new TicTacButtons(n); // create real buttons
71 btArray = new TicTacArray(n); // create button model 72 btArray = new TicTacArray(n); // create button model
72 QGridLayout * grid = new QGridLayout( this, 3, 3, 4 ); 73 QGridLayout * grid = new QGridLayout( this, 3, 3, 4 );
73 QPalette p( blue ); 74 QPalette p( blue );
74 for ( int i=0; i<n; i++ ) { // create and connect buttons 75 for ( int i=0; i<n; i++ ) { // create and connect buttons
75 TicTacButton *ttb = new TicTacButton( this ); 76 TicTacButton *ttb = new TicTacButton( this );
76 ttb->setPalette( p ); 77 ttb->setPalette( p );
77 ttb->setEnabled( FALSE ); 78 ttb->setEnabled( FALSE );
78 connect( ttb, SIGNAL(clicked()), SLOT(buttonClicked()) ); 79 connect( ttb, SIGNAL(clicked()), SLOT(buttonClicked()) );
79 grid->addWidget( ttb, i%3, i/3 ); 80 grid->addWidget( ttb, i%3, i/3 );
80 buttons->insert( i, ttb ); 81 buttons->insert( i, ttb );
81 btArray->at(i) = TicTacButton::Blank;// initial button type 82 btArray->at(i) = TicTacButton::Blank; // initial button type
82 } 83 }
83 QTime t = QTime::currentTime(); // set random seed 84 QTime t = QTime::currentTime(); // set random seed
84 srand( t.hour()*12+t.minute()*60+t.second()*60 ); 85 srand( t.hour()*12+t.minute()*60+t.second()*60 );
85} 86}
86 87
87TicTacGameBoard::~TicTacGameBoard() 88TicTacGameBoard::~TicTacGameBoard()
88{ 89{
89 delete buttons; 90 delete buttons;
90 delete btArray; 91 delete btArray;
91} 92}
92 93
93 94
94// -------------------------------------------------------------------------- 95// --------------------------------------------------------------------------
95// TicTacGameBoard::computerStarts( bool v ) 96// TicTacGameBoard::computerStarts( bool v )
96// 97//
97// Computer starts if v=TRUE. The human starts by default. 98// Computer starts if v=TRUE. The human starts by default.
98// 99//
99 100
100void TicTacGameBoard::computerStarts( bool v ) 101void TicTacGameBoard::computerStarts( bool v )
101{ 102{
102 comp_starts = v; 103 comp_starts = v;
103} 104}
104 105
105 106
106// -------------------------------------------------------------------------- 107// --------------------------------------------------------------------------
107// TicTacGameBoard::newGame() 108// TicTacGameBoard::newGame()
108// 109//
109// Clears the game board and prepares for a new game 110// Clears the game board and prepares for a new game
110// 111//
111 112
112void TicTacGameBoard::newGame() 113void TicTacGameBoard::newGame()
113{ 114{
114 st = HumansTurn; 115 st = HumansTurn;
115 for ( int i=0; i<nBoard*nBoard; i++ ) 116 for ( int i=0; i<nBoard*nBoard; i++ )
116 btArray->at(i) = TicTacButton::Blank; 117 btArray->at(i) = TicTacButton::Blank;
117 if ( comp_starts ) 118 if ( comp_starts )
118 computerMove(); 119 computerMove();
119 else 120 else
120 updateButtons(); 121 updateButtons();
121} 122}
122 123
123 124
124// -------------------------------------------------------------------------- 125// --------------------------------------------------------------------------
125 // TicTacGameBoard::buttonClicked() - SLOT 126// TicTacGameBoard::buttonClicked() - SLOT
126// 127//
127// This slot is activated when a TicTacButton emits the signal "clicked()", 128// This slot is activated when a TicTacButton emits the signal "clicked()",
128// i.e. the user has clicked on a TicTacButton. 129// i.e. the user has clicked on a TicTacButton.
129// 130//
130 131
131void TicTacGameBoard::buttonClicked() 132void TicTacGameBoard::buttonClicked()
132{ 133{
133 if ( st != HumansTurn ) // not ready 134 if ( st != HumansTurn ) // not ready
134 return; 135 return;
135 int i = buttons->findRef( (TicTacButton*)sender() ); 136 int i = buttons->findRef( (TicTacButton*)sender() );
136 TicTacButton *b = buttons->at(i); // get piece that was pressed 137 TicTacButton *b = buttons->at(i); // get piece that was pressed
137 if ( b->type() == TicTacButton::Blank ) {// empty piece? 138 if ( b->type() == TicTacButton::Blank ) { // empty piece?
138 btArray->at(i) = TicTacButton::Circle; 139 btArray->at(i) = TicTacButton::Circle;
139 updateButtons(); 140 updateButtons();
140 if ( checkBoard( btArray ) == 0 )// not a winning move? 141 if ( checkBoard( btArray ) == 0 ) // not a winning move?
141 computerMove(); 142 computerMove();
142 int s = checkBoard( btArray ); 143 int s = checkBoard( btArray );
143 if ( s ) { // any winners yet? 144 if ( s ) { // any winners yet?
144 st = s == TicTacButton::Circle ? HumanWon : ComputerWon; 145 st = s == TicTacButton::Circle ? HumanWon : ComputerWon;
145 emit finished(); 146 emit finished();
146 } 147 }
147 } 148 }
148} 149}
149 150
150 151
151// -------------------------------------------------------------------------- 152// --------------------------------------------------------------------------
152// TicTacGameBoard::updateButtons() 153// TicTacGameBoard::updateButtons()
153// 154//
154// Updates all buttons that have changed state 155// Updates all buttons that have changed state
155// 156//
156 157
157void TicTacGameBoard::updateButtons() 158void TicTacGameBoard::updateButtons()
158{ 159{
159 for ( int i=0; i<nBoard*nBoard; i++ ) { 160 for ( int i=0; i<nBoard*nBoard; i++ ) {
160 if ( buttons->at(i)->type() != btArray->at(i) ) 161 if ( buttons->at(i)->type() != btArray->at(i) )
161 buttons->at(i)->setType( (TicTacButton::Type)btArray->at(i) ); 162 buttons->at(i)->setType( (TicTacButton::Type)btArray->at(i) );
162 buttons->at(i)->setEnabled( buttons->at(i)->type() == 163 buttons->at(i)->setEnabled( buttons->at(i)->type() ==
163 TicTacButton::Blank ); 164 TicTacButton::Blank );
164 } 165 }
165} 166}
166 167
167 168
168// -------------------------------------------------------------------------- 169// --------------------------------------------------------------------------
169// TicTacGameBoard::checkBoard() 170// TicTacGameBoard::checkBoard()
170// 171//
171// Checks if one of the players won the game, works for any board size. 172// Checks if one of the players won the game, works for any board size.
172// 173//
173// Returns: 174// Returns:
174// - TicTacButton::Cross if the player with X buttons won 175// - TicTacButton::Cross if the player with X buttons won
175// - TicTacButton::Circle if the player with O buttons won 176// - TicTacButton::Circle if the player with O buttons won
176// - Zero (0) if there is no winner yet 177// - Zero (0) if there is no winner yet
177// 178//
178 179
179int TicTacGameBoard::checkBoard( TicTacArray *a ) 180int TicTacGameBoard::checkBoard( TicTacArray *a )
180{ 181{
181 int t = 0; 182 int t = 0;
182 int row, col; 183 int row, col;
183 bool won = FALSE; 184 bool won = FALSE;
184 for ( row=0; row<nBoard && !won; row++ ) {// check horizontal 185 for ( row=0; row<nBoard && !won; row++ ) { // check horizontal
185 t = a->at(row*nBoard); 186 t = a->at(row*nBoard);
186 if ( t == TicTacButton::Blank ) 187 if ( t == TicTacButton::Blank )
187 continue; 188 continue;
188 col = 1; 189 col = 1;
189 while ( col<nBoard && a->at(row*nBoard+col) == t ) 190 while ( col<nBoard && a->at(row*nBoard+col) == t )
190 col++; 191 col++;
191 if ( col == nBoard ) 192 if ( col == nBoard )
192 won = TRUE; 193 won = TRUE;
193 } 194 }
194 for ( col=0; col<nBoard && !won; col++ ) {// check vertical 195 for ( col=0; col<nBoard && !won; col++ ) { // check vertical
195 t = a->at(col); 196 t = a->at(col);
196 if ( t == TicTacButton::Blank ) 197 if ( t == TicTacButton::Blank )
197 continue; 198 continue;
198 row = 1; 199 row = 1;
199 while ( row<nBoard && a->at(row*nBoard+col) == t ) 200 while ( row<nBoard && a->at(row*nBoard+col) == t )
200 row++; 201 row++;
201 if ( row == nBoard ) 202 if ( row == nBoard )
202 won = TRUE; 203 won = TRUE;
203 } 204 }
204 if ( !won ) { // check diagonal top left 205 if ( !won ) { // check diagonal top left
205 t = a->at(0); // to bottom right 206 t = a->at(0); // to bottom right
206 if ( t != TicTacButton::Blank ) { 207 if ( t != TicTacButton::Blank ) {
207 int i = 1; 208 int i = 1;
208 while ( i<nBoard && a->at(i*nBoard+i) == t ) 209 while ( i<nBoard && a->at(i*nBoard+i) == t )
209 i++; 210 i++;
210 if ( i == nBoard ) 211 if ( i == nBoard )
211 won = TRUE; 212 won = TRUE;
212 } 213 }
213 } 214 }
214 if ( !won ) { // check diagonal bottom left 215 if ( !won ) { // check diagonal bottom left
215 int j = nBoard-1; // to top right 216 int j = nBoard-1; // to top right
216 int i = 0; 217 int i = 0;
217 t = a->at(i+j*nBoard); 218 t = a->at(i+j*nBoard);
218 if ( t != TicTacButton::Blank ) { 219 if ( t != TicTacButton::Blank ) {
219 i++; j--; 220 i++; j--;
220 while ( i<nBoard && a->at(i+j*nBoard) == t ) { 221 while ( i<nBoard && a->at(i+j*nBoard) == t ) {
221 i++; j--; 222 i++; j--;
222 } 223 }
223 if ( i == nBoard ) 224 if ( i == nBoard )
224 won = TRUE; 225 won = TRUE;
225 } 226 }
226 } 227 }
227 if ( !won ) // no winner 228 if ( !won ) // no winner
228 t = 0; 229 t = 0;
229 return t; 230 return t;
230} 231}
231 232
232 233
233// -------------------------------------------------------------------------- 234// --------------------------------------------------------------------------
234// TicTacGameBoard::computerMove() 235// TicTacGameBoard::computerMove()
235// 236//
236// Puts a piece on the game board. Very, very simple. 237// Puts a piece on the game board. Very, very simple.
237// 238//
238 239
239void TicTacGameBoard::computerMove() 240void TicTacGameBoard::computerMove()
240{ 241{
241 int numButtons = nBoard*nBoard; 242 int numButtons = nBoard*nBoard;
242 int *altv = new int[numButtons]; // buttons alternatives 243 int *altv = new int[numButtons]; // buttons alternatives
243 int altc = 0; 244 int altc = 0;
244 int stopHuman = -1; 245 int stopHuman = -1;
245 TicTacArray a = btArray->copy(); 246 TicTacArray a = btArray->copy();
246 int i; 247 int i;
247 for ( i=0; i<numButtons; i++ ) { // try all positions 248 for ( i=0; i<numButtons; i++ ) { // try all positions
248 if ( a[i] != TicTacButton::Blank )// already a piece there 249 if ( a[i] != TicTacButton::Blank ) // already a piece there
249 continue; 250 continue;
250 a[i] = TicTacButton::Cross; // test if computer wins 251 a[i] = TicTacButton::Cross; // test if computer wins
251 if ( checkBoard(&a) == a[i] ) { // computer will win 252 if ( checkBoard(&a) == a[i] ) { // computer will win
252 st = ComputerWon; 253 st = ComputerWon;
253 stopHuman = -1; 254 stopHuman = -1;
254 break; 255 break;
255 } 256 }
256 a[i] = TicTacButton::Circle; // test if human wins 257 a[i] = TicTacButton::Circle; // test if human wins
257 if ( checkBoard(&a) == a[i] ) { // oops... 258 if ( checkBoard(&a) == a[i] ) { // oops...
258 stopHuman = i; // remember position 259 stopHuman = i; // remember position
259 a[i] = TicTacButton::Blank; // restore button 260 a[i] = TicTacButton::Blank; // restore button
260 continue; // computer still might win 261 continue; // computer still might win
261 } 262 }
262 a[i] = TicTacButton::Blank; // restore button 263 a[i] = TicTacButton::Blank; // restore button
263 altv[altc++] = i; // remember alternative 264 altv[altc++] = i; // remember alternative
264 } 265 }
265 if ( stopHuman >= 0 ) // must stop human from winning 266 if ( stopHuman >= 0 ) // must stop human from winning
266 a[stopHuman] = TicTacButton::Cross; 267 a[stopHuman] = TicTacButton::Cross;
267 else if ( i == numButtons ) { // tried all alternatives 268 else if ( i == numButtons ) { // tried all alternatives
268 if ( altc > 0 ) // set random piece 269 if ( altc > 0 ) // set random piece
269 a[altv[rand()%(altc--)]] = TicTacButton::Cross; 270 a[altv[rand()%(altc--)]] = TicTacButton::Cross;
270 if ( altc == 0 ) { // no more blanks 271 if ( altc == 0 ) { // no more blanks
271 st = NobodyWon; 272 st = NobodyWon;
272 emit finished(); 273 emit finished();
273 } 274 }
274 } 275 }
275 *btArray = a; // update model 276 *btArray = a; // update model
276 updateButtons(); // update buttons 277 updateButtons(); // update buttons
277 delete[] altv; 278 delete[] altv;
278} 279}
279 280
280 281
281//*************************************************************************** 282//***************************************************************************
282//* TicTacToe member functions 283//* TicTacToe member functions
283//*************************************************************************** 284//***************************************************************************
284 285
285// -------------------------------------------------------------------------- 286// --------------------------------------------------------------------------
286// Creates a game widget with a game board and two push buttons, and connects 287// Creates a game widget with a game board and two push buttons, and connects
287// signals of child widgets to slots. 288// signals of child widgets to slots.
288// 289//
289 290
290TicTacToe::TicTacToe( int boardSize, QWidget *parent, const char *name ) 291TicTacToe::TicTacToe( int boardSize, QWidget *parent, const char *name )
291 : QWidget( parent, name ) 292 : QWidget( parent, name )
292{ 293{
293 QVBoxLayout * l = new QVBoxLayout( this, 6 ); 294 QVBoxLayout * l = new QVBoxLayout( this, 6 );
294 295
295 // Create a message label 296 // Create a message label
296 297
297 message = new QLabel( this ); 298 message = new QLabel( this );
298 message->setFrameStyle( QFrame::WinPanel | QFrame::Sunken ); 299 message->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
299 message->setAlignment( AlignCenter ); 300 message->setAlignment( AlignCenter );
300 l->addWidget( message ); 301 l->addWidget( message );
301 302
302 // Create the game board and connect the signal finished() to this 303 // Create the game board and connect the signal finished() to this
303 // gameOver() slot 304 // gameOver() slot
304 305
305 board = new TicTacGameBoard( boardSize, this ); 306 board = new TicTacGameBoard( boardSize, this );
306 connect( board, SIGNAL(finished()), SLOT(gameOver()) ); 307 connect( board, SIGNAL(finished()), SLOT(gameOver()) );
307 l->addWidget( board ); 308 l->addWidget( board );
308 309
309 // Create a horizontal frame line 310 // Create a horizontal frame line
310 311
311 QFrame *line = new QFrame( this ); 312 QFrame *line = new QFrame( this );
312 line->setFrameStyle( QFrame::HLine | QFrame::Sunken ); 313 line->setFrameStyle( QFrame::HLine | QFrame::Sunken );
313 l->addWidget( line ); 314 l->addWidget( line );
314 315
315 // Create the combo box for deciding who should start, and 316 // Create the combo box for deciding who should start, and
316 // connect its clicked() signals to the buttonClicked() slot 317 // connect its clicked() signals to the buttonClicked() slot
317 318
318 whoStarts = new QComboBox( this ); 319 whoStarts = new QComboBox( this );
319 whoStarts->insertItem( tr( "Computer starts" ) ); 320 whoStarts->insertItem( tr( "Computer starts" ) );
320 whoStarts->insertItem( tr( "Human starts" ) ); 321 whoStarts->insertItem( tr( "Human starts" ) );
321 l->addWidget( whoStarts ); 322 l->addWidget( whoStarts );
322 323
323 // Create the push buttons and connect their clicked() signals 324 // Create the push buttons and connect their clicked() signals
324 // to this right slots. 325 // to this right slots.
325 326
326 newGame = new QPushButton( tr( "Play!" ), this ); 327 newGame = new QPushButton( tr( "Play!" ), this );
327 connect( newGame, SIGNAL(clicked()), SLOT(newGameClicked()) ); 328 connect( newGame, SIGNAL(clicked()), SLOT(newGameClicked()) );
328 quit = new QPushButton( tr( "Quit" ), this ); 329 quit = new QPushButton( tr( "Quit" ), this );
329 connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) ); 330 connect( quit, SIGNAL(clicked()), qApp, SLOT(quit()) );
330 QHBoxLayout * b = new QHBoxLayout; 331 QHBoxLayout * b = new QHBoxLayout;
331 l->addLayout( b ); 332 l->addLayout( b );
332 b->addWidget( newGame ); 333 b->addWidget( newGame );
333 b->addWidget( quit ); 334 b->addWidget( quit );
334showMaximized(); 335 showMaximized();
335 newState(); 336 newState();
336} 337}
337 338
338 339
339// -------------------------------------------------------------------------- 340// --------------------------------------------------------------------------
340 // TicTacToe::newGameClicked() - SLOT 341// TicTacToe::newGameClicked() - SLOT
341// 342//
342// This slot is activated when the new game button is clicked. 343// This slot is activated when the new game button is clicked.
343// 344//
344 345
345void TicTacToe::newGameClicked() 346void TicTacToe::newGameClicked()
346{ 347{
347 board->computerStarts( whoStarts->currentItem() == 0 ); 348 board->computerStarts( whoStarts->currentItem() == 0 );
348 board->newGame(); 349 board->newGame();
349 newState(); 350 newState();
350} 351}
351 352
352 353
353// -------------------------------------------------------------------------- 354// --------------------------------------------------------------------------
354 // TicTacToe::gameOver() - SLOT 355// TicTacToe::gameOver() - SLOT
355// 356//
356// This slot is activated when the TicTacGameBoard emits the signal 357// This slot is activated when the TicTacGameBoard emits the signal
357// "finished()", i.e. when a player has won or when it is a draw. 358// "finished()", i.e. when a player has won or when it is a draw.
358// 359//
359 360
360void TicTacToe::gameOver() 361void TicTacToe::gameOver()
361{ 362{
362 newState(); // update text box 363 newState(); // update text box
363} 364}
364 365
365 366
366// -------------------------------------------------------------------------- 367// --------------------------------------------------------------------------
367// Updates the message to reflect a new state. 368// Updates the message to reflect a new state.
368// 369//
369 370
370void TicTacToe::newState() 371void TicTacToe::newState()
371{ 372{
372 static const char *msg[] = { // TicTacGameBoard::State texts 373 QStringList msg;
373 "Click Play to start", "Make your move", 374 msg << tr( "Click Play to start")
374 "You won!", "Computer won!", "It's a draw" }; 375 << tr("Make your move")
376 << tr("You won!")
377 << tr("Computer won!")
378 << tr("It's a draw");
375 message->setText( msg[board->state()] ); 379 message->setText( msg[board->state()] );
376 return; 380 return;
377} 381}