You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdegames/tdefifteen/src/gameboard.cpp

402 lines
6.2 KiB

// Author: Denis Kozadaev - (c) 2017-2020
#include <cstdlib>
#include <tdeapplication.h>
#include <tqpainter.h>
#include <tqcursor.h>
#include <tqmessagebox.h>
#include <tqfiledialog.h>
#include <tqdatetime.h>
#include <tqwmatrix.h>
#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, TQ_SIGNAL(timeout()), this, TQ_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"