Commit 7b9ee4cc authored by Dmitry Suzdalev's avatar Dmitry Suzdalev

Implemented undoing.

It allows to undo only one step atm

svn path=/branches/work/kreversi_rewrite/; revision=573261
parent 5914c466
......@@ -32,16 +32,25 @@ int KReversiBoard::playerScore( ChipColor player ) const
return m_score[player];
}
void KReversiBoard::setChipColor(int row, int col, ChipColor color)
void KReversiBoard::setChipColor(ChipColor color, int row, int col)
{
Q_ASSERT( row < 8 && col < 8 );
// first: if the current cell already contains a chip of the opponent,
// we'll decrease opponents score
if( m_cells[row][col] != NoColor && m_cells[row][col] != color )
if( m_cells[row][col] != NoColor && color != NoColor && m_cells[row][col] != color )
m_score[opponentColorFor(color)]--;
// if the cell contains some chip and is being replaced by NoColor,
// we'll decrease the score of that color
// Such replacements (with NoColor) occur during undoing
// and now replacing with chip of 'color'
if( m_cells[row][col] != NoColor && color == NoColor )
m_score[ m_cells[row][col] ]--;
m_cells[row][col] = color;
m_score[color]++;
if( color != NoColor )
m_score[color]++;
kDebug() << "Score of White player: " << m_score[White] << endl;
kDebug() << "Score of Black player: " << m_score[Black] << endl;
}
......
......@@ -20,7 +20,7 @@ public:
/**
* Sets the type of chip at (row,col)
*/
void setChipColor(int row, int col, ChipColor type);
void setChipColor(ChipColor type, int row, int col);
/**
* Retruns type of the chip in cell at (row, col)
*/
......
......@@ -34,6 +34,7 @@ void KReversiGame::makePlayerMove( int row, int col )
return;
}
makeMove( move );
m_lastUndoPlayer = m_changedChips;
}
void KReversiGame::makeComputerMove()
......@@ -50,13 +51,60 @@ void KReversiGame::makeComputerMove()
Q_ASSERT(move.color == m_computerColor);
kDebug() << "Computer plays ("<<move.row<<","<<move.col<<")" <<endl;
makeMove(move);
m_lastUndoComputer = m_changedChips;
}
void KReversiGame::undo()
{
if( m_lastUndoPlayer.isEmpty() || m_lastUndoComputer.isEmpty() )
return;
// NOTE the order of undoing matters here -
// first computer (which plays second)
// and then player (which plays first)
//
// Another thing that matters is that we take the
// chip color directly from board, rather than from move.color
// That allows to take into account undo from first list, while
// undoing changes which are in the second list
// Sounds not very understandable?
// Then try to use move.color instead of chipColorAt
// and it will mess things when undoing such moves as
// "Player captures computer-owned chip,
// Computer makes move and captures this chip back"
// Yes, I like long descriptions in comments ;).
// let's undo computer move
KReversiMove move = m_lastUndoComputer.takeFirst();
m_board->setChipColor( NoColor, move.row, move.col );
// and change back the color of the rest chips
foreach( KReversiMove mv, m_lastUndoComputer )
{
// NOTE: if chipColorAt == NoColor here, we've some serious problem. It shouldn't be :)
ChipColor opponentColor = (m_board->chipColorAt(mv.row,mv.col) == White ? Black : White);
m_board->setChipColor( opponentColor, mv.row, mv.col );
}
m_lastUndoComputer.clear();
// now the same steps with player's turn:
move = m_lastUndoPlayer.takeFirst();
m_board->setChipColor( NoColor, move.row, move.col );
// and change back the color of the rest chips
foreach( KReversiMove mv, m_lastUndoPlayer )
{
// NOTE: if chipColorAt == NoColor here, we've some serious problem. It shouldn't be :)
ChipColor opponentColor = (m_board->chipColorAt(mv.row,mv.col) == White ? Black : White);
m_board->setChipColor( opponentColor, mv.row, mv.col );
}
m_lastUndoPlayer.clear();
emit boardChanged();
}
void KReversiGame::makeMove( const KReversiMove& move )
{
m_changedChips.clear();
m_board->setChipColor( move.row, move.col, move.color );
m_board->setChipColor( move.color, move.row, move.col );
// the first one is the move itself
m_changedChips.append( move );
// now turn color of all chips that were won
......@@ -66,7 +114,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, move.col ) == move.color )
break;
m_board->setChipColor( r, move.col, move.color );
m_board->setChipColor( move.color, r, move.col );
m_changedChips.append( KReversiMove( move.color, r, move.col ) );
}
}
......@@ -76,7 +124,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, move.col ) == move.color )
break;
m_board->setChipColor( r, move.col, move.color );
m_board->setChipColor( move.color, r, move.col );
m_changedChips.append( KReversiMove( move.color, r, move.col ) );
}
}
......@@ -86,7 +134,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( move.row, c ) == move.color )
break;
m_board->setChipColor( move.row, c, move.color );
m_board->setChipColor( move.color, move.row, c );
m_changedChips.append( KReversiMove( move.color, move.row, c ) );
}
}
......@@ -96,7 +144,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( move.row, c ) == move.color )
break;
m_board->setChipColor( move.row, c, move.color );
m_board->setChipColor( move.color, move.row, c );
m_changedChips.append( KReversiMove( move.color, move.row, c ) );
}
}
......@@ -106,7 +154,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, c ) == move.color )
break;
m_board->setChipColor( r, c, move.color );
m_board->setChipColor( move.color, r, c );
m_changedChips.append( KReversiMove( move.color, r, c ) );
}
}
......@@ -116,7 +164,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, c ) == move.color )
break;
m_board->setChipColor( r, c, move.color );
m_board->setChipColor( move.color, r, c );
m_changedChips.append( KReversiMove( move.color, r, c ) );
}
}
......@@ -126,7 +174,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, c ) == move.color )
break;
m_board->setChipColor( r, c, move.color );
m_board->setChipColor( move.color, r, c );
m_changedChips.append( KReversiMove( move.color, r, c ) );
}
}
......@@ -136,7 +184,7 @@ void KReversiGame::makeMove( const KReversiMove& move )
{
if( m_board->chipColorAt( r, c ) == move.color )
break;
m_board->setChipColor( r, c, move.color );
m_board->setChipColor( move.color, r, c );
m_changedChips.append( KReversiMove( move.color, r, c ) );
}
}
......
......@@ -42,6 +42,10 @@ public:
* wants to put his chip... and he'll put it there!
*/
void makeComputerMove();
/**
* Undoes the last player-computer move pair
*/
void undo();
/**
* Returns true, if it's computer's turn now
*/
......@@ -100,5 +104,15 @@ private:
* move.
*/
QList<KReversiMove> m_changedChips;
/**
* This list holds chips changed with last computer move
* and is used while undoing
*/
QList<KReversiMove> m_lastUndoComputer;
/**
* This list holds chips changed with last player move
* and is used while undoing
*/
QList<KReversiMove> m_lastUndoPlayer;
};
#endif
......@@ -45,7 +45,6 @@ void KReversiScene::setGame( KReversiGame* game )
updateBoard();
}
// FIXME dimsuz: seems like it is obsolete now. Remove it?
void KReversiScene::updateBoard()
{
for(int row=0; row<8; ++row)
......@@ -72,6 +71,11 @@ void KReversiScene::updateBoard()
chip->setPos( cellTopLeft(row, col) );
}
}
else
{
// this if-branch happens on undos
delete itemAt( cellCenter(row, col) );
}
}
}
......@@ -105,7 +109,9 @@ void KReversiScene::slotAnimationStep()
m_animTimer->stop();
// next turn
if( m_game->computersTurn() )
{
m_game->makeComputerMove();
}
}
}
}
......@@ -162,6 +168,11 @@ void KReversiScene::mousePressEvent( QGraphicsSceneMouseEvent* ev )
return;
int row = (int)ev->scenePos().y() / CHIP_SIZE;
int col = (int)ev->scenePos().x() / CHIP_SIZE;
if( row < 0 ) row = 0;
if( row > 7 ) row = 7;
if( col < 0 ) col = 0;
if( col > 7 ) col = 7;
kDebug() << "Cell (" << row << "," << col << ") clicked." << endl;
......
......@@ -6,6 +6,9 @@
<Action name="new_game"/>
<Action name="quit"/>
</Menu>
<Menu name="edit"><text>&amp;Edit</text>
<Action name="undo"/>
</Menu>
<Menu name="settings"><text>&amp;Settings</text>
<Action name="choose_bkgnd" />
</Menu>
......@@ -13,5 +16,6 @@
<ToolBar name="mainToolBar"><text>Main Toolbar</text>
<Action name="new_game"/>
<Action name="undo" />
</ToolBar>
</kpartgui>
......@@ -14,12 +14,10 @@
#include <QGraphicsView>
KReversiMainWindow::KReversiMainWindow(QWidget* parent)
: KMainWindow(parent)
: KMainWindow(parent), m_scene(0), m_game(0)
{
m_game = new KReversiGame;
// FIXME dimsuz: if chips.png not found give error end exit
m_scene = new KReversiScene(m_game, KStandardDirs::locate("appdata", "pics/chips.png"));
slotNewGame();
// m_scene is created in slotNewGame();
m_view = new KReversiView(m_scene, this);
m_view->show();
......@@ -32,7 +30,8 @@ KReversiMainWindow::KReversiMainWindow(QWidget* parent)
void KReversiMainWindow::setupActions()
{
KAction *quitAct = KStdAction::quit(this, SLOT(close()), actionCollection(), "quit");
KAction *newGameAct = KStdAction::openNew(this, SLOT(newGame()), actionCollection(), "new_game");
KAction *newGameAct = KStdAction::openNew(this, SLOT(slotNewGame()), actionCollection(), "new_game");
KAction *undoAct = KStdAction::undo( this, SLOT(slotUndo()), actionCollection(), "undo" );
KSelectAction *bkgndAct = new KSelectAction(i18n("Choose background"), actionCollection(), "choose_bkgnd");
connect(bkgndAct, SIGNAL(triggered(const QString&)), SLOT(slotBackgroundChanged(const QString&)));
......@@ -54,6 +53,7 @@ void KReversiMainWindow::setupActions()
addAction(newGameAct);
addAction(quitAct);
addAction(undoAct);
}
void KReversiMainWindow::slotBackgroundChanged( const QString& text )
......@@ -71,11 +71,25 @@ void KReversiMainWindow::slotBackgroundChanged( const QString& text )
}
}
void KReversiMainWindow::newGame()
void KReversiMainWindow::slotNewGame()
{
delete m_game;
m_game = new KReversiGame;
m_scene->setGame( m_game );
if(m_scene == 0) // if called first time
{
// FIXME dimsuz: if chips.png not found give error end exit
m_scene = new KReversiScene(m_game, KStandardDirs::locate("appdata", "pics/chips.png"));
}
else
{
m_scene->setGame( m_game );
}
}
void KReversiMainWindow::slotUndo()
{
m_game->undo();
}
#include "mainwindow.moc"
......@@ -6,6 +6,7 @@
class KReversiScene;
class KReversiGame;
class KReversiView;
class KAction;
class KReversiMainWindow : public KMainWindow
{
......@@ -13,8 +14,9 @@ class KReversiMainWindow : public KMainWindow
public:
KReversiMainWindow(QWidget* parent=0);
public slots:
void newGame();
void slotNewGame();
void slotBackgroundChanged(const QString& text);
void slotUndo();
private:
void setupActions();
......
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