Root/Tile/src/tile.cpp

1#include "tile.h"
2#include "ui_tile.h"
3
4Tile::Tile(QWidget *parent) :
5    QMainWindow(parent),
6    ui(new Ui::Tile)
7{
8    ui->setupUi(this);
9    ui->pushButton_16->hide();
10    ui->pushButton->setProperty("id","1");
11    ui->pushButton_2->setProperty("id","2");
12    ui->pushButton_3->setProperty("id","3");
13    ui->pushButton_4->setProperty("id","4");
14    ui->pushButton_5->setProperty("id","5");
15    ui->pushButton_6->setProperty("id","6");
16    ui->pushButton_7->setProperty("id","7");
17    ui->pushButton_8->setProperty("id","8");
18    ui->pushButton_9->setProperty("id","9");
19    ui->pushButton_10->setProperty("id","10");
20    ui->pushButton_11->setProperty("id","11");
21    ui->pushButton_12->setProperty("id","12");
22    ui->pushButton_13->setProperty("id","13");
23    ui->pushButton_14->setProperty("id","14");
24    ui->pushButton_15->setProperty("id","15");
25    ui->pushButton_16->setProperty("id","16");
26    /*ui->pushButton_Reset->setProperty("id","Reset");
27    ui->pushButton_Shuffle->setProperty("id","Shuffle");
28    ui->pushButton_Help->setProperty("id","Help");
29    ui->pushButton_Quit->setProperty("id","Quit");*/
30    /*
31    ui->pushButton->setAccessibleDescription("1");
32    ui->pushButton_2->setAccessibleDescription("2");
33    ui->pushButton_3->setAccessibleDescription("3");
34    ui->pushButton_4->setAccessibleDescription("4");
35    ui->pushButton_5->setAccessibleDescription("5");
36    ui->pushButton_6->setAccessibleDescription("6");
37    ui->pushButton_7->setAccessibleDescription("7");
38    ui->pushButton_8->setAccessibleDescription("8");
39    ui->pushButton_9->setAccessibleDescription("9");
40    ui->pushButton_10->setAccessibleDescription("10");
41    ui->pushButton_11->setAccessibleDescription("11");
42    ui->pushButton_12->setAccessibleDescription("12");
43    ui->pushButton_13->setAccessibleDescription("13");
44    ui->pushButton_14->setAccessibleDescription("14");
45    ui->pushButton_15->setAccessibleDescription("15");
46    ui->pushButton_16->setAccessibleDescription("16");
47    */
48    // Create seed for the random
49    // That is needed only once on application startup
50    QTime time = QTime::currentTime();
51    qsrand((uint)time.msec());
52
53    qApp->installEventFilter(this);
54    //ui->pushButton->installEventFilter(this);
55}
56
57Tile::~Tile()
58{
59    delete ui;
60}
61
62void Tile::changeEvent(QEvent *e)
63{
64    QMainWindow::changeEvent(e);
65    switch (e->type()) {
66    case QEvent::LanguageChange:
67        ui->retranslateUi(this);
68        break;
69    default:
70        break;
71    }
72}
73
74void Tile::checkNeighbours()
75{
76    QPushButton *button = qobject_cast< QPushButton* >(QObject::sender());
77    //int id = button->accessibleDescription().toInt();
78    int id = button->property("id").toInt();
79    //check button to the right
80    if (id != 16 && id != 12 && id != 8 && id != 4) {
81        QPushButton *button_neighbour = idtoButton(id+1);
82        if (button_neighbour->text() == "16" && button_neighbour->isHidden()) {
83            swapButtons(button, button_neighbour);
84            return;
85        }
86    }
87    //check button to the left
88    if (id != 13 && id != 9 && id != 5 && id != 1) {
89        QPushButton *button_neighbour = idtoButton(id-1);
90        if (button_neighbour->text() == "16" && button_neighbour->isHidden()) {
91            swapButtons(button, button_neighbour);
92            return;
93        }
94    }
95    //check button to the bottom
96    if (id != 16 && id != 15 && id != 14 && id != 13) {
97        QPushButton *button_neighbour = idtoButton(id+4);
98        if (button_neighbour->text() == "16" && button_neighbour->isHidden()) {
99            swapButtons(button, button_neighbour);
100            return;
101        }
102    }
103    //check button to the up
104    if (id != 4 && id != 3 && id != 2 && id != 1) {
105        QPushButton *button_neighbour = idtoButton(id-4);
106        if (button_neighbour->text() == "16" && button_neighbour->isHidden()) {
107            swapButtons(button, button_neighbour);
108            return;
109        }
110    }
111    //qDebug() << "No swap candidates...";
112    return;
113}
114
115QPushButton* Tile::idtoButton(int id)
116{
117    switch (id) {
118    case 1:
119        return ui->pushButton;
120    case 2:
121        return ui->pushButton_2;
122    case 3:
123        return ui->pushButton_3;
124    case 4:
125        return ui->pushButton_4;
126    case 5:
127        return ui->pushButton_5;
128    case 6:
129        return ui->pushButton_6;
130    case 7:
131        return ui->pushButton_7;
132    case 8:
133        return ui->pushButton_8;
134    case 9:
135        return ui->pushButton_9;
136    case 10:
137        return ui->pushButton_10;
138    case 11:
139        return ui->pushButton_11;
140    case 12:
141        return ui->pushButton_12;
142    case 13:
143        return ui->pushButton_13;
144    case 14:
145        return ui->pushButton_14;
146    case 15:
147        return ui->pushButton_15;
148    case 16:
149        return ui->pushButton_16;
150    default:
151        break;
152    }
153    return NULL;
154}
155
156void Tile::swapButtons(QPushButton *button, QPushButton *button_neighbour) {
157    button->hide();
158    button_neighbour->setText(button->text());
159    button->setText("16");
160    button_neighbour->show();
161    button_neighbour->setFocus();
162    if (isRunning) {
163        Moves++;
164        updateMoves();
165    }
166    if (isRunning && isSolved()) {
167        isRunning = 0;
168        switch (QMessageBox::information(this,
169                                 "Solved!",
170                                 "Hooray, you solved it!\nShuffle again?",
171                                 "&Yes","&No"))
172        {
173        case 0:
174            Shuffle();
175        default:
176            break;
177        }
178    }
179}
180
181void Tile::Reset()
182{
183    isRunning = 0;
184    Moves=0;
185    updateMoves();
186    for (int i = 1; i < 16; i++) {
187        QPushButton *button = idtoButton(i);
188        QString str;
189        button->show();
190        button->setText(str.setNum(i));
191    }
192    QPushButton *button = idtoButton(16);
193    button->hide();
194    button->setText("16");
195}
196
197void Tile::Quit()
198{
199    switch (QMessageBox::information(this,
200                             "Confirm Quit",
201                             "Are you sure to quit?",
202                             "&Quit","&Cancel"))
203    {
204    case 0:
205        qApp->quit();
206    default:
207        break;
208    }
209}
210
211void Tile::Shuffle()
212{
213    Reset();
214    for (int i = 1; i < 16; i++) {
215        //get random number 1..15
216        int id = randInt(1,15);
217        //swap it
218        QPushButton *button_1 = idtoButton(i);
219        QPushButton *button_2 = idtoButton(id);
220        QString str = button_1->text();
221        button_1->setText(button_2->text());
222        button_2->setText(str);
223    }
224    if (!isSolvable()) {
225        Shuffle();
226    } else {
227        isRunning = 1;
228    }
229}
230
231int Tile::randInt(int low, int high)
232{
233    // Random number between low and high
234    return qrand() % ((high + 1) - low) + low;
235}
236
237bool Tile::isSolvable()
238{
239    //http://mathworld.wolfram.com/15Puzzle.html
240    //accumulator
241    int acc = 0;
242    //iterate through all tiles
243    for (int i = 1; i < 17; i++) {
244        //get button from id
245        QPushButton *button = idtoButton(i);
246        //get the number on tile
247        int num = button->text().toInt();
248        if (num == 16) {
249            //get row of empty tile
250            if (i < 5) {
251                acc = acc + 1;
252            } else if (i < 9) {
253                acc = acc + 2;
254            } else if (i < 13) {
255                acc = acc + 3;
256            } else {
257                acc = acc + 4;
258            }
259            continue;
260        }
261        //iterate though the rest of tiles
262        for (int j = i+1; j < 17; j++) {
263            //get next button
264            QPushButton *button_next = idtoButton(j);
265            //get the number of next tile
266            int num_next = button_next->text().toInt();
267            //compare and increment accumulator
268            if (num_next < num) {
269                acc++;
270            }
271        }
272    }
273    //qDebug() << acc;
274    if (acc%2 == 0) {
275        return 1;
276    } else {
277        return 0;
278    }
279}
280
281void Tile::Help()
282{
283    QMessageBox::about(this,
284            "15 Puzzle",
285            "\
286This is the famous 15 Puzzle game.\n\
287The object of the puzzle is to place the\n\
288tiles in order by making sliding moves\n\
289that use the empty space.\n\
290\n\
291\"Reset\" (Alt+R): reset the puzzle to solved position\n\
292\"Shuffle\" (Alt+S): shuffle the puzzle. Note that this\n\
293always produces solvable positions, don\'t give up\n\
294\"Help\" (Alt+H): show this help\n\
295\"Quit\" (Alt+Q): quit the app");
296}
297
298void Tile::keyPressEvent(QKeyEvent *event)
299{
300   if (event->key() == Qt::Key_Escape || event->key() == Qt::Key_Q) {
301       Quit();
302   } else if (event->key() == Qt::Key_Up) {
303       //focusNextChild();
304       //qDebug() << qApp->focusWidget();
305       QPushButton *button = qobject_cast< QPushButton* >(qApp->focusWidget());
306       keyUp(button);
307   } else if (event->key() == Qt::Key_Down) {
308       //focusPreviousChild();
309       //qDebug() << qApp->focusWidget();
310       QPushButton *button = qobject_cast< QPushButton* >(qApp->focusWidget());
311       keyDown(button);
312   } else {
313       return;
314   }
315}
316
317bool Tile::eventFilter(QObject *obj, QEvent *event)
318{
319    QKeyEvent *keyEvent = NULL;//event data, if this is a keystroke event
320    bool result = false;//return true to consume the keystroke
321
322    if (event->type() == QEvent::KeyPress)
323    {
324         keyEvent = dynamic_cast<QKeyEvent*>(event);
325         //override Key Up and Key Down only
326         if (keyEvent->key() == Qt::Key_Up || keyEvent->key() == Qt::Key_Down) {
327            this->keyPressEvent(keyEvent);
328            result = true;
329        } else {
330            result = QObject::eventFilter(obj, event);
331        }
332    }//if type()
333
334    /*else if (event->type() == QEvent::KeyRelease)
335    {
336        keyEvent = dynamic_cast<QKeyEvent*>(event);
337        this->keyReleaseEvent(keyEvent);
338        result = true;
339    }*///else if type()
340
341    //### Standard event processing ###
342    else
343        result = QObject::eventFilter(obj, event);
344
345    return result;
346}//eventFilter
347
348void Tile::keyUp(QPushButton *button)
349{
350    int id = button->property("id").toInt();
351    QPushButton *button_up;
352    if (id < 5) {
353        button_up = idtoButton(id+12);
354    } else {
355        button_up = idtoButton(id-4);
356    }
357    if (button_up->isHidden()) {
358        keyUp(button_up);
359    } else {
360        button_up->setFocus();
361    }
362}
363
364void Tile::keyDown(QPushButton *button)
365{
366    int id = button->property("id").toInt();
367    QPushButton *button_down;
368    if (id > 12) {
369        button_down = idtoButton(id-12);
370    } else {
371        button_down = idtoButton(id+4);
372    }
373    if (button_down->isHidden()) {
374        keyDown(button_down);
375    } else {
376        button_down->setFocus();
377    }
378}
379
380bool Tile::isSolved()
381{
382    QPushButton *button;
383    for (int i = 1; i < 17; i++) {
384        button = idtoButton(i);
385        if (button->text() != button->property("id")) {
386            return 0;
387        }
388    }
389    return 1;
390}
391
392void Tile::updateMoves()
393{
394    QString mooves;
395    ui->moves->setText("Moves:\n"+mooves.setNum(Moves));
396}
397

Archive Download this file



interactive