OpenWrt packages
Sign in or create your account | Project List | Help
OpenWrt packages Git Source Tree
Root/
| 1 | #include "tile.h" |
| 2 | #include "ui_tile.h" |
| 3 | |
| 4 | Tile::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 | |
| 57 | Tile::~Tile() |
| 58 | { |
| 59 | delete ui; |
| 60 | } |
| 61 | |
| 62 | void 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 | |
| 74 | void 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 | |
| 115 | QPushButton* 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 | |
| 156 | void 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 | |
| 181 | void 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 | |
| 197 | void 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 | |
| 211 | void 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 | |
| 231 | int Tile::randInt(int low, int high) |
| 232 | { |
| 233 | // Random number between low and high |
| 234 | return qrand() % ((high + 1) - low) + low; |
| 235 | } |
| 236 | |
| 237 | bool 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 | |
| 281 | void Tile::Help() |
| 282 | { |
| 283 | QMessageBox::about(this, |
| 284 | "15 Puzzle", |
| 285 | "\ |
| 286 | This is the famous 15 Puzzle game.\n\ |
| 287 | The object of the puzzle is to place the\n\ |
| 288 | tiles in order by making sliding moves\n\ |
| 289 | that 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\ |
| 293 | always 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 | |
| 298 | void 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 | |
| 317 | bool 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 | |
| 348 | void 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 | |
| 364 | void 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 | |
| 380 | bool 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 | |
| 392 | void Tile::updateMoves() |
| 393 | { |
| 394 | QString mooves; |
| 395 | ui->moves->setText("Moves:\n"+mooves.setNum(Moves)); |
| 396 | } |
| 397 |
