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