Number Slider Game Code

Advanced game related topics
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Number Slider Game Code

Post by Rook Zimbabwe »

Since Stargate helped me remember SWAP() ((I am SUCH an idiot!)) I finished this in about 12 minutes...

Making nicer version for me.

Code: Select all

; nUMB3Rz Game
; (c) 2009 by Ralph Dunn - Blue Mesa Software
; Thanks to STARGATE for asisting me in remembering SWAP
; I feel like SUCH an idiot!!!

Enumeration
  #Window_SCR
EndEnumeration

Enumeration
  #Image_0
  #Image_1
  #Image_2
  #Image_3
  #Image_4
  #Image_5
  #Image_6
  #Image_7
  #Image_8
  #Frame3D_0
  #Button_SCRAMBLE
EndEnumeration

Structure VisualDesignerGadgets
  Gadget.l
  EventFunction.l
EndStructure

Global NewList EventProcedures.VisualDesignerGadgets()

UseJPEGImageDecoder()

Global Dim POPIT(8) ; base array to hold tiles?
Global Dim IDimage(8)
Global Image1, Image2, Image2, Image3, Image4
Global Image5, Image6, Image7, Image8, Image0


Image0= CatchImage(#PB_Any, ?Image0)
Image8= CatchImage(#PB_Any, ?Image8)
Image7= CatchImage(#PB_Any, ?Image7)
Image6= CatchImage(#PB_Any, ?Image6)
Image5= CatchImage(#PB_Any, ?Image5)
Image4= CatchImage(#PB_Any, ?Image4)
Image3= CatchImage(#PB_Any, ?Image3)
Image2= CatchImage(#PB_Any, ?Image2)
Image1= CatchImage(#PB_Any, ?Image1)

DataSection
Image8:
  IncludeBinary "Image8.jpg"
Image7:
  IncludeBinary "Image7.jpg"
Image6:
  IncludeBinary "Image6.jpg"
Image5:
  IncludeBinary "Image5.jpg"
Image4:
  IncludeBinary "Image4.jpg"
Image3:
  IncludeBinary "Image3.jpg"
Image2:
  IncludeBinary "Image2.jpg"
Image1:
  IncludeBinary "Image1.jpg"
Image0:
  IncludeBinary "ImageX.jpg"
EndDataSection

;-

POPIT(0) = 1
POPIT(1) = 2
POPIT(2) = 3
POPIT(3) = 4
POPIT(4) = 5
POPIT(5) = 6
POPIT(6) = 7
POPIT(7) = 8
POPIT(8) = 0

IDimage(0) = Image0 ; these are the image ID generated by system at program runtime
IDimage(1) = Image1 ; I could probably assign them to the same numbers
IDimage(2) = Image2 ; but I am too lazy -- AND I wanted to make sure I could store this info
IDimage(3) = Image3
IDimage(4) = Image4
IDimage(5) = Image5
IDimage(6) = Image6
IDimage(7) = Image7
IDimage(8) = Image8

;-

Procedure CheckWinner()
  ; run through the array and add a point if numbertile is where it is supposed to be
  For DAISY = 0 To 8
    If POPIT(Daisy) = Daisy
      score = score + 1
    EndIf
  Next
  
  If score = 9
    End
  EndIf

EndProcedure

Procedure Drawboard()
; just like MAKEBOARD() but it only reads the $$ and draws the ID from the ID array
For goofy = #Image_0 To #Image_8
  what = POPIT(goofy)
  IDis = IDimage(what)
   SetGadgetState(goofy, ImageID(IDis))
Next

EndProcedure

Procedure MakeBoard()

For n = 0 To 8
  POPIT(n) = n
Next

For i = 0 To 8
  Swap POPIT(i), POPIT(Random(8)) ; Thank you StarGate and Trond!
Next

For goofy = #Image_0 To #Image_8
  what = POPIT(goofy)
  IDis = IDimage(what)
   SetGadgetState(goofy, ImageID(IDis))
Next

EndProcedure

Procedure CheckLegal(IDIT)
; this is where I see if the BLANK square is up down L or R tothe piece clicked on
; just check logivcal directions...
; I think I can optimize this!
Select IDIT
  Case #Image_0
  ; 8 and 6
  slipit = POPIT(0)
  Debug "Slipit = "+Str(slipit)
  If POPIT(6) = 0
    Swap POPIT(6) , POPIT(0)
  ElseIf POPIT(8) = 0
    Swap POPIT(8) , POPIT(0)  
  EndIf
  Case #Image_1
  ; 2 and 4
  slipit = POPIT(1)
  Debug "Slipit = "+Str(slipit)
  If POPIT(2) = 0
    Swap POPIT(2) , POPIT(1)
  ElseIf POPIT(4) = 0
    Swap POPIT(4) , POPIT(1)  
  EndIf
  Case #Image_2
  ; 1 and 3 and 5
  If POPIT(1) = 0
    Swap POPIT(1) , POPIT(2)
  ElseIf POPIT(3) = 0
    Swap POPIT(3) , POPIT(2) 
  ElseIf POPIT(5) = 0
    Swap POPIT(5) , POPIT(2)  
  EndIf
  Case #Image_3
  ; 2 and 6
  slipit = POPIT(3)
  Debug "Slipit = "+Str(slipit)
  If POPIT(2) = 0
    Swap POPIT(2) , POPIT(3)
  ElseIf POPIT(6) = 0
    Swap POPIT(6) , POPIT(3)  
  EndIf
  Case #Image_4
  ; 1 and 7 and 5
  If POPIT(1) = 0
    Swap POPIT(1) , POPIT(4)
  ElseIf POPIT(7) = 0
    Swap POPIT(7) , POPIT(4) 
  ElseIf POPIT(5) = 0
    Swap POPIT(5) , POPIT(4)  
  EndIf
  Case #Image_5
  ; 2 and 8 and 4 and 6
  slipit = POPIT(5)
  Debug "Slipit = "+Str(slipit)
  If POPIT(2) = 0
    Swap POPIT(2) , POPIT(5)
  ElseIf POPIT(8) = 0
    Swap POPIT(8) , POPIT(5) 
  ElseIf POPIT(4) = 0
    Swap POPIT(4) , POPIT(5)
  ElseIf POPIT(6) = 0
    Swap POPIT(6) , POPIT(5)   
  EndIf
  Case #Image_6
  ; 3 and 5 and 9
  If POPIT(3) = 0
    Swap POPIT(3) , POPIT(6)
  ElseIf POPIT(5) = 0
    Swap POPIT(5) , POPIT(6) 
  ElseIf POPIT(0) = 0
    Swap POPIT(0) , POPIT(6)  
  EndIf
  Case #Image_7
  ; 4 and 8
  slipit = POPIT(7)
  Debug "Slipit = "+Str(slipit)
  If POPIT(4) = 0
    Swap POPIT(4) , POPIT(7)
  ElseIf POPIT(8) = 0
    Swap POPIT(8) , POPIT(7)  
  EndIf
  Case #Image_8
  ; 5 and 7 and 0
  If POPIT(5) = 0
    Swap POPIT(5) , POPIT(8)
  ElseIf POPIT(7) = 0
    Swap POPIT(7) , POPIT(8) 
  ElseIf POPIT(0) = 0
    Swap POPIT(0) , POPIT(8)  
  EndIf
EndSelect

Drawboard()

CheckWinner()

EndProcedure

;-

Procedure Button_SCRAMBLE_Event(Window, Event, Gadget, Type)
  MakeBoard()
EndProcedure

;-

Procedure Image_NULL_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_0)
EndProcedure

Procedure Image_1_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_1)
EndProcedure

Procedure Image_2_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_2)
EndProcedure

Procedure Image_3_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_3)
EndProcedure

Procedure Image_4_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_4)
EndProcedure

Procedure Image_5_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_5)
EndProcedure

Procedure Image_6_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_6)
EndProcedure

Procedure Image_7_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_7)
EndProcedure

Procedure Image_8_Event(Window, Event, Gadget, Type)
  CheckLegal(#Image_8)
EndProcedure

;-

Procedure RegisterGadgetEvent(Gadget, *Function)
  
  If IsGadget(Gadget)
    AddElement(EventProcedures())
    EventProcedures()\Gadget        = Gadget
    EventProcedures()\EventFunction = *Function
  EndIf
  
EndProcedure

Procedure CallEventFunction(Window, Event, Gadget, Type)
  
  ForEach EventProcedures()
    If EventProcedures()\Gadget = Gadget
      CallFunctionFast(EventProcedures()\EventFunction, Window, Event, Gadget, Type)
      LastElement(EventProcedures())
    EndIf
  Next
  
EndProcedure

;-

Procedure Open_Window_SCR()
  
  If OpenWindow(#Window_SCR, 116, 33, 172, 200, "nUMb3Rz 1.0",  #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered )
    ;If CreateGadgetList(WindowID(#Window_SCR))
      
      ImageGadget(#Image_8, 65, 100, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_8, @Image_8_Event())
      ImageGadget(#Image_7, 25, 100, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_7, @Image_7_Event())
      ImageGadget(#Image_6, 105, 60, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_6, @Image_6_Event())
      ImageGadget(#Image_5, 65, 60, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_5, @Image_5_Event())
      ImageGadget(#Image_4, 25, 60, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_4, @Image_4_Event())
      ImageGadget(#Image_3, 105, 20, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_3, @Image_3_Event())
      ImageGadget(#Image_2, 65, 20, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_2, @Image_2_Event())
      ImageGadget(#Image_1, 25, 20, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_1, @Image_1_Event())
      ImageGadget(#Image_0, 105, 100, 40, 40, ImageID(Image0))
      RegisterGadgetEvent(#Image_0, @Image_NULL_Event())
      
      ButtonGadget(#Button_SCRAMBLE, 20, 150, 130, 35, "SCRAMBLE")
      RegisterGadgetEvent(#Button_SCRAMBLE, @Button_SCRAMBLE_Event())
      
      Frame3DGadget(#Frame3D_0, 20, 10, 130, 135, "")
      
    ;EndIf
  EndIf
EndProcedure

Open_Window_SCR()

MakeBoard()

Repeat
  
  Event  = WaitWindowEvent()
  Gadget = EventGadget()
  Type   = EventType()
  Window = EventWindow()
  
  Select Event
    Case #PB_Event_Gadget
      CallEventFunction(Window, Event, Gadget, Type)
      
  EndSelect
  
Until Event = #PB_Event_CloseWindow

End

It could be easily adapted for the picture slider game I saw here...

No, I will not post graphics... make your own. You need a square and a number 1-8 in each and a blank square for ImageX... Then go to town! :mrgreen:
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
akj
Enthusiast
Enthusiast
Posts: 668
Joined: Mon Jun 09, 2003 10:08 pm
Location: Nottingham

Re: Number Slider Game Code

Post by akj »

Unfortunately the scrambling routine can often result in an invalid (insoluble) arrangement. The code below corrects this and approximately halves the length of the program.

Code: Select all

; nUMB3Rz Game
; (c) 2009 by Ralph Dunn - Blue Mesa Software
; Thanks to STARGATE for asisting me in remembering SWAP
; I feel like SUCH an idiot!!!
; Modified by AKJ

EnableExplicit

Enumeration
  #Image_0 = 0 ; Nine image gadgets
  #Window_SCR = 9
  #Frame3D_0
  #Button_SCRAMBLE
EndEnumeration

Structure VisualDesignerGadgets
  Gadget.l
  EventFunction.l
EndStructure

Global NewList EventProcedures.VisualDesignerGadgets()
Global Dim POPIT(8) ; Base array to hold tiles
Global Dim IDimage(8) ; Image IDs.  The PB image numbers are 0..8
Global Dim Move$(8) ; Table of legal moves

Procedure CreateImages(w, h)
Protected i, text.s
For i = 0 To 8
  IDimage(i) = CreateImage(i, w, h)
  StartDrawing(ImageOutput(i))
  DrawingMode(#PB_2DDrawing_Transparent)
  Box(0, 0, w, h, #Gray)
  If i: text = Str(i): Else: text="": EndIf
  DrawText(w/2-TextWidth(text)/2, h/2-TextHeight(text)/2, text, #Red)
  StopDrawing()
Next i
EndProcedure

Procedure CheckWinner()
  ; Run through the array and add a point if numbertile is where it is supposed to be
  Protected score=0, DAISY
  For DAISY = 0 To 8
    If POPIT(Daisy) = Daisy
      score = score + 1
    EndIf
  Next
  If score = 9
    MessageRequester("Win", "You Win!")
  EndIf
EndProcedure

Procedure Drawboard()
Protected goofy, what
For goofy = #Image_0 To #Image_0+8
  what = POPIT(goofy)
  SetGadgetState(goofy, IDimage(what))
Next
EndProcedure

Procedure MakeBoard()
Protected n, oldempty, empty, cell
For n = 0 To 8
  POPIT(n) = n
Next
empty = 0 ; Position of the empty cell
oldempty = 0 ; Position of the previously empty cell
For n = 1 To 25+Random(5) ; The random parameter should be an odd number
  Repeat
    cell = Val(Mid(Move$(empty), Random(Len(Move$(empty))-1)+1, 1)) ; Valid swappable cell
  Until cell<>oldempty ;  Avoid undoing the previous swap
  Swap POPIT(empty), POPIT(cell) ; Thank you StarGate and Trond!
  oldempty = empty
  empty = cell
Next n
Drawboard()
EndProcedure

Procedure CheckLegal(IDIT)
; This where I see if the BLANK square is up down L or R to the piece clicked on
; Just check logical directions ...
Protected cell, p, c
cell = IDIT-#Image_0 ; Cell clicked
For p = 1 To Len(Move$(cell))
  c = Val(Mid(Move$(cell), p, 1)) ; Cell to try swapping with clicked cell
  If POPIT(c)=0
    Swap POPIT(c), POPIT(cell)
    Drawboard()
    CheckWinner()
    ProcedureReturn
  EndIf
Next p
EndProcedure

Procedure Button_SCRAMBLE_Event(Window, Event, Gadget, Type)
  MakeBoard()
EndProcedure

Procedure Image_Event(Window, Event, Gadget, Type)
  CheckLegal(gadget)
EndProcedure

Procedure RegisterGadgetEvent(Gadget, *Function)
  If IsGadget(Gadget)
    AddElement(EventProcedures())
    EventProcedures()\Gadget        = Gadget
    EventProcedures()\EventFunction = *Function
  EndIf
EndProcedure

Procedure CallEventFunction(Window, Event, Gadget, Type)
  ForEach EventProcedures()
    If EventProcedures()\Gadget = Gadget
      CallFunctionFast(EventProcedures()\EventFunction, Window, Event, Gadget, Type)
      LastElement(EventProcedures())
    EndIf
  Next
EndProcedure

Procedure Open_Window_SCR()
  Protected flags
  flags = #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered
  If OpenWindow(#Window_SCR, 116, 33, 172, 200, "nUMb3Rz 1.0", flags)
    ImageGadget(#Image_0+8, 65, 100, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+8, @Image_Event())
    ImageGadget(#Image_0+7, 25, 100, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+7, @Image_Event())
    ImageGadget(#Image_0+6, 105, 60, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+6, @Image_Event())
    ImageGadget(#Image_0+5, 65, 60, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+5, @Image_Event())
    ImageGadget(#Image_0+4, 25, 60, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+4, @Image_Event())
    ImageGadget(#Image_0+3, 105, 20, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+3, @Image_Event())
    ImageGadget(#Image_0+2, 65, 20, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+2, @Image_Event())
    ImageGadget(#Image_0+1, 25, 20, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+1, @Image_Event())
    ImageGadget(#Image_0+0, 105, 100, 40, 40, 0)
    RegisterGadgetEvent(#Image_0+0, @Image_Event())
    ButtonGadget(#Button_SCRAMBLE, 20, 150, 130, 35, "SCRAMBLE")
    RegisterGadgetEvent(#Button_SCRAMBLE, @Button_SCRAMBLE_Event())
    Frame3DGadget(#Frame3D_0, 20, 10, 130, 135, "")
  EndIf
EndProcedure

;-Main program
Define m, Event, Gadget, Type, Window
CreateImages(40, 40)
Open_Window_SCR()
; Build table of legal moves
For m = 0 To 8
  Move$(m) = StringField("86 24 135 26 175 2846 350 48 570", m+1, " ")
Next m
MakeBoard() ; Scramble
Repeat
  Event  = WaitWindowEvent()
  Gadget = EventGadget()
  Type   = EventType()
  Window = EventWindow()
  Select Event
  Case #PB_Event_Gadget
    CallEventFunction(Window, Event, Gadget, Type)
  EndSelect
Until Event = #PB_Event_CloseWindow
End
Anthony Jordan
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4322
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Re: Number Slider Game Code

Post by Rook Zimbabwe »

I love what you have done with the code... THANK YOU! :D

I do have a query concerning unsoluble arrangements... I really don't see how that could happen... because every piece could be anywhere on the board right? so there would be much harder to solve ones and easier ones?

Then again I am really only good at Tuatology and Statistics in math! 8)
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
User avatar
Demivec
Addict
Addict
Posts: 4282
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Number Slider Game Code

Post by Demivec »

Rook Zimbabwe wrote:I love what you have done with the code... THANK YOU! :D

I do have a query concerning unsoluble arrangements... I really don't see how that could happen... because every piece could be anywhere on the board right? so there would be much harder to solve ones and easier ones?

Then again I am really only good at Tuatology and Statistics in math! 8)
What you are saying is that "any board position be transformed into any other board position simply by sliding the tiles."

If that is true, start with either the tiles arrangement on the left or the right and try to make this other arrangement of tiles only by sliding (according to the puzzle rules):

Code: Select all

1 2 3     1 2 3
4 5 6     4 5 6
8 7       7 8
The fact that you can't means that you also wouldn't be able to solve a puzzle that started with the arrangement of tiles on the left. The only way to get this arrangement is by swapping tiles. Swapping tiles isn't possible in the puzzle because it only allows the sliding of tiles. Thus it becomes unsolvable in a case like this because you got into a situation differently than you are allowed to get out of it.
Post Reply