 


Task

Implement the Fifteen Puzzle Game.



The   15-puzzle   is also known as:

   Fifteen Puzzle
   Gem Puzzle
   Boss Puzzle
   Game of Fifteen
   Mystic Square
   14-15 Puzzle
   and some others.


Related Tasks

   15 Puzzle Solver
   16 Puzzle Game


 
' 15-PUZZLE GAME
' ********************************
dim d(16)
dim ds$(16) ' Board pieces
dim sh(3)
 
call buildBoard introAndLevel()
call printPuzzle
do
  print "To move a piece, enter its number: "
  input x
  while isMoveValid(x, y, z) = 0
    print "Wrong move."
    call printPuzzle
    print "To move a piece, enter its number: "
    input x
  wend
  d(z) = x
  d(y) = 0
  call printPuzzle
loop until isPuzzleComplete()
print "YOU WON!"
end
 
sub printPuzzle
  for p = 1 to 16
    if d(p) = 0 then
      ds$(p) = "     "
    else
      ds$(p) = using("###", d(p)) + "  "
    end if
  next p
  print "+-----+-----+-----+-----+"
  print "|"; ds$(1); "|"; ds$(2); "|"; ds$(3); "|"; ds$(4); "|"
  print "+-----+-----+-----+-----+"
  print "|"; ds$(5); "|"; ds$(6); "|"; ds$(7); "|"; ds$(8); "|"
  print "+-----+-----+-----+-----+"
  print "|"; ds$(9); "|"; ds$(10); "|";ds$(11); "|"; ds$(12); "|"
  print "+-----+-----+-----+-----+"
  print "|"; ds$(13); "|"; ds$(14); "|"; ds$(15); "|"; ds$(16); "|"
  print "+-----+-----+-----+-----+"
end sub
 
function introAndLevel()
  cls
  sh(1) = 10
  sh(2) = 50
  sh(3) = 100
  print "15 PUZZLE GAME"
  print
  print
  print "Please enter level of difficulty,"
  do
    print "1 (easy), 2 (medium) or 3 (hard): ";
    input level
  loop while (level < 1) or (level > 3)
  introAndLevel = level
end function
 
sub buildBoard level
  ' Set pieces in correct order first
  for p = 1 to 15
    d(p) = p
  next p
  d(16) = 0 ' 0 = empty piece/slot
  z = 16 ' z = empty position
  print
  print "Shuffling pieces";
  for n = 1 to sh(level)
    print ".";
    do
      x = int(rnd(0) * 4) + 1
      select case x
        case 1
          r = z - 4
        case 2
          r = z + 4
        case 3
          if (z - 1) mod 4 <> 0 then
            r = z - 1
          end if
        case 4
          if z mod 4 <> 0 then
            r = z + 1
          end if
      end select
    loop while (r < 1) or (r > 16)
    d(z) = d(r)
    z = r
    d(z) = 0
  next n
  cls
end sub
 
function isMoveValid(piece, byref piecePos, byref emptyPos)
  mv = 0
  if (piece >= 1) and (piece <= 15) then
    piecePos = piecePosition(piece)
    emptyPos = piecePosition(0)
    ' Check if empty piece is above, below, left or right to piece
    if (piecePos - 4 = emptyPos) or _
      (piecePos + 4 = emptyPos) or _
      ((piecePos - 1 = emptyPos) and (emptyPos mod 4 <> 0)) or _
      ((piecePos + 1 = emptyPos) and (piecePos mod 4 <> 0)) then
      mv = 1
    end if
  end if
  isMoveValid = mv
end function
 
function piecePosition(piece)
  p = 1
  while d(p) <> piece
    p = p + 1
    if p > 16 then
      print "UH OH!"
      stop
    end if
  wend
  piecePosition = p
end function
 
function isPuzzleComplete()
  pc = 0
  p = 1
  while (p < 16) and (d(p) = p)
    p = p + 1
  wend
  if p = 16 then
    pc = 1
  end if
  isPuzzleComplete = pc
end function
 