Puzzle slide

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Puzzle slide

Message par Micoute »

Avec PB, il y a plus d'un chemin qui mène à la bonne réponse.
Microsoft Windows 10 Famille 64 bits : Carte mère : ASRock 970 Extreme3 R2.0 : Carte Graphique NVIDIA GeForce RTX 3080 : Processeur AMD FX 6300 6 cœurs 12 threads 3,50 GHz PB 5.73 PB 6.00 LTS (x64)
Un homme doit être poli, mais il doit aussi être libre !
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide

Message par SPH »

J'ai chronométré les 3 routines : toutes les 3 ont le meme temps d'execution
Quand à la taille de l'exe, crisot et moi faisont -1% par rapport a l'exe de venom

Donc, c'est pareil mais je prefere quand meme les codes optimisés. C'est le confort de se relire qui compte (je trouve mon code logique alors que j'ai du mal a lire le code de crisot; pourtant plus optimisé) :idea:
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Puzzle slide

Message par venom »

Micoute a écrit :Avec PB, il y a plus d'un chemin qui mène à la bonne réponse.
C'est ça qui est cool.

@sph
Chacun a sa façon de coder. Même si je pense qu'en école de prog il doit y avoir des choses a respecter pour que tout le monde comprennent :wink:








@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Puzzle slide

Message par crisot »

Et pourtant si on compare les parties que j'ai remplacé dans ton code (dont je me sert de base)

J'ai remplacé ta routine servant à déterminer xx et yy:
ça:

Code : Tout sélectionner

 
  If x+y<>0
    xx=-1
    yy=0
    For i=0 To 8
      xx+1
      If xx=3
        xx=0
        yy+1
      EndIf
      If brique(i)=0
        Break
      EndIf
    Next
Par ça:

Code : Tout sélectionner

      For i=0 To 8
        If brique(i)=8
          x=i%3 : y=i/3
        EndIf
      Next 
***

J'ai remplacé la routine qui swap les briques en fonction des impulsions clavier:
ça:

Code : Tout sélectionner

    If x=1 And xx>0
      Swap brique(xx-1+yy*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
   
    If x=-1 And xx<2
      Swap brique(xx+1+yy*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
   
    If y=1 And yy>0
      Swap brique(xx+(yy-1)*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
   
    If y=-1 And yy<2
      Swap brique(xx+(yy+1)*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
par ça:

Code : Tout sélectionner

    If x!ox Or y!oy
      Swap brique(x+y*3), brique(ox+oy*3)
      PlaySound(0, 0, 100) ; joue le son slide
    EndIf
***

J'ai remplacé la routine qui vérifie le puzzle:
ça:

Code : Tout sélectionner

    For nb=1 To 8
      If brique(nb-1)<>nb
        nb=-1
        Break
      EndIf
    Next
   
    If nb=9
      run=2
    EndIf
par ça:

Code : Tout sélectionner

    run=2
    For nb=0 To 8
      If brique(nb)!nb
        run=1
      EndIf
    Next
***

J'ai remplacé la routine qui affiche les 9 briques du jeu:
ça:

Code : Tout sélectionner

  nb=0
  For u=0 To 2
    For i=0 To 2
      DisplayTransparentSprite(brique(nb), i*128, u*128) : nb+1
    Next
  Next
par ça:

Code : Tout sélectionner

  For i=0 To 8
    DisplayTransparentSprite(brique(i), (i%3)*128, (i/3)*128)
  Next
Et je trouve que prises individuellement, toutes ces routines sont plus courtes, plus propres, et plus compréhensibles (surtout les 2 premières) :)
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Puzzle slide

Message par crisot »

Maintenant oui il existe plein de manières de coder, toutes sont en fonction de nos connaissances, nos envies, nos besoin d'optimisations.

Techniquement je pense que le code de SPH est plus rapide que le mien, mais de manière non mesurable vu qu'on parle d'un truc qui prend 0.000000000000000000001% des perfs d'une calcultrice. Donc on s'en fout.
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide

Message par SPH »

venom a écrit :@sph
Chacun a sa façon de coder. Même si je pense qu'en école de prog il doit y avoir des choses a respecter pour que tout le monde comprennent :wink:
Totalement d'accord 8)

@crisot : les chronos sont sensiblement les mêmes (tout en sachant qu'en executant la même routine plusieurs fois, on retrouve un resultat different a chaque fois genre : 22510 ms, 22535 ms, 22498 ms)
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide

Message par SPH »

Très intéressant :
https://www.youtube.com/watch?v=-3IsCOJ ... %ABlLaunay

1 2 3 4 5 6 8 7 est impossible a résoudre... 8)
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Puzzle slide

Message par venom »

Merci sph, je regarderai ça. :wink:






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
crisot
Messages : 98
Inscription : lun. 30/août/2004 21:03

Re: Puzzle slide

Message par crisot »

SPH a écrit :Très intéressant :
https://www.youtube.com/watch?v=-3IsCOJ ... %ABlLaunay

1 2 3 4 5 6 8 7 est impossible a résoudre... 8)
C'est car le puzzle est mélangé n'importe comment en début de partie (n'importe quelle case vers n'importe quelle case), et il est possible que parfois on ne puisse pas le remettre en ordre avec les mouvements normaux du curseur.

Pour résoudre ça et avoir un puzzle toujours soluble, il suffirait de faire un algo qui partirait du curseur et le déplacerait de manière complètement aléatoire comme un joueur peut faire (toujours déplacer le curseur vers haut/bas/droite/gauche, à partir d'un plateau de jeu fini 12345678[]). Surtout pas déplacer le curseur en diagonale, surtout pas inverser deux autre cases. Toujours le curseur et un voisin.
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide

Message par SPH »

J'aurais une autre methode... :idea:
Allez, ouvrez les hostilités en proposant une routine.
Je coderais la mienne apres la votre... 8)
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Avatar de l’utilisateur
venom
Messages : 3072
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Puzzle slide

Message par venom »

crisot a écrit : C'est car le puzzle est mélangé n'importe comment en début de partie (n'importe quelle case vers n'importe quelle case), et il est possible que parfois on ne puisse pas le remettre en ordre avec les mouvements normaux du curseur.
Exact. C'est comme si tu démonte un Rubik's Cube et le remonte de façon aléatoire. Il ne sera sans doute plus solvable :lol:
sph a écrit : J'aurais une autre methode... :idea:
Allez, ouvrez les hostilités en proposant une routine.
Je coderais la mienne apres la votre...
J'avoue que c'était pas prévu a mon planning... :(






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide

Message par SPH »

venom a écrit :
sph a écrit : J'aurais une autre methode... :idea:
Allez, ouvrez les hostilités en proposant une routine.
Je coderais la mienne apres la votre...
J'avoue que c'était pas prévu a mon planning... :(
Je parlais a crisot en particulier :mrgreen: 8)
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Demivec
Messages : 90
Inscription : sam. 18/sept./2010 18:13

Re: Puzzle slide

Message par Demivec »

Rendre le puzzle toujours résoluble:

Code : Tout sélectionner

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Code : Crisot
;   Graphisme : venom
;   But de ce code : reduire encore le code de SPH :)
;   Code : Demivec
;   But de ce code: rendre le puzzle toujours résoluble.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

Procedure Panic()
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire pour ouvrir ce jeu !", 0)
  End
EndProcedure

Global TAILLE_BLOC = 128
Global LARGEUR_FENETRE = TAILLE_BLOC*3, HAUTEUR_FENETRE = TAILLE_BLOC*3
Global CheminImages$ = "GFX\", CheminSons$ = "SFX\"

; Dépendances
If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0 : Panic() : EndIf
UsePNGImageDecoder()
UseOGGSoundDecoder()

; Ouverture de la fenetre principale
If Not OpenWindow(0, 0, 0, LARGEUR_FENETRE, HAUTEUR_FENETRE, "Puzzle Slide", #PB_Window_TitleBar | #PB_Window_ScreenCentered) : Panic() : EndIf
If Not OpenWindowedScreen(WindowID(0), 0, 0, LARGEUR_FENETRE, HAUTEUR_FENETRE) : Panic() : EndIf

; Chargement des sprites : Attention sprite 8 = curseur []
For i=0 To 7
  LoadSprite(i, CheminImages$+"\Tuiles\Tuile"+Str(i+1)+".png", #PB_Sprite_AlphaBlending)
Next
LoadSprite(8, CheminImages$+"\Tuiles\Curseur.png", #PB_Sprite_AlphaBlending)

; Chargement des boutons menu
LoadSprite(10, CheminImages$+"\Menu\Button_New_Game.png", #PB_Sprite_AlphaBlending)
LoadSprite(11, CheminImages$+"\Menu\Button_Quitter.png", #PB_Sprite_AlphaBlending)
LoadSprite(12, CheminImages$+"\Menu\Button_Win.png", #PB_Sprite_AlphaBlending)

; chargement des sons
LoadSound(0, CheminSons$+"slide.ogg", 0)

; Plateau de jeu vide 12345678[]
Dim brique(8)
For i=0 To 8
  brique(i)=i
Next

;;;;;; Boucle principale ;;;;;;
Repeat
  ExamineKeyboard()
  ExamineMouse()
  ClearScreen(RGB(0, 0, 0))
  
  ; Affichage du plateau de jeu
  For i=0 To 8
    DisplayTransparentSprite(brique(i), (i%3)*128, (i/3)*128)
  Next
  
  Select run
    Case 0 ;;; Menu ;;;
      DisplayTransparentSprite(10, LARGEUR_FENETRE/2-SpriteWidth(10)/2, 128-SpriteHeight(10)/2)
      DisplayTransparentSprite(11, LARGEUR_FENETRE/2-SpriteWidth(11)/2, 256-SpriteHeight(11)/2)
      
      If KeyboardReleased(#PB_Key_Space)
        isSolvable = #False
        Repeat
          For i=0 To 8
            Swap brique(i),brique(Random(8))
          Next
          
          tile$ = ""
          For i = 0 To 8
            tile$ + Str(brique(i) + 1)
          Next
          tile$ = ReplaceString(tile$, "9", "")
          
          cycleCount = 0
          While Trim(tile$) <> ""
            startCycleElement = Val(Left(LTrim(tile$),1))
            Repeat
              nextCycleElement = Val(Mid(tile$, startCycleElement, 1))
              ReplaceString(tile$, Str(startCycleElement), " ", #PB_String_InPlace)
              If nextCycleElement
                startCycleElement = nextCycleElement
              Else
                cycleCount + 1
                Break
              EndIf
            ForEver
          Wend
          
          If (8 - cycleCount) % 2 = 0
            isSolvable = #True
          EndIf
        Until isSolvable
        
        For i=0 To 8
          If brique(i)=8
            x=i%3 : y=i/3 ; On trouve le x,y de la brique vide
          EndIf
        Next 
        run=1
      EndIf
      
    Case 1 ;;; Jeu ;;;
      ox = x : oy = y
      If KeyboardReleased(#PB_Key_Up) And y>0 : y-1
      ElseIf KeyboardReleased(#PB_Key_Down) And y<2 : y+1
      ElseIf KeyboardReleased(#PB_Key_Left) And x>0 : x-1
      ElseIf KeyboardReleased(#PB_Key_Right) And x<2 : x+1
      EndIf
      
      If x!ox Or y!oy
        Swap brique(x+y*3), brique(ox+oy*3)
        PlaySound(0, 0, 100) ; joue le son slide
      EndIf
      
      ; Vérification du puzzle
      run=2
      For nb=0 To 8
        If brique(nb)!nb
          run=1
        EndIf
      Next
      
    Case 2 ;;; Fin ;;;
      DisplayTransparentSprite(12, LARGEUR_FENETRE/2-SpriteWidth(12)/2, HAUTEUR_FENETRE/2-SpriteHeight(1)/2)
      run = 0
  EndSelect
  
  FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape)
Avatar de l’utilisateur
SPH
Messages : 4722
Inscription : mer. 09/nov./2005 9:53

Re: Puzzle slide finissable

Message par SPH »

Ma routine pour éviter tous les jeux non finissables :wink: :

Code : Tout sélectionner

Procedure build()
  Dim brique(8)
  Repeat
    For i=1 To 8
      brique(i)=i
    Next
    For i=1 To 8
      Swap brique(i),brique(Random(7)+1)
    Next
    x=0
    For i=1 To 8
      For u=i+1 To 8
        If brique(i)>brique(u)
          x+1
        EndIf
      Next
    Next
  Until x%2=0
EndProcedure
Le code complet du jeu :

Code : Tout sélectionner

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;   Code : SPH
;   Graphisme : venom
;   But de ce code : coder un jeu finissable =)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


If InitSprite() = 0 Or InitKeyboard() = 0 Or InitMouse() = 0 Or InitSound() = 0
  MessageRequester("Erreur", "Impossible d'ouvrir l'écran & l'environnement nécessaire pour ouvrir ce jeu !", 0)
  End
EndIf

Enumeration
  #Curseur
  #Slide
  #Button_New_Game=20
  #Button_Quitter=21
  #Button_Win=22
EndEnumeration

; Activations des supports
UsePNGImageDecoder()
UseOGGSoundDecoder()

Global TAILLE_BLOC = 128
Global LARGEUR_FENETRE = TAILLE_BLOC*3, HAUTEUR_FENETRE = TAILLE_BLOC*3
Global CheminImages$ = "GFX\", CheminSons$ = "SFX\"
Global Dim brique(8)

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Ouverture de la fenetre principale
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
If OpenWindow(0, 0, 0, LARGEUR_FENETRE, HAUTEUR_FENETRE, "Puzzle Slide", #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  If OpenWindowedScreen(WindowID(0), 0, 0, LARGEUR_FENETRE, HAUTEUR_FENETRE) ; Ouverture OpenWindowedScreen
  EndIf         
EndIf
;;;;
LoadSprite(0, CheminImages$+"\Tuiles\Curseur.png", #PB_Sprite_AlphaBlending)
For i=1 To 8
  LoadSprite(i, CheminImages$+"\Tuiles\Tuile"+Str(i)+".png", #PB_Sprite_AlphaBlending)
Next

LoadSprite(#Button_New_Game, CheminImages$+"\Menu\Button_New_Game.png", #PB_Sprite_AlphaBlending)
LoadSprite(#Button_Quitter, CheminImages$+"\Menu\Button_Quitter.png", #PB_Sprite_AlphaBlending)
LoadSprite(#Button_Win, CheminImages$+"\Menu\Button_Win.png", #PB_Sprite_AlphaBlending)

; chargement des sons
LoadSound(#Slide, CheminSons$+"slide.ogg", 0)

;;;;;;;;;;;;;;;;;
Procedure build()
  Dim brique(8)
  Repeat
    For i=1 To 8
      brique(i)=i
    Next
    For i=1 To 8
      Swap brique(i),brique(Random(7)+1)
    Next
    x=0
    For i=1 To 8
      For u=i+1 To 8
        If brique(i)>brique(u)
          x+1
        EndIf
      Next
    Next
  Until x%2=0
EndProcedure

build()
run = 0

; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Boucle
; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Repeat
  Repeat
    Event_Window = WindowEvent()
    Select Event_Window
      Case #PB_Event_CloseWindow
        End
    EndSelect
  Until Event_Window = 0
  
  ExamineKeyboard()
  ExamineMouse()
  ClearScreen(RGB(0, 0, 0))
  
  
  ;;;;;;; Keyboard
  If KeyboardReleased(#PB_Key_Space)
    build()
    run=1
  EndIf
  ;;;
  
  x=0
  y=0
  If KeyboardReleased(#PB_Key_Up)
    y=1
  ElseIf KeyboardReleased(#PB_Key_Down)
    y=-1
  ElseIf KeyboardReleased(#PB_Key_Left)
    x=1
  ElseIf KeyboardReleased(#PB_Key_Right)
    x=-1
  EndIf
  ;;;
  
  If x+y<>0 And run=1
    xx=-1
    yy=0
    For i=0 To 8
      xx+1
      If xx=3
        xx=0
        yy+1
      EndIf
      If brique(i)=0
        Break
      EndIf
    Next
    
    ;;;;;   
    If x=1 And xx>0
      Swap brique(xx-1+yy*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
    
    If x=-1 And xx<2
      Swap brique(xx+1+yy*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
    
    If y=1 And yy>0
      Swap brique(xx+(yy-1)*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
    
    If y=-1 And yy<2
      Swap brique(xx+(yy+1)*3),brique(xx+yy*3)
      PlaySound(#Slide, 0, 100) ; joue le son slide
    EndIf
    
    ;;;;; verif si on a fini le puzzle
    For nb=1 To 8
      If brique(nb-1)<>nb
        nb=-1
        Break
      EndIf
    Next
    
    If nb=9
      run=2
    EndIf
    
  EndIf
  
  ;;;;;;; DisplayTransparentSprite()
  nb=0
  For u=0 To 2
    For i=0 To 2
      DisplayTransparentSprite(brique(nb), i*128, u*128) : nb+1
    Next
  Next
  If run=0
    DisplayTransparentSprite(#Button_New_Game, LARGEUR_FENETRE/2-SpriteWidth(#Button_New_Game)/2, 128-SpriteHeight(#Button_New_Game)/2)
    DisplayTransparentSprite(#Button_Quitter, LARGEUR_FENETRE/2-SpriteWidth(#Button_Quitter)/2, 256-SpriteHeight(#Button_Quitter)/2)
  EndIf
  If run=2
    DisplayTransparentSprite(#Button_Win, LARGEUR_FENETRE/2-SpriteWidth(#Button_Win)/2, HAUTEUR_FENETRE/2-SpriteHeight(#Button_Win)/2)
  EndIf
  
  
  FlipBuffers()
  
Until KeyboardReleased(#PB_Key_Escape)

End
@Demivec : on a la même méthode (je viens de te lire après avoir codé ma procedure...). Tu t'es basé sur la vidéo ?
http://HexaScrabble.com/
!i!i!i!i!i!i!i!i!i!
!i!i!i!i!i!i!
!i!i!i!
//// Informations ////
Intel Core i7 4770 64 bits - GTX 650 Ti
Version de PB : 6.00 - 64 bits
Demivec
Messages : 90
Inscription : sam. 18/sept./2010 18:13

Re: Puzzle slide finissable

Message par Demivec »

SPH a écrit : @Demivec : on a la même méthode (je viens de te lire après avoir codé ma procedure...). Tu t'es basé sur la vidéo ?
Johnson & Story (1879) https://www.jstor.org/stable/2369492?se ... b_contents
Répondre