/*************************************************************************** * Copyright (C) 2005 by Torben Nielsen * * torben@t-hoerup.dk * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * 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 General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include #include #include #include #include #include #include #include #include "queensmain.h" #include "board.h" #include "queens.h" #include "solution.h" #include "solutionmatrix.h" #include "solutionint.h" #include "containervector.h" #include "containerlist.h" #include "containerhash.h" #include "containermnvector.h" #include "containerminimalvector.h" #include "config.h" QueensMain::QueensMain(QWidget *parent, const char *name) : QDialog(parent, name) { QVBoxLayout *mainlayout = new QVBoxLayout( this ); m_board = new Board( this ); m_start = new QPushButton("Start", this); m_quit = new QPushButton("Quit", this); m_stop = new QPushButton("Stop", this); m_stop->setEnabled( false ); QHBoxLayout *upperlayout = new QHBoxLayout( mainlayout ); QVBoxLayout *left = new QVBoxLayout( upperlayout ); upperlayout->add( m_board ); m_list = new QListBox( this ); m_list->setMinimumWidth( 180 ); m_sizeSelector = new QSpinBox( this ); m_status = new QLabel( this ); left->add( m_list ); left->add( m_sizeSelector ); QHBoxLayout *buttons = new QHBoxLayout( mainlayout ); buttons->add( m_start ); buttons->add( m_stop ); buttons->add( m_quit ); mainlayout->add( m_status ); m_sizeSelector->setMinValue( MIN_SIZE ); m_sizeSelector->setMaxValue( MAX_SIZE ); m_sizeSelector->setValue( 8 ); m_board->setSize( 8 ); m_storage = StorageInt; m_sortalgo = SortList; m_solutions = NULL; m_queens = NULL; m_sol = NULL; connect(m_quit, SIGNAL( clicked() ), qApp, SLOT( quit() ) ); connect(m_sizeSelector, SIGNAL( valueChanged(int) ), this, SLOT( resize(int) ) ); connect(m_start, SIGNAL( clicked() ), this, SLOT( start() ) ); connect(m_stop, SIGNAL( clicked() ), this, SLOT( stop() ) ); connect(m_list, SIGNAL( selectionChanged() ), this, SLOT( showSolution() ) ); connect( qApp, SIGNAL( lastWindowClosed() ), qApp, SLOT( quit() ) ); } QueensMain::~QueensMain() { delete m_board; if (m_solutions != NULL) delete m_solutions; if (m_sol != NULL) delete m_sol; } void QueensMain::start() { m_sizeSelector->setEnabled( false ); m_start->setEnabled( false ); m_stop->setEnabled( true ); m_list->clear(); m_status->setText( QString("Searching ...") ); m_board->setMatrix(0); if (m_queens != NULL) { m_queens->wait(); delete m_queens; m_queens = 0; } if (m_solutions != NULL) delete m_solutions; switch (m_sortalgo) { case SortList: m_solutions = new ContainerList(this); break; case SortVector: m_solutions = new ContainerVector(this); break; case SortHash: m_solutions = new ContainerHash(this); break; case SortMNVector: m_solutions = new ContainerMNVector(this); break; case SortMinimalVector: m_solutions = new ContainerMinimalVector(this); break; } if (m_sol != NULL) delete m_sol; switch(this->m_storage) { case StorageInt: m_sol = new SolutionInt(m_sizeSelector->value()); break; case StorageMatrix: m_sol = new SolutionMatrix(m_sizeSelector->value()); break; } m_elapsed.start(); m_time.start(); m_queens = new Queens(this, m_sol, m_solutions, m_sizeSelector->value() ,false); m_queens->start(); } void QueensMain::stop() { m_solutions->halt(); m_queens->stop(); m_queens->wait(); int num = m_solutions->numSolutions(); m_status->setText( QString("Aborted. Found ") + QString::number(num,10).append(" solutions") ); m_list->clear(); for (int i=1; i<=num; i++) m_list->insertItem( QString("Solution no ") + QString::number(i,10), i); delete m_queens; m_queens = NULL; m_list->setEnabled( true ); m_sizeSelector->setEnabled( true ); m_start->setEnabled( true ); m_stop->setEnabled( false ); } void QueensMain::foundSolution() { int num = m_solutions->numSolutions(); if (m_elapsed.elapsed() > 500) { m_status->setText( QString("Searching ... found ") + QString::number(num,10).append(" solutions") ); m_elapsed.restart(); } } void QueensMain::finishedSearch() { uniqueSolutions(); m_sizeSelector->setEnabled( true ); m_start->setEnabled( true ); m_stop->setEnabled( false ); } void QueensMain::showSolution() { int index = m_list->currentItem(); Solution* sol = m_solutions->solution( index ); m_board->setMatrix( sol ); } void QueensMain::resize(int size) { m_board->setSize( size ); m_board->repaint( true ); m_list->clear(); } QString QueensMain::elapsed() { int time = m_time.elapsed(); int msec = time % 1000; int sec = time / 1000; int min = sec / 60; sec %= 60; QString smsec = (QString::number(msec)).rightJustify(3, '0'); QString ssec = (QString::number(sec)).rightJustify(2,'0'); QString res; if (min!=0) res = QString("%1:%2.%3").arg(min).arg(ssec).arg(smsec); else res = QString("%1.%2").arg(sec).arg(smsec); return res; } void QueensMain::uniqueSolutions() { m_totalcount = m_solutions->totalSolutions(); m_status->setText( QString("sorting ") + QString::number(m_totalcount,10).append(" solutions...") ); m_elapsed.restart(); m_solutions->uniqueSolutions(); int uniq = m_solutions->numSolutions(); QString msg; msg = QString( "Found %1 unique solutions, of %2 total solutions. Time elapsed: %3" ).arg(uniq).arg(m_totalcount).arg( elapsed() ); m_list->clear(); for (int i=1; i<=uniq; i++) m_list->insertItem( QString("Unique solution no ") + QString::number(i,10), i); m_status->setText( msg ); } void QueensMain::contextMenuEvent( QContextMenuEvent *event) { QPopupMenu *contextMenu = new QPopupMenu( this ); contextMenu->setCheckable( true ); QLabel *sortCaption = new QLabel("Container class", this); sortCaption->setAlignment( Qt::AlignCenter ); contextMenu->insertItem( sortCaption ); contextMenu->insertItem("List", this, SLOT( sortList() ), 0, 1); contextMenu->insertItem("Vector", this, SLOT( sortVector() ), 0, 2); contextMenu->insertItem("Hash", this, SLOT( sortHash() ), 0, 3); contextMenu->insertItem("M*N Vector", this, SLOT(sortMNVector()), 0, 4); contextMenu->insertItem("Minimal Vector", this, SLOT(sortMinimalVector()), 0, 5); QLabel *storageCaption = new QLabel("Solution class", this); storageCaption->setAlignment( Qt::AlignCenter ); contextMenu->insertItem( storageCaption ); contextMenu->insertItem("Matrix Solution", this, SLOT( storageMatrix() ), 0, 6); contextMenu->insertItem("Int Solution", this, SLOT( storageInt() ), 0, 7); switch (m_sortalgo) { case SortList: contextMenu->setItemChecked( 1, true); break; case SortVector: contextMenu->setItemChecked( 2, true); break; case SortHash: contextMenu->setItemChecked( 3, true); break; case SortMNVector: contextMenu->setItemChecked( 4, true); break; case SortMinimalVector: contextMenu->setItemChecked( 5, true); break; } switch (m_storage) { case StorageMatrix: contextMenu->setItemChecked(6, true); break; case StorageInt: contextMenu->setItemChecked(7, true); break; } contextMenu->exec( event->globalPos() ); delete contextMenu; } void QueensMain::duplicateRemoved() { if (m_elapsed.elapsed() > 500) { int uniq = m_solutions->getUniqueRemoved(); QString status; status = QString ("Sorting %1 solutions. So far identified %2 duplicates").arg(m_totalcount).arg(uniq); m_status->setText(status); m_elapsed.restart(); } } void QueensMain::sortList() { m_sortalgo = SortList; } void QueensMain::sortVector() { m_sortalgo = SortVector; } void QueensMain::sortHash() { m_sortalgo = SortHash; } void QueensMain::sortMNVector() { m_sortalgo = SortMNVector; } void QueensMain::sortMinimalVector() { m_sortalgo = SortMinimalVector; } void QueensMain::storageInt() { m_storage = StorageInt; } void QueensMain::storageMatrix() { m_storage = StorageMatrix; }