Commit 9de53c75 authored by Dmitry Suzdalev's avatar Dmitry Suzdalev

Now you can PLAY!

With yourself ;)

svn path=/branches/work/kreversi_rewrite/; revision=572491
parent 3e9d27d9
......@@ -129,7 +129,7 @@
#include <QBitArray>
#include <QVector>
#include <krandomsequence.h>
#include "kreversiboard.h"
#include "commondefs.h"
class KReversiGame;
......
#ifndef COMMON_DEFINITIONS_H
#define COMMON_DEFINITIONS_H
// noColor = empty
enum ChipColor { White = 0, Black = 1, NoColor = 2 };
struct KReversiMove
{
KReversiMove( ChipColor col = NoColor, int r = -1, int c = -1 )
: color(col), row(r), col(c) { }
ChipColor color;
int row;
int col;
};
#endif
#ifndef KREVERSI_BOARD_H
#define KREVERSI_BOARD_H
// noColor = empty
enum ChipColor { White = 0, Black = 1, NoColor = 2 };
#include "commondefs.h"
/**
* This class represents a reversi board.
......@@ -40,14 +39,4 @@ private:
*/
int m_score[2];
};
struct KReversiMove
{
KReversiMove( ChipColor col = NoColor, int r = -1, int c = -1 )
: color(col), row(r), col(c) { }
ChipColor color;
int row;
int col;
};
#endif
......@@ -3,19 +3,14 @@
#include <QPixmap>
KReversiChip::KReversiChip( ChipColor color, QGraphicsScene* scene )
: QGraphicsPixmapItem( 0, scene )
: QGraphicsPixmapItem( 0, scene ), m_color(color)
{
QPixmap pix(32, 32);
pix.fill( Qt::white );
QPainter p(&pix);
p.setBrush( color == White ? Qt::white : Qt::black );
p.drawEllipse( QRectF(0,0,32,32) );
p.end();
setPixmap( pix );
setColor(m_color);
}
void KReversiChip::setColor( ChipColor color )
{
m_color = color;
QPixmap pix(32, 32);
pix.fill( Qt::white );
QPainter p(&pix);
......
......@@ -2,9 +2,7 @@
#define KREVERSI_CHIP_H
#include <QGraphicsPixmapItem>
// this is to get ChipColor declaration.
// FIXME dimsuz: Move it to some common .h? (as it won't be the only h) where it is needed
#include "kreversiboard.h"
#include "commondefs.h"
class QGraphicsScene;
......@@ -13,5 +11,8 @@ class KReversiChip : public QGraphicsPixmapItem
public:
KReversiChip( ChipColor color, QGraphicsScene *scene );
void setColor( ChipColor color );
ChipColor color() const { return m_color; }
private:
ChipColor m_color;
};
#endif
......@@ -17,19 +17,308 @@ KReversiGame::~KReversiGame()
void KReversiGame::putChipAt( int row, int col )
{
if( m_board->chipColorAt( row, col ) != NoColor )
KReversiMove move( m_curPlayer, row, col );
if( !isMovePossible(move) )
{
kDebug() << "This cell isn't empty! No move Possible" << endl;
kDebug() << "No move possible" << endl;
return;
}
m_board->setChipColor( row, col, m_curPlayer );
// now turn color of all chips that were won
if( hasChunk( Up, move ) )
{
for(int r=move.row-1; r >= 0; --r)
{
if( m_board->chipColorAt( r, move.col ) == m_curPlayer )
break;
m_board->setChipColor( r, move.col, m_curPlayer );
}
}
if( hasChunk( Down, move ) )
{
for(int r=move.row+1; r < 8; ++r)
{
if( m_board->chipColorAt( r, move.col ) == m_curPlayer )
break;
m_board->setChipColor( r, move.col, m_curPlayer );
}
}
if( hasChunk( Left, move ) )
{
for(int c=move.col-1; c >= 0; --c)
{
if( m_board->chipColorAt( move.row, c ) == m_curPlayer )
break;
m_board->setChipColor( move.row, c, m_curPlayer );
}
}
if( hasChunk( Right, move ) )
{
for(int c=move.col+1; c < 8; ++c)
{
if( m_board->chipColorAt( move.row, c ) == m_curPlayer )
break;
m_board->setChipColor( move.row, c, m_curPlayer );
}
}
if( hasChunk( UpLeft, move ) )
{
for(int r=move.row-1, c=move.col-1; r>=0 && c >= 0; --r, --c)
{
if( m_board->chipColorAt( r, c ) == m_curPlayer )
break;
m_board->setChipColor( r, c, m_curPlayer );
}
}
if( hasChunk( UpRight, move ) )
{
for(int r=move.row-1, c=move.col+1; r>=0 && c < 8; --r, ++c)
{
if( m_board->chipColorAt( r, c ) == m_curPlayer )
break;
m_board->setChipColor( r, c, m_curPlayer );
}
}
if( hasChunk( DownLeft, move ) )
{
for(int r=move.row+1, c=move.col-1; r < 8 && c >= 0; ++r, --c)
{
if( m_board->chipColorAt( r, c ) == m_curPlayer )
break;
m_board->setChipColor( r, c, m_curPlayer );
}
}
if( hasChunk( DownRight, move ) )
{
for(int r=move.row+1, c=move.col+1; r < 8 && c < 8; ++r, ++c)
{
if( m_board->chipColorAt( r, c ) == m_curPlayer )
break;
m_board->setChipColor( r, c, m_curPlayer );
}
}
m_curPlayer = (m_curPlayer == White ? Black : White );
kDebug() << "Now " << (m_curPlayer == White ? "White" : "Black" )<< " play" << endl;
emit boardChanged();
}
bool KReversiGame::isMovePossible( const KReversiMove& move ) const
{
// first - the trivial case:
if( m_board->chipColorAt( move.row, move.col ) != NoColor || move.color == NoColor )
return false;
if( hasChunk( Up, move ) || hasChunk( Down, move )
|| hasChunk( Left, move ) || hasChunk( Right, move )
|| hasChunk( UpLeft, move ) || hasChunk( UpRight, move )
|| hasChunk( DownLeft, move ) || hasChunk( DownRight, move ) )
{
return true;
}
return false;
}
bool KReversiGame::hasChunk( Direction dir, const KReversiMove& move ) const
{
// On each step (as we proceed) we must ensure that current chip is of the
// opponent color.
// We'll do our steps until we reach the chip of player color or we reach
// the end of the board in this direction.
// If we found player-colored chip and number of opponent chips between it and
// the starting one is greater than zero, then Hurray! we found a chunk
//
// Well, I wrote this description from my head, now lets produce some code for that ;)
ChipColor opColor = ( move.color == White ? Black : White );
int opponentChipsNum = 0;
bool foundPlayerColor = false;
if( dir == Up )
{
for( int row=move.row-1; row >= 0; --row )
{
ChipColor color = m_board->chipColorAt( row, move.col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == Down )
{
for( int row=move.row+1; row < 8; ++row )
{
ChipColor color = m_board->chipColorAt( row, move.col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == Left )
{
for( int col=move.col-1; col >= 0; --col )
{
ChipColor color = m_board->chipColorAt( move.row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == Right )
{
for( int col=move.col+1; col < 8; ++col )
{
ChipColor color = m_board->chipColorAt( move.row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == UpLeft )
{
for( int row=move.row-1, col=move.col-1; row >= 0 && col >= 0; --row, --col )
{
ChipColor color = m_board->chipColorAt( row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == UpRight )
{
for( int row=move.row-1, col=move.col+1; row >= 0 && col < 8; --row, ++col )
{
ChipColor color = m_board->chipColorAt( row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == DownLeft )
{
for( int row=move.row+1, col=move.col-1; row < 8 && col >= 0; ++row, --col )
{
ChipColor color = m_board->chipColorAt( row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
else if( dir == DownRight )
{
for( int row=move.row+1, col=move.col+1; row < 8 && col < 8; ++row, ++col )
{
ChipColor color = m_board->chipColorAt( row, col );
if( color == opColor )
{
opponentChipsNum++;
}
else if(color == m_curPlayer)
{
foundPlayerColor = true;
break; //bail out
}
else // NoColor
break; // no luck in this direction
}
if(foundPlayerColor && opponentChipsNum != 0)
return true;
}
return false;
}
const KReversiBoard& KReversiGame::board() const
{
return *m_board;
}
int KReversiGame::playerScore( ChipColor player ) const
{
return m_board->playerScore( player );
}
ChipColor KReversiGame::chipColorAt( int row, int col ) const
{
return m_board->chipColorAt( row, col );
}
#include "kreversigame.moc"
......@@ -3,7 +3,9 @@
#include <QObject>
#include "kreversiboard.h"
#include "commondefs.h"
class KReversiBoard;
/**
* KReversiGame incapsulates all of the game logic.
......@@ -22,13 +24,36 @@ public:
* @returns the board so the callers can examine its current state
*/
const KReversiBoard& board() const;
ChipColor currentPlayer() const { return NoColor;/* FIXME dimsuz: implement */ }
int playerScore( ChipColor player ) const { return m_board->playerScore( player ); }
ChipColor chipColorAt( int row, int col ) const { return m_board->chipColorAt( row, col ); }
ChipColor currentPlayer() const { return m_curPlayer; }
// NOTE: this is just a wrapper around KReversiBoard::playerScore
// Maybe consider merging KReversiBoard into this class?
// same applies to chipColorAt
int playerScore( ChipColor player ) const;
// NOTE: this is just a wrapper around KReversiBoard::playerScore
ChipColor chipColorAt( int row, int col ) const;
void putChipAt(int row, int col);
signals:
void boardChanged();
private:
/**
* This function will tell you if the move is possible.
* That's why it was given such a name ;)
*/
bool isMovePossible( const KReversiMove& move ) const;
enum Direction { Up, Down, Right, Left, UpLeft, UpRight, DownLeft, DownRight };
/**
* Searches for "chunk" in direction dir for move.
* As my English-skills are somewhat limited, let me introduce
* new terminology ;).
* I'll define a "chunk" of chips for color "C" as follows:
* (let "O" be the color of the opponent for "C")
* CO[O]C <-- this is a chunk
* where [O] is one or more opponent's pieces
*/
bool hasChunk( Direction dir, const KReversiMove& move) const;
/**
* Board itself
*/
KReversiBoard *m_board;
/**
* Color of the current player
......
......@@ -25,6 +25,7 @@ void KReversiScene::setGame( KReversiGame* game )
{
m_game = game;
connect( m_game, SIGNAL(boardChanged()), this, SLOT(updateBoard()) );
// this will remove all items left from previous game
QList<QGraphicsItem*> allChips = items( m_boardRect );
foreach( QGraphicsItem* chip, allChips )
......@@ -32,6 +33,7 @@ void KReversiScene::setGame( KReversiGame* game )
removeItem( chip );
delete chip;
}
updateBoard();
}
......@@ -40,20 +42,24 @@ void KReversiScene::updateBoard()
for(int row=0; row<8; ++row)
for(int col=0; col<8; ++col )
{
if( m_game->chipColorAt( row, col ) != NoColor )
ChipColor color = m_game->chipColorAt( row, col );
if( color != NoColor )
{
// if there's a chip, just change it color
// otherwise create new
KReversiChip *chip = static_cast<KReversiChip*>(itemAt( cellCenter(row, col) ));
if( chip != 0 )
{
kDebug() << "Found item at (" << row << "," << col << "). Setting its color." << endl;
chip->setColor( m_game->chipColorAt( row, col ) );
if( chip->color() != color )
{
kDebug() << "Found item at (" << row << "," << col << "). Setting its color." << endl;
chip->setColor( color );
}
}
else
{
kDebug() << "No item at (" << row << "," << col << "). Creating." << endl;
chip = new KReversiChip( m_game->chipColorAt( row, col ), this );
chip = new KReversiChip( color, this );
chip->setPos( cellTopLeft(row, col) );
}
}
......
......@@ -4,8 +4,6 @@
#include <kdebug.h>
const int BOARD_SIZE = 8;
KReversiView::KReversiView( QGraphicsScene* scene, QWidget *parent )
: QGraphicsView(scene, parent)
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment