// Author: Denis Kozadaev - (c) 2017-2020 #include #include #include #include #include #include #include #include #include "gameboard.h" #define DELAY 10 #define STEP 5 BoardItem::BoardItem(int n, TQWidget *parent, const char *name) :TQLabel(parent, name) { num = n; } BoardItem::~BoardItem() { } void BoardItem::paintEvent(TQPaintEvent *e) { TQPainter *p; int w = width() - 1, h = height() - 1; TQLabel::paintEvent(e); p = new TQPainter(this); p->setPen(TQt::black); p->drawRect(0, 0, w, h); p->setPen(TQt::magenta); p->drawText(0, 0, w, h, TQt::AlignCenter, TQString::number(item() + 1)); delete p; } //------------------------------------------------------------------------------ GameBoard::GameBoard(TQWidget *parent, const char *name) :TQWidget(parent, name) { #include "cat.xpm" TQPixmap xpm(cat_xpm); memset(map, 0, sizeof(map)); nt = n = xt = yt = -1; dx = dy = 0; tmr = new TQTimer(this); TQObject::connect(tmr, SIGNAL(timeout()), this, SLOT(moveItem())); setEnabled(TRUE); origin = xpm; } GameBoard::~GameBoard() { int i; for (i = 0; i < 16; ++i) if (map[i] != NULL) delete map[i]; delete tmr; } void GameBoard::resizeEvent(TQResizeEvent *e) { TQWidget::resizeEvent(e); initMap(); } void GameBoard::initMap() { const int num = 15; int i, x, y, w = width() / 4, h = height() / 4; TQFont fnt("Antiqua", 18); TQPixmap xpm; if (!origin.isNull()) { TQWMatrix mtx; mtx.scale((float)width() / (float)origin.width(), (float)height() / (float)origin.height()); xpm = origin.xForm(mtx); } for (i = 0; i < num; ++i) { if (map[i] != NULL) delete map[i]; map[i] = new BoardItem(i, this); map[i]->setFont(fnt); map[i]->resize(w, h); map[i]->setAlignment(TQt::AlignCenter); if (!xpm.isNull()) { y = (i >> 2); x = i - (y << 2); map[i]->move(x * w, y * h); TQPixmap xpm1(map[i]->size()); copyBlt(&xpm1, 0, 0, &xpm, map[i]->x(), map[i]->y(), w, h); map[i]->setPixmap(xpm1); } } if (map[num] != NULL) delete map[num]; map[num] = NULL; } void GameBoard::mousePressEvent(TQMouseEvent *e) { int x = e->x(), y = e->y(), i, it; i = index(x, y); if (mayMove(i) && (n == -1)) { for (it = 0; (it < 16) && (map[it] != NULL); ++it); startMoving(i, it); } } int GameBoard::mayMove(int n) { int res = 0; if ((n >= 0) && (n < 16)) { switch (n) { case 0: res = (map[n + 1] == NULL) || (map[n + 4] == NULL); break; case 1: case 2: res = (map[n - 1] == NULL) || (map[n + 1] == NULL) || (map[n + 4] == NULL); break; case 3: res = (map[n - 1] == NULL) || (map[n + 4] == NULL); break; case 4: case 8: res = (map[n + 1] == NULL) || (map[n - 4] == NULL) || (map[n + 4] == NULL); break; case 5: case 6: case 9: case 10: res = (map[n - 1] == NULL) || (map[n + 1] == NULL) || (map[n - 4] == NULL) || (map[n + 4] == NULL); break; case 7: case 11: res = (map[n - 1] == NULL) || (map[n - 4] == NULL) || (map[n + 4] == NULL); break; case 12: res = (map[n + 1] == NULL) || (map[n - 4] == NULL); break; case 13: case 14: res = (map[n - 1] == NULL) || (map[n + 1] == NULL) || (map[n - 4] == NULL); break; case 15: res = (map[n - 1] == NULL) || (map[n - 4] == NULL); break; } } return (res); } int GameBoard::index(int x, int y) { int ndx = -1, i, x1, y1; if ((map[0] != NULL) || (map[1] != NULL)) { for (i = 0; i < 16; ++i) { if (map[i] != NULL) { x1 = map[i]->x(); y1 = map[i]->y(); if ((x >= x1) && (y >= y1) && (x < (x1 + map[i]->width())) && (y < (y1 + map[i]->height()))) { ndx = i; break; } } } } return (ndx); } void GameBoard::startMoving(int i, int t) { n = i; nt = t; xt = (t - (t & ~3)) * map[n]->width(); yt = (t >> 2) * map[n]->height(); dx = step(xt, map[n]->x()); dy = step(yt, map[n]->y()); tmr->start(DELAY); TDEApplication::setOverrideCursor(TQCursor(TQt::WaitCursor)); } int GameBoard::step(int t, int f) { int res; if (t > f) res = STEP; else if (t < f) res = -STEP; else res = 0; return (res); } void GameBoard::moveItem() { int x, y, stp, a; if ((n != -1) && (nt != -1) && (map[n] != NULL)) { x = map[n]->x(); y = map[n]->y(); stp = 0; if (dx != 0) { stp = (x == xt); if (!stp) { a = abs(x - xt); if (a < abs(dx)) dx = sign(dx) * a; x += dx; } } else if (dy != 0) { stp = (y == yt); if (!stp) { a = abs(y - yt); if (a < abs(dy)) dy = sign(dy) * a; y += dy; } } map[n]->move(x, y); if (stp) { map[nt] = map[n]; map[n] = NULL; nt = n = -1; xt = yt = -1; dx = dy = 0; tmr->stop(); TDEApplication::restoreOverrideCursor(); checkEndGame(); } } } int GameBoard::sign(int x) { int res; if (x > 0) res = 1; else if (x < 0) res = -1; else res = 0; return (res); } void GameBoard::checkEndGame() { int i, n; TQString txt; for (n = i = 0; i < 15; ++i) if ((map[i] != NULL) && (map[i]->item() == i)) n++; if (n == 15) { txt = tr("Game Over"); TQMessageBox::information(this, txt, txt); setEnabled(FALSE); } } void GameBoard::newGame() { setEnabled(TRUE); initMap(); newTask(); } void GameBoard::newTask() { int i, n, stp, x, y; BoardItem *tmp; srandom(TQDateTime::currentDateTime().toTime_t()); do { stp = (random() % 13) & 0xF; if ((stp & 1) == 0) stp++; } while (stp % 5 == 0); n = random() & 0xF; for (i = 0; i < 16; ++i) { n += stp; if (n > 15) n -= 16; tmp = map[i]; map[i] = map[n]; map[n] = tmp; } for (i = 0; i < 16; ++i) if (map[i] != NULL) { y = (i >> 2); x = i - (y << 2); map[i]->move(x * map[i]->width(), y * map[i]->height()); map[i]->show(); } } void GameBoard::loadImage() { TQString str; TQPixmap img; str = TQFileDialog::getOpenFileName(TQString::null, "*", this, NULL, tr("Open an image...")); if (!str.isEmpty()) { if (img.load(str)) { origin = img; initMap(); } else TQMessageBox::critical(this, tr("Error loading..."), tr("Cannot load the image ") + str); } } #include "gameboard.moc"