summaryrefslogtreecommitdiff
authorzecke <zecke>2004-07-24 18:11:45 (UTC)
committer zecke <zecke>2004-07-24 18:11:45 (UTC)
commit5a8963dff615da61611f5cc4bf410e7a6eeef55b (patch) (side-by-side diff)
tree5a559826d04a2f99a0d00bd8e979c4e9e133c05c
parente7ccf9bd121f98fa4c07b78eae7d36bdfa5b60bc (diff)
downloadopie-5a8963dff615da61611f5cc4bf410e7a6eeef55b.zip
opie-5a8963dff615da61611f5cc4bf410e7a6eeef55b.tar.gz
opie-5a8963dff615da61611f5cc4bf410e7a6eeef55b.tar.bz2
Have a custom grid for the game. Now the name of fifteen is
pretty obsolete but hey it is fun :)
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/games/fifteen/fifteen.cpp153
-rw-r--r--noncore/games/fifteen/fifteen.h2
-rw-r--r--noncore/games/fifteen/fifteenconfigdialog.cpp4
3 files changed, 108 insertions, 51 deletions
diff --git a/noncore/games/fifteen/fifteen.cpp b/noncore/games/fifteen/fifteen.cpp
index f425e06..bb57ee1 100644
--- a/noncore/games/fifteen/fifteen.cpp
+++ b/noncore/games/fifteen/fifteen.cpp
@@ -13,487 +13,546 @@
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "fifteen.h"
#include "fifteenconfigdialog.h"
#include <opie2/ofileselector.h>
#include <qtopia/resource.h>
#include <qtopia/config.h>
#include <qtopia/qpeapplication.h>
#include <qvbox.h>
#include <qaction.h>
#include <qpainter.h>
#include <qmessagebox.h>
#include <qtoolbar.h>
#include <qmenubar.h>
#include <qimage.h>
#include <stdlib.h>
#include <time.h>
FifteenMainWindow::FifteenMainWindow(QWidget *parent, const char* name, WFlags fl)
: QMainWindow( parent, name, fl )
{
// random seed
srand(time(0));
setCaption( tr("Fifteen Pieces") );
QToolBar *toolbar = new QToolBar(this);
toolbar->setHorizontalStretchable( FALSE );
QMenuBar *menubar = new QMenuBar( toolbar );
menubar->setMargin(0);
QPopupMenu *game = new QPopupMenu( this );
QWidget *spacer = new QWidget( toolbar );
spacer->setBackgroundMode( PaletteButton );
toolbar->setStretchableWidget( spacer );
setToolBarsMovable( FALSE );
QVBox *vbox = new QVBox( this );
PiecesTable *table = new PiecesTable( vbox );
setCentralWidget(vbox);
QAction *a = new QAction( tr( "Randomize" ), Resource::loadPixmap( "new" ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), table, SLOT( slotRandomize() ) );
a->addTo( game );
a->addTo( toolbar );
a = new QAction( tr("Configure"), Resource::loadPixmap( "SettingsIcon" ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated()), table, SLOT( slotConfigure()) );
a->addTo( game );
/* This is pointless and confusing.
a = new QAction( tr( "Solve" ), Resource::loadIconSet( "repeat" ),
QString::null, 0, this, 0 );
connect( a, SIGNAL( activated() ), table, SLOT( slotReset() ) );
a->addTo( game );
a->addTo( toolbar );
*/
menubar->insertItem( tr( "Game" ), game );
}
///////////////
/////// Pieces table Implementation
///////
PiecesTable::PiecesTable(QWidget* parent, const char* name )
: QTableView(parent, name), _menu(0), _randomized(false),
_dialog( 0l )
{
// setup table view
setFrameStyle(StyledPanel | Sunken);
setBackgroundMode(NoBackground);
setMouseTracking(true);
setNumRows(4);
setNumCols(4);
// init arrays
- initMap();
readConfig();
initColors();
}
PiecesTable::~PiecesTable()
{
writeConfig();
clear();
}
void PiecesTable::writeConfig()
{
Config cfg("Fifteen");
cfg.setGroup("Game");
QStringList map;
- for (int i = 0; i < 16; i++)
+
+ int items = numRows()*numCols();
+
+ for (int i = 0; i < items; i++)
map.append( QString::number( _map[i] ) );
+
cfg.writeEntry("Map", map, '-');
cfg.writeEntry("Randomized", _randomized );
cfg.writeEntry("Image", _image );
+ cfg.writeEntry("Rows", numRows() );
+ cfg.writeEntry("Cols", numCols() );
}
void PiecesTable::readConfig()
{
Config cfg("Fifteen");
cfg.setGroup("Game");
QStringList map = cfg.readListEntry("Map", '-');
_randomized = cfg.readBoolEntry( "Randomized", FALSE );
_image = cfg.readEntry( "Image", QString::null );
- int i = 0;
+
+ int rows = cfg.readNumEntry( "Rows", 4 );
+ int cols = cfg.readNumEntry( "Cols", 4 );
+ uint items= rows*cols;
+ setNumRows( rows );
+ setNumCols( cols );
+
+ initMap();
+
+ /* if we've more items than 'stones' don't restore the state */
+ if ( items > map.count() )
+ return;
+
+
+ uint i = 0;
for ( QStringList::Iterator it = map.begin(); it != map.end(); ++it ) {
_map[i] = (*it).toInt();
i++;
- if ( i > 15 ) break;
+ if ( i > items ) break;
}
}
void PiecesTable::clear() {
/* clean up and resize */
for (uint i = 0; i < _pixmap.count(); ++i )
delete _pixmap[i];
- _pixmap.resize( 16 );
+ _pixmap.resize( numRows()*numCols() );
}
/*
* Let us pre-render the tiles. Either we've a Custom Image as
* background or we use the drawRect to fill the background and
* last we put the number on it
*/
-void PiecesTable::slotCustomImage( const QString& _str , bool upd ) {
+void PiecesTable::slotCustomImage( const QString& _str ) {
QString str = _str;
/* couldn't load image fall back to plain tiles*/
QImage img = QImage(str);
+ QPixmap pix;
if(img.isNull())
str = QString::null;
- else
+ else{
img = img.smoothScale( width(),height() );
+ pix.convertFromImage( img );
+ }
- QPixmap pix;
- pix.convertFromImage( img );
-
+ /* initialize base point */
uint image=0;
+ /* clear the old tiles */
clear();
/* used variables */
int cols = numCols();
int rows = numRows();
int cellW = cellWidth();
int cellH = cellHeight();
int x2 = cellW-1;
int y2 = cellH-1;
bool empty = str.isEmpty();
double bw = empty ? 0.9 : 0.98;
int x_offset = cellW - int(cellW * bw); // 10% should be enough
int y_offset = cellH - int(cellH * bw);
- /* border polygon */
+ /* border polygon calculation*/
initPolygon(cellW, cellH, x_offset, y_offset );
+ /* avoid crashes with isNull() pixmap later */
if ( cellW == 0 || cellH == 0 ) {
_pixmap.resize( 0 );
return;
}
+ /* make it bold and bigger */
QFont f = font();
f.setPixelSize(18);
f.setBold( TRUE );
/* for every tile */
for(int row = 0; row < rows; ++row ) {
for(int col= 0; col < cols; ++col) {
QPixmap *pip = new QPixmap(cellW, cellH );
QPainter *p = new QPainter(pip );
p->setFont( f );
/* draw the tradional tile or a part of the pixmap*/
if(empty) {
p->setBrush(_colors[image]);
p->setPen(NoPen);
p->drawRect(0,0,cellW,cellH);
}else
p->drawPixmap(0, 0, pix,col*cellW, row*cellH, cellW, cellH );
// draw borders
if (height() > 40) {
p->setBrush(_colors[image].light(130));
p->drawPolygon(light_border);
p->setBrush(_colors[image].dark(130));
p->drawPolygon(dark_border);
}
// draw number
p->setPen(black);
p->drawText(0, 0, x2, y2, AlignHCenter | AlignVCenter, QString::number(image+1));
delete p;
_pixmap[image++] = pip;
}
}
_image = str;
-
- if ( upd )
- update();
}
/*
* Calculate 3d-effect borders
*/
void PiecesTable::initPolygon(int cell_w, int cell_h, int x_offset, int y_offset ) {
light_border.setPoints(6,
0, 0,
cell_w, 0,
cell_w - x_offset, y_offset,
x_offset, y_offset,
x_offset, cell_h - y_offset,
0, cell_h);
dark_border.setPoints(6,
cell_w, 0,
cell_w, cell_h,
0, cell_h,
x_offset, cell_h - y_offset,
cell_w - x_offset, cell_h - y_offset,
cell_w - x_offset, y_offset);
}
void PiecesTable::paintCell(QPainter *p, int row, int col)
{
int w = cellWidth();
int h = cellHeight();
+ uint pos = col+row*numCols();
+
+ /* sanity check. setNumRows()/setNumCols() calls repaint() directly */
+ if ( pos >= _map.count() ) {
+ p->drawRect(0, 0, w, h);
+ return;
+ }
+
int number = _map[col + row * numCols()] + 1;
// draw cell background
- if(number == 16) {
+ if(number == numCols()*numRows() ) {
p->setBrush(colorGroup().background());
p->setPen(NoPen);
p->drawRect(0, 0, w, h);
return;
}
+ /* no tiles then contentRect() is not visible or too small anyway */
if( _pixmap.count() == 0 )
return;
p->drawPixmap(0, 0, *(_pixmap[(number-1 )]) );
}
void PiecesTable::resizeEvent(QResizeEvent *e)
{
- QTableView::resizeEvent(e);
+ /*
+ * null if we faked it after the config dialog ran to
+ * regenerate everything
+ */
+ if ( e )
+ QTableView::resizeEvent(e);
- setCellWidth(contentsRect().width()/ numRows());
- setCellHeight(contentsRect().height() / numCols());
+ setCellWidth(contentsRect().width()/ numCols());
+ setCellHeight(contentsRect().height() / numRows());
/* update the image and calculate border*/
slotCustomImage( _image );
}
void PiecesTable::initColors()
{
_colors.resize(numRows() * numCols());
for (int r = 0; r < numRows(); r++)
for (int c = 0; c < numCols(); c++)
- _colors[c + r *numCols()] = QColor(255 - 70 * c,255 - 70 * r, 150);
+ _colors[c + r *numCols()] = QColor( 255 - (70 * c)%255 ,255 - (70 * r)%255, 150);
}
void PiecesTable::initMap()
{
- _map.resize(16);
- for ( int i = 0; i < 16; i++)
+ int items = numCols()*numRows();
+ _map.resize( items );
+ for ( int i = 0; i < items; i++)
_map[i] = i;
_randomized = false;
}
void PiecesTable::randomizeMap()
{
initMap();
_randomized = true;
// find the free position
- int pos = _map.find(15);
+ int cols = numCols();
+ int rows = numRows();
+ int pos = _map.find( cols*rows -1 );
int move = 0;
while ( move < 333 ) {
- int frow = pos / numCols();
- int fcol = pos - frow * numCols();
+ int frow = pos / cols;
+ int fcol = pos - frow * cols;
// find click position
- int row = rand()%4;
- int col = rand()%4;
+ int row = rand()%rows;
+ int col = rand()%cols;
// sanity check
- if ( row < 0 || row >= numRows() ) continue;
- if ( col < 0 || col >= numCols() ) continue;
+ if ( row < 0 || row >= rows ) continue;
+ if ( col < 0 || col >= cols ) continue;
if ( row != frow && col != fcol ) continue;
move++;
// rows match -> shift pieces
if(row == frow) {
if (col < fcol) {
for(int c = fcol; c > col; c--) {
- _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
+ _map[c + row * cols] = _map[ c-1 + row *cols];
}
}
else if (col > fcol) {
for(int c = fcol; c < col; c++) {
- _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
+ _map[c + row * cols] = _map[ c+1 + row *cols];
}
}
}
// cols match -> shift pieces
else if (col == fcol) {
if (row < frow) {
for(int r = frow; r > row; r--) {
- _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
+ _map[col + r * cols] = _map[ col + (r-1) *cols];
}
}
else if (row > frow) {
for(int r = frow; r < row; r++) {
- _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
+ _map[col + r * cols] = _map[ col + (r+1) *cols];
}
}
}
// move free cell to click position
- _map[pos=(col + row * numCols())] = 15;
+ _map[pos=(col + row * cols)] = rows*cols-1;
}
repaint();
}
void PiecesTable::checkwin()
{
if(!_randomized) return;
+ int items=numCols()*numRows();
int i;
- for (i = 0; i < 16; i++)
+ for (i = 0; i < items; i++)
if(i != _map[i])
break;
- if (i == 16) {
+ if (i == items) {
QMessageBox::information(this, tr("Fifteen Pieces"),
tr("Congratulations!\nYou win the game!"));
_randomized = FALSE;
}
}
void PiecesTable::slotRandomize()
{
randomizeMap();
}
void PiecesTable::slotReset()
{
initMap();
repaint();
}
void PiecesTable::mousePressEvent(QMouseEvent* e)
{
QTableView::mousePressEvent(e);
if (e->button() == RightButton) {
// setup RMB pupup menu
if(!_menu) {
_menu = new QPopupMenu(this);
_menu->insertItem(tr("R&andomize Pieces"), mRandomize);
_menu->insertItem(tr("&Reset Pieces"), mReset);
_menu->adjustSize();
}
// execute RMB popup and check result
switch(_menu->exec(mapToGlobal(e->pos()))) {
case mRandomize:
randomizeMap();
break;
case mReset:
initMap();
repaint();
break;
default:
break;
}
}
else {
// GAME LOGIC
+ int cols = numCols();
+ int rows = numRows();
+ int item = cols*rows -1;
// find the free position
- int pos = _map.find(15);
+ int pos = _map.find(item);
if(pos < 0) return;
- int frow = pos / numCols();
- int fcol = pos - frow * numCols();
+ int frow = pos / cols;
+ int fcol = pos - frow * cols;
// find click position
int row = findRow(e->y());
int col = findCol(e->x());
// sanity check
- if (row < 0 || row >= numRows()) return;
- if (col < 0 || col >= numCols()) return;
+ if (row < 0 || row >= rows) return;
+ if (col < 0 || col >= cols) return;
if ( row != frow && col != fcol ) return;
// valid move?
if(row != frow && col != fcol) return;
// rows match -> shift pieces
if(row == frow) {
if (col < fcol) {
for(int c = fcol; c > col; c--) {
- _map[c + row * numCols()] = _map[ c-1 + row *numCols()];
+ _map[c + row * cols] = _map[ c-1 + row *cols];
updateCell(row, c, false);
}
}
else if (col > fcol) {
for(int c = fcol; c < col; c++) {
- _map[c + row * numCols()] = _map[ c+1 + row *numCols()];
+ _map[c + row * cols] = _map[ c+1 + row *cols];
updateCell(row, c, false);
}
}
}
// cols match -> shift pieces
else if (col == fcol) {
if (row < frow) {
for(int r = frow; r > row; r--) {
- _map[col + r * numCols()] = _map[ col + (r-1) *numCols()];
+ _map[col + r * cols] = _map[ col + (r-1) *cols];
updateCell(r, col, false);
}
}
else if (row > frow) {
for(int r = frow; r < row; r++) {
- _map[col + r * numCols()] = _map[ col + (r+1) *numCols()];
+ _map[col + r * cols] = _map[ col + (r+1) *cols];
updateCell(r, col, false);
}
}
}
// move free cell to click position
- _map[col + row * numCols()] = 15;
+ _map[col + row * cols] = item;
updateCell(row, col, false);
// check if the player wins with this move
checkwin();
}
}
void PiecesTable::slotConfigure() {
if ( !_dialog )
_dialog = new FifteenConfigDialog(this, "Fifteen Configure Dialog", true );
_dialog->setImageSrc( _image );
- if ( QPEApplication::execDialog(_dialog) == QDialog::Accepted )
- slotCustomImage( _dialog->imageSrc(), true );
+ _dialog->setGameboard( numRows(), numCols() );
+
+ if ( QPEApplication::execDialog(_dialog) == QDialog::Accepted ) {
+ /*
+ * update the board grid and reinit the game if changed
+ * First set new columns so the update will regenerate the
+ * tiles with slotCustomImage
+ */
+ _image = _dialog->imageSrc();
+ if (numRows() != _dialog->rows() ||
+ numCols() != _dialog->columns() ) {
+ setNumCols(_dialog->columns());
+ setNumRows(_dialog->rows());
+ slotReset();
+ }
+ resizeEvent( 0l );
+
+
+ update();
+ }
}
diff --git a/noncore/games/fifteen/fifteen.h b/noncore/games/fifteen/fifteen.h
index 4b8702d..c70afc8 100644
--- a/noncore/games/fifteen/fifteen.h
+++ b/noncore/games/fifteen/fifteen.h
@@ -1,102 +1,102 @@
/**********************************************************************
** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
**
** This file is part of the Qtopia Environment.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#ifndef __fifteenapplet_h__
#define __fifteenapplet_h__
#include <qmainwindow.h>
#include <qtableview.h>
#include <qarray.h>
#include <qpointarray.h>
#include <qpixmap.h>
#include <qvector.h>
class QPopupMenu;
class FifteenConfigDialog;
class PiecesTable : public QTableView
{
Q_OBJECT
public:
PiecesTable(QWidget* parent = 0, const char* name = 0);
~PiecesTable();
protected slots:
void slotConfigure();
- void slotCustomImage(const QString &str, bool upd = false);
+ void slotCustomImage(const QString &str);
void slotRandomize();
void slotReset();
protected:
void resizeEvent(QResizeEvent*);
void mousePressEvent(QMouseEvent*);
void paintCell(QPainter *, int row, int col);
void initImage();
void initMap();
void initColors();
void randomizeMap();
void checkwin();
void readConfig();
void writeConfig();
void initPolygon(int w, int h, int x_of, int y_of );
private:
void clear();
QString _image;
QArray<int> _map;
QArray<QColor> _colors;
QArray<QPixmap*> _pixmap;
QPopupMenu *_menu;
bool _randomized;
QPointArray light_border;
QPointArray dark_border;
FifteenConfigDialog *_dialog;
enum MenuOp { mRandomize = 1, mReset = 2 };
};
class FifteenWidget : public QWidget
{
Q_OBJECT
public:
FifteenWidget(QWidget *parent = 0, const char *name = 0);
private:
PiecesTable *_table;
};
class FifteenMainWindow : public QMainWindow
{
Q_OBJECT
public:
static QString appName() {
return QString::fromLatin1("fifteen");
}
FifteenMainWindow(QWidget *parent=0, const char* name=0, WFlags fl=0);
};
#endif
diff --git a/noncore/games/fifteen/fifteenconfigdialog.cpp b/noncore/games/fifteen/fifteenconfigdialog.cpp
index 3f974f8..8539e0e 100644
--- a/noncore/games/fifteen/fifteenconfigdialog.cpp
+++ b/noncore/games/fifteen/fifteenconfigdialog.cpp
@@ -1,112 +1,110 @@
/*
               =. This file is part of the OPIE Project
             .=l. Copyright (c) 2002 <>
           .>+-=
 _;:,     .>    :=|. This program is free software; you can
.> <`_,   >  .   <= redistribute it and/or modify it under
:`=1 )Y*s>-.--   : the terms of the GNU General Public
.="- .-=="i,     .._ License as published by the Free Software
 - .   .-<_>     .<> Foundation; either version 2 of the License,
     ._= =}       : or (at your option) any later version.
    .%`+i>       _;_.
    .i_,=:_.      -<s. This program is distributed in the hope that
     +  .  -:.       = it will be useful, but WITHOUT ANY WARRANTY;
    : ..    .:,     . . . without even the implied warranty of
    =_        +     =;=|` MERCHANTABILITY or FITNESS FOR A
  _.=:.       :    :=>`: PARTICULAR PURPOSE. See the GNU
..}^=.=       =       ; Library General Public License for more
++=   -.     .`     .: details.
 :     =  ...= . :.=-
 -.   .:....=;==+<; You should have received a copy of the GNU
  -_. . .   )=.  = General Public License along with
    --        :-=` this library; see the file COPYING.LIB.
If not, write to the Free Software Foundation,
Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "fifteenconfigdialog.h"
#include <opie2/ofiledialog.h>
#include <qimage.h>
#include <qlabel.h>
#include <qspinbox.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
using Opie::Ui::OFileSelector;
using Opie::Ui::OFileDialog;
FifteenConfigDialog::FifteenConfigDialog( QWidget* parent, const char* name, bool modal )
: FifteenConfigDialogBase( parent, name, modal )
-{
- grpGameGrid->hide();
-}
+{}
FifteenConfigDialog::~FifteenConfigDialog()
{}
/**
* src.isEmpty() means no Custom Image to be set
*/
void FifteenConfigDialog::setImageSrc( const QString& src ) {
ckbCustomImage->setChecked( !src.isEmpty() );
lneImage->setText( src );
lblPreview->setPixmap( preview(src ) );
}
/*
* If the return isEmpty() this means no custom image is wished
*/
QString FifteenConfigDialog::imageSrc()const {
return ckbCustomImage->isChecked() ? lneImage->text() : QString::null;
}
void FifteenConfigDialog::setGameboard( int rows, int columns ) {
spnRow->setValue( rows );
spnCol->setValue( columns );
}
int FifteenConfigDialog::columns()const {
return spnCol->value();
}
int FifteenConfigDialog::rows() const{
return spnRow->value();
}
void FifteenConfigDialog::slotLoadImage() {
QStringList lst;
lst << "image/*";
MimeTypes type;
type.insert( tr("All Images" ), lst );
type.insert( tr("All Files"), "*/*" );
QString str = OFileDialog::getOpenFileName(OFileSelector::Normal,
QString::null, QString::null,
type, this,
tr("Select board background") );
if (!str.isEmpty() )
setImageSrc( str );
}
QPixmap FifteenConfigDialog::preview( const QString& file ) {
QPixmap pix;
QImage img( file );
if( img.isNull() )
return pix;
img = img.smoothScale(120, 120 );
pix.convertFromImage( img );
return pix;
}