OK, you have your picture which you say chop into 16 pieces in a 4x4 grid. Each piece is turned into a sprite numbered 1 to 16.
If you place them on the grid in their correct positions, it would look like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
So, you use Dim Grid(4,4) and the 1 would go into Grid(1,1), the 2 would go into Grid(2,1), the 3 into Grid(3,1) and so on.
But that's when the puzzle is completed.
What you would do is feed the 16 tile numbers into the array randomly using something like this:
Dim Grid(4,4)
Randomize Timer()
Numbers$=""
For N=1 To 16
Numbers$ = Numbers$+Chr$(N)
Next N
For GridY=1 To 4
For GridX=1 To 4
R = Rnd(Len(Numbers$)-1)+1
TileNum = ASC(Mid$(Numbers$,R))
Grid(GridX,GridY) = TileNum
Numbers$ = Left$(Numbers$,R-1)+Right$(Numbers$,Len(Numbers$)-R)
Next GridX
Next GridY
After this, the array contains all 16 tiles, so we now have to choose one to be the empty slot. The easiest way is to set the array slot which currently has tile number 16 in it:
For GridY=1 To 4
For GridX=1 To 4
If Grid(GridX,GridY) = 16
Grid(GridX,GridY) = 0
Exit
Endif
Next GridX
Next GridY
Next you use the contents of the array to create the sprites and place them on the puzzle:
PTLx = 100: Rem Puzzle Top Left X Position
PTLy = 100: Rem Puzzle Top Left Y Position
SpriteNum = 1
For GridY=0 To 3
For GridX=0 To 3
If Grid(GridX+1,GridY+1) <> 0
Sprite SpriteNum,GridX*32+PTLx,GridY*32+PTLy,Grid(GridX+1,GridY+1)
Set Sprite SpriteNum,1,1
Inc SpriteNum
Endif
Next GridX
Next GridY
In the game, we calculate the position on the grid that the mouse is over and get the sprite number when the mouse button is clicked.
We then Gosub CheckForGap which determines if there's a gap above, below, left or right of the tile clicked on. The variable OpenPosition is set to 0 if there's no gap or 1, 2, 3 or 4 if the gap is above, below, left or right.
The SwapPositions procedure moves the tile in the correct direction.
Here's all of it in a usable format, though I've left the CheckForWin procedure for you to do. I've put a few Text commands to make it a little easier to figure out what it's doing.
Rem Sliding Tile Puzzle Example By TDK_Man
Gosub Setup
Do
Mx=MouseX(): My=MouseY(): Mc=MouseClick()
Sprite 100,Mx,My,100
OverGridX = (Mx-PTLx)/32+1: OverGridY = (My-PTLy)/32+1
OverGrid = (OverGridY-1)*4+OverGridX
If OverGrid <= 16 And Mc = 1
Rem Must Have Clicked On A Tile (Number Of Actual Grid Position Is OverGrid)
SpriteNum = Sprite Collision(100,0)
Gosub CheckForGap
If OpenPosition <> 0
Rem OpenPosition: 1=Above, 2=Below, 3=Left & 4=Right 0=None
Gosub SwapPositions
Gosub CheckForWin
Else
Text 4,20,"No Gap To Swap Tiles... "
Endif
Endif
Sync
If OverGrid <= 16
Text 4,4,"Grid: X="+Str$(OverGridX)+" Y="+Str$(OverGridY)+" Contents: "+Str$(Grid(OverGridX,OverGridY))+" "
Endif
Loop
CheckForWin:
Rem Loop Through Array Here To See If It Contains 1, 2, 3, 4, etc Up To 15.
Rem If It Does, Then Paste Last Image (16) In Bottom Right Corner And Game Over!
Return
SwapPositions:
Select OpenPosition
Case 1
Rem Swap With Above
ImageNum = Grid(OverGridX,OverGridY)
For N=0 To 31
Sprite SpriteNum,Sprite X(SpriteNum),Sprite Y(SpriteNum)-1,ImageNum
Sync
Next N
Rem Now Update Grid Array
Grid(OverGridX,OverGridY) = 0: Rem Old Tile Position Now Empty
Grid(OverGridX,OverGridY-1) = ImageNum: Rem Tile's New Position
EndCase
Case 2
Rem Swap With Below
ImageNum = Grid(OverGridX,OverGridY)
For N=0 To 31
Sprite SpriteNum,Sprite X(SpriteNum),Sprite Y(SpriteNum)+1,ImageNum
Sync
Next N
Rem Now Update Grid Array
Grid(OverGridX,OverGridY) = 0: Rem Old Tile Position Now Empty
Grid(OverGridX,OverGridY+1) = ImageNum: Rem Tile's New Position
EndCase
Case 3
Rem Swap With Left
ImageNum = Grid(OverGridX,OverGridY)
For N=0 To 31
Sprite SpriteNum,Sprite X(SpriteNum)-1,Sprite Y(SpriteNum),ImageNum
Sync
Next N
Rem Now Update Grid Array
Grid(OverGridX,OverGridY) = 0: Rem Old Tile Position Now Empty
Grid(OverGridX-1,OverGridY) = ImageNum: Rem Tile's New Position
EndCase
Case 4
Rem Swap With Right
ImageNum = Grid(OverGridX,OverGridY)
For N=0 To 31
Sprite SpriteNum,Sprite X(SpriteNum)+1,Sprite Y(SpriteNum),ImageNum
Sync
Next N
Rem Now Update Grid Array
Grid(OverGridX,OverGridY) = 0: Rem Old Tile Position Now Empty
Grid(OverGridX+1,OverGridY) = ImageNum: Rem Tile's New Position
EndCase
EndSelect
Return
CheckForGap:
Rem OverGrid is grid number clicked on (1-16)
Rem OverGridX is grid column number clicked on (1-4)
Rem OverGridY is grid row number clicked on (1-4)
AboveY = OverGridY - 1
BelowY = OverGridY + 1
LeftX = OverGridX - 1
RightX = OverGridX + 1
OpenPosition = 0
If AboveY > 0 And AboveY < 5
Above = Grid(OverGridX,AboveY)
If Above = 0 Then Inc OpenPosition,1
Else
Above = -1
Endif
Text 4,320,"Above Contains: "+Str$(Above)+" "
If BelowY < 5
Below = Grid(OverGridX,BelowY)
If Below = 0 Then Inc OpenPosition,2
Else
Below = -1
Endif
Text 4,340,"Below Contains: "+Str$(Below)+" "
If LeftX > 0 And LeftX < 5
Left = Grid(LeftX,OverGridY)
If Left = 0 Then Inc OpenPosition,3
Else
Left = -1
Endif
Text 4,360,"Left Contains: "+Str$(Left)+" "
If RightX < 5
Right = Grid(RightX,OverGridY)
If Right = 0 Then Inc OpenPosition,4
Else
Right = -1
Endif
Text 4,380,"Right Contains: "+Str$(Right)+" "
Text 4,400,"OpenPosition Contains: "+Str$(OpenPosition)+" "
Rem If OpenPosition = 0 Here Then No Empty Adjacent Space
Rem If Not Zero then 1=Above, 2=Below, 3=Left & 4=Right
Return
Setup:
Set Display Mode 800,600,32
Sync On: Sync Rate 60
Dim Grid(4,4)
Randomize Timer()
Set Text Opaque
Rem Create Hidden Bitmap
Create Bitmap 1,320,200
Rem Grab A Tiny Image To Use As A Hidden Collision Sprite
CLS 5000
Get Image 100,0,0,2,2
Sprite 100,-100,-100,100
Hide Sprite 100
Rem Load The Image & Place On Hidden Screen
CLS 0
Load Image "Puzzle1.bmp",1
Paste Image 1,0,0
Rem Grab The Tiles As Images 1 To 16
ImageNum = 1
For GridY=0 To 3
For GridX=0 To 3
Get Image ImageNum,GridX*32,GridY*32,GridX*32+32,GridY*32+32
Inc ImageNum
Next GridX
Next GridY
Rem Switch Back To Main Screen And Delete Hidden Bitmap
Set Current Bitmap 0
Delete Bitmap 1
Rem Create A String For Random Tile Values
Numbers$=""
For N=1 To 16
Numbers$ = Numbers$+Chr$(N)
Next N
Rem Feed Random Tile Numbers Into Array
For GridY=1 To 4
For GridX=1 To 4
R = Rnd(Len(Numbers$)-1)+1
TileNum = ASC(Mid$(Numbers$,R))
Grid(GridX,GridY) = TileNum
Numbers$ = Left$(Numbers$,R-1)+Right$(Numbers$,Len(Numbers$)-R)
Next GridX
Next GridY
Rem Find Time Number 16 And Set To Zero For Blank
For GridY=1 To 4
For GridX=1 To 4
If Grid(GridX,GridY) = 16
Grid(GridX,GridY) = 0
Exit
Endif
Next GridX
Next GridY
Rem Now Use The Grid Array To Build The Puzzle
PTLx = 100: Rem Puzzle Top Left X Position
PTLy = 100: Rem Puzzle Top Left Y Position
SpriteNum = 1
For GridY=0 To 3
For GridX=0 To 3
If Grid(GridX+1,GridY+1) <> 0
Sprite SpriteNum,GridX*32+PTLx,GridY*32+PTLy,Grid(GridX+1,GridY+1)
Set Sprite SpriteNum,1,1
Inc SpriteNum
Endif
Next GridX
Next GridY
Return
The image I used is also attached below.
TDK_Man