I do not see the architecture of your program as the important stuff is missing. I would expect you got a list of objects per page with their positions,size,labels,color etc. in form of some arrays of struct
and loop through that for booth rendering and mouse handling. Something like this
- Does anyone know of a low level (no frameworks) example of a drag & drop, re-order-able list?
just ignore the VCL stuff TCanvas,Graphics::TBitmap
so ignore lines starting with bmp->
or scr->
(or port them into your graphics).
not sure if it helps but I just dig my ancient mine sweep game with partial solver using mouse in Turbo C++. It looks like this:
Here Turbo C++ source for it:
//===========================================================================
//=== Includes: =============================================================
//===========================================================================
#include <stdlib.h>
//===========================================================================
//=== Types: ================================================================
//===========================================================================
typedef unsigned char byte;
typedef unsigned int word;
typedef unsigned long dword;
//===========================================================================
//=== Headers: ==============================================================
//===========================================================================
void initscr(); // 320*200*256, BW palette
void clrscr(); // clear scr
void rfsscr(); // vga << scr
void box(word x,word y,word a); // draw box a <0..cfree> at x,y
void boardint(); // init mines, clear board map
void boardprn(); // draw board map
void mouseint(); // init mouse
void mousetst(); // test mouse (x,y,buttons)
void numprn(word x,word y,word n); // write number n <0..9999> at x,y
void boardtst0(int x,int y,int &n); // sub test count number of mines around
void boardtst(int x,int y); // test number of mines around if error then boardend;
void boardend(); // game over (lose)
void boardwin(); // game over (win)
int boardopt0(int x,int y);
void boardopt1(int x,int y,int &c);
int boardopt2(int x,int y);
void boardopt3(int x,int y,int &c);
void boardopt(); // optimized search
//===========================================================================
//=== Global data: ==========================================================
//===========================================================================
const c0=25; // used colors
const c1=30;
const c2=20;
const c3=40;
const c4=34;
const c5=35;
const c6=5;
const cfree=13;
const boardx=30; // board size
const boardy=16;
const minesn=99; // number of mines
const boardx0=(320-(10*boardx))/2;
const boardy0=(190-(10*boardy))/2+10;
byte board[32][20];
byte mines[32][20];
word far *pit;
long xtime0,xtime;
int flags;
word scrseg,scrofs;
word mousex=0,mousey=0,
mousel=0,mouser=0,
mousel0=0,mouser0=0,
mousebx=255,mouseby=255;
byte far scr[64000],*vga; // 320x200x8bpp backbuffer and VGA screen
byte far mouset[10][10]= // mouse cursor
{
1,1,0,0,0,0,0,0,0,0,
1,1,1,1,0,0,0,0,0,0,
1,1,1,1,1,1,0,0,0,0,
1,1,1,1,0,0,0,0,0,0,
1,1,1,1,0,0,0,0,0,0,
1,0,0,1,1,0,0,0,0,0,
1,0,0,0,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0
};
byte far txr[14*100]= // board tiles
{
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c5,c5,c0,c0,c0,c2,
c1,c0,c0,c5,c0,c0,c5,c0,c0,c2,
c1,c0,c0,c5,c0,c0,c5,c0,c0,c2,
c1,c0,c0,c5,c0,c0,c5,c0,c0,c2,
c1,c0,c0,c5,c0,c0,c5,c0,c0,c2,
c1,c0,c0,c0,c5,c5,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c4,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c4,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c4,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c3,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c3,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c3,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c4,c0,c0,c3,c0,c0,c2,
c1,c0,c0,c0,c3,c3,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c6,c6,c0,c0,c0,c0,c2,
c1,c0,c0,c6,c6,c6,c6,c0,c0,c2,
c1,c0,c0,c6,c6,c6,c6,c0,c0,c2,
c1,c0,c0,c6,c0,c6,c6,c0,c0,c2,
c1,c0,c0,c6,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c6,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c6,c6,c0,c0,c0,c2,
c1,c0,c0,c6,c6,c6,c6,c0,c0,c2,
c1,c0,c0,c6,c6,c6,c6,c0,c0,c2,
c1,c0,c0,c0,c6,c6,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c6,c0,c0,c0,c0,c6,c0,c2,
c1,c0,c0,c6,c0,c0,c6,c0,c0,c2,
c1,c0,c0,c0,c6,c6,c0,c0,c0,c2,
c1,c0,c0,c0,c6,c6,c0,c0,c0,c2,
c1,c0,c0,c6,c0,c0,c6,c0,c0,c2,
c1,c0,c6,c0,c0,c0,c0,c6,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2,
c2,c1,c1,c1,c1,c1,c1,c1,c1,c1,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c0,c0,c0,c0,c0,c0,c0,c0,c2,
c1,c2,c2,c2,c2,c2,c2,c2,c2,c2
};
//===========================================================================
//=== Subroutines: ==========================================================
//===========================================================================
void initscr()
{
dword h,l;
int i;
vga=(byte far*)0x0A0000000;
h=(unsigned long)scr; l=h;
l=l & 65535;
h=h >> 16;
scrseg=h;
scrofs=l;
asm {
mov ax,0x0013
int 0x10
}
for (i=0;i<256;i++) // set color palette to grayscale
asm {
mov dx,0x03C8
mov ax,i
out dx,al
mov dx,0x03C9
mov ax,i
out dx,al
out dx,al
out dx,al
}
}
//===========================================================================
void clrscr()
{
asm {
pusha
push es
mov di,scrofs
mov es,scrseg
mov ax,0x1313
mov cx,32000
rep stosw
pop es
popa
}
}
//===========================================================================
void rfsscr()
{
asm {
pusha
push ds
push es
mov di,0
mov si,scrofs
mov ds,scrseg
mov ax,0xA000
mov es,ax
mov cx,32000
rep movsw
pop es
pop ds
popa
}
}
//===========================================================================
void box(word x,word y,word a)
{
word b;
a=a*100;
b=x+320*y;
for (y=0;y<10;y++)
{
for (x=0;x<10;x++) scr[b+x]=txr[a+x];
b+=320;
a+=10;
}
}
//===========================================================================
void boardint()
{
word i,x,y;
for (y=0;y<boardy;y++)
for (x=0;x<boardx;x++)
{
board[x][y]=cfree;
mines[x][y]=0;
}
randomize();
for (i=0;i<minesn;i++)
{
x=random(boardx);
y=random(boardy);
if (mines[x][y]) i--;
else mines[x][y]=1;
}
}
//===========================================================================
void boardprn()
{
word x,y,i,j;
clrscr();
x=boardx0;
y=boardy0;
for (j=0;j<boardy;j++)
for (i=0;i<boardx;i++) box(x+10*i,y+10*j,board[i][j]);
box(310,0,12); // X .. exit button
box(150,0,11); // O .. restart button
box(160,0,11);
box( 0,0,10); // flag
xtime=pit[0]; // time
xtime=xtime-xtime0;
if (xtime<0) xtime=-xtime;
xtime=xtime*55/1000;
if (xtime>9999) xtime=9999;
numprn(260,0,xtime);
numprn( 20,0,flags); // flags
}
//===========================================================================
void mouseint()
{
mousex=0;
mousey=0;
mousel=0;
mouser=0;
asm {
pusha
push ds
push es
mov ax,0 // reset mouse
int 0x33
mov cx,0 // set range
mov dx,319
mov ax,7
int 0x33
mov cx,0
mov dx,199
mov ax,8
int 0x33
mov cx,mousex // set pos.
mov dx,mousey
mov ax,4
int 0x33
pop es
pop ds
popa
}
mousetst();
}
//===========================================================================
void mousetst()
{
int b,x,y;
asm {
mov ax,3 // in mouse status test
int 0x33
mov mousex,cx
mov mousey,dx
and bx,3
mov b,bx
}
mousel0=mousel;
mouser0=mouser;
mousel=b&1;
mouser=(b&2)>>1;
for (y=0;y<10;y++)
for (x=0;x<10;x++)
{
if (mouset[y][x])
if (x+mousex<320)
if (y+mousey<200)
scr[(x+mousex)+320*(y+mousey)]=63;
}
mousebx=255; x=mousex-boardx0;
mouseby=255; y=mousey-boardy0;
if (x>=0) if (x<boardx*10) if (x%10>1) if (x%10<9) mousebx=x/10;
if (y>=0) if (y<boardy*10) if (y%10>1) if (y%10<9) mouseby=y/10;
}
//===========================================================================
void numprn(word x,word y,word n)
{
int i,c;
x+=3*10;
c=10;
for (i=0;i<4;i++)
{
box(x,y,n%c);
n=(n-(n%c))/c;
x-=10;
}
}
//===========================================================================
void boardtst0(int x,int y,int &n)
{
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (mines[x][y])
n++;
}
//===========================================================================
void boardtst(int x,int y)
{
int n=0;
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (board[x][y]==cfree)
{
boardtst0(x-1,y+0,n);
boardtst0(x+1,y+0,n);
boardtst0(x-1,y-1,n);
boardtst0(x+0,y-1,n);
boardtst0(x+1,y-1,n);
boardtst0(x-1,y+1,n);
boardtst0(x+0,y+1,n);
boardtst0(x+1,y+1,n);
board[x][y]=n;
if (n==0)
{
boardtst(x-1,y+0);
boardtst(x+1,y+0);
boardtst(x-1,y-1);
boardtst(x+0,y-1);
boardtst(x+1,y-1);
boardtst(x-1,y+1);
boardtst(x+0,y+1);
boardtst(x+1,y+1);
}
}
}
//===========================================================================
void boardend()
{
int x,y;
byte a,b,c;
for (y=0;y<boardy;y++)
for (x=0;x<boardx;x++)
{
a=mines[x][y];
b=board[x][y];
c=b;
if (a) if (b!=10) c=11;
if (!a) if (b==10) c=12;
board[x][y]=c;
}
boardprn();
rfsscr();
do { mousetst(); } while (mousel==1);
do { mousetst(); } while (mousel==0);
boardint();
xtime0=pit[0];
flags=minesn;
}
//===========================================================================
void boardwin()
{
int x,y;
byte a,b,c;
c=1;
for (y=0;y<boardy;y++)
for (x=0;x<boardx;x++)
{
a=mines[x][y];
b=board[x][y];
if ( a) if (b!=10) c=0;
if (!a) if (b==10) c=0;
if (!a) if (b==cfree) c=0;
}
if (c) {
boardprn();
box(150,0,10); // O .. restart button
box(160,0,10);
rfsscr();
do { mousetst(); } while (mousel==1);
do { mousetst(); } while (mousel==0);
boardint();
xtime0=pit[0];
flags=minesn;
}
}
//===========================================================================
int boardopt0(int x,int y)
{
int n=0;
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (board[x][y]<9) n=1;
return n;
}
//===========================================================================
void boardopt1(int x,int y,int &c)
{
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (board[x][y]==cfree)
if (flags)
{
board[x][y]=10;
flags--;
c=1;
}
}
//===========================================================================
int boardopt2(int x,int y)
{
int n=0;
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (board[x][y]==10) n=1;
return n;
}
//===========================================================================
void boardopt3(int x,int y,int &c)
{
if (x>=0) if (x<boardx)
if (y>=0) if (y<boardy)
if (board[x][y]==cfree)
{
boardtst(x,y);
c=1;
}
}
//===========================================================================
void boardopt()
{
int x,y,n,c;
byte a;
do {
c=0; // flag map changed
for (y=0;y<boardy;y++)
for (x=0;x<boardx;x++)
{
a=board[x][y];
if (a!=cfree)
{
n=8; // add flags
if (boardopt0(x-1,y+0)) n--;
if (boardopt0(x+1,y+0)) n--;
if (boardopt0(x-1,y-1)) n--;
if (boardopt0(x+0,y-1)) n--;
if (boardopt0(x+1,y-1)) n--;
if (boardopt0(x-1,y+1)) n--;
if (boardopt0(x+0,y+1)) n--;
if (boardopt0(x+1,y+1)) n--;
if (n==a)
{
boardopt1(x-1,y+0,c);
boardopt1(x+1,y+0,c);
boardopt1(x-1,y-1,c);
boardopt1(x+0,y-1,c);
boardopt1(x+1,y-1,c);
boardopt1(x-1,y+1,c);
boardopt1(x+0,y+1,c);
boardopt1(x+1,y+1,c);
}
n=0; // add space
if (boardopt2(x-1,y+0)) n++;
if (boardopt2(x+1,y+0)) n++;
if (boardopt2(x-1,y-1)) n++;
if (boardopt2(x+0,y-1)) n++;
if (boardopt2(x+1,y-1)) n++;
if (boardopt2(x-1,y+1)) n++;
if (boardopt2(x+0,y+1)) n++;
if (boardopt2(x+1,y+1)) n++;
if (n==a)
{
boardopt3(x-1,y+0,c);
boardopt3(x+1,y+0,c);
boardopt3(x-1,y-1,c);
boardopt3(x+0,y-1,c);
boardopt3(x+1,y-1,c);
boardopt3(x-1,y+1,c);
boardopt3(x+0,y+1,c);
boardopt3(x+1,y+1,c);
}
}
}
} while (c);
}
//===========================================================================
//=== Main: =================================================================
//===========================================================================
void main()
{
byte a,b;
pit=(word far*)0x0000046C;
initscr();
mouseint();
boardint();
xtime0=pit[0];
flags=minesn;
do {
boardprn(); //render screen
if ((mousel)&&(mousey/10==0))
if ((mousex/10==15)||(mousex/10==16))
boardend();
if ((!mouser0)&&(mouser)&&(mousebx!=255)&&(mouseby!=255))
{
a=board[mousebx][mouseby]; b=a;
if (a==10)
{
b=cfree;
flags++;
}
if ((a==cfree)&&(flags!=0))
{
b=10;
flags--;
}
board[mousebx][mouseby]=b;
}
if ((!mousel0)&&(mousel)&&(mousebx!=255)&&(mouseby!=255))
if (board[mousebx][mouseby]==cfree)
{
a=mines[mousebx][mouseby];
if (a==0) boardtst(mousebx,mouseby);
if (a==1) boardend();
}
if (mousel+mouser) boardopt();
if (!flags) boardwin();
mousetst();
rfsscr(); // swap buffers to avoid flickering
}
while (!((mousel)&&(mousex/10==31)&&(mousey/10==0)));
asm {
mov ax,0x0003
int 0x10
}
}
//===========================================================================
//=== End: ==================================================================
//===========================================================================
Sorry it is not much commented. Left mouse button sweeps and right mouse button add flag (expecting bomb). If you need help understanding the VGA gfx part then see:
- Display an array of color in C
If you look at the main
then you see I got one "infinite" loop redrawing the screen and handling mouse events + game logic. I expect you should have something similar. The difference is that my objects are in grid so the selection is done just by scaling/offsetting mouse position.
In your case you should have list of objects and should loop through them and find the one closest to mouse and not too far ... similarly like in the Drag&Drop example link at the top of Answer.
Also here another related QA:
- understanding the minesweeper programming p.roblem