Le plus ou moins

Programmation avancée de jeux en PureBasic
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Le plus ou moins

Message par venom »

Bonjour,

Voici un petit "jeux", qui a la particularité d’être très facile a coder. Il s'agit simplement de retrouver un nombre (entier) aléatoire en un minimum de coups. Un classique très connu. Il y a 3 niveaux de difficulté.

Voici le code :

Code : Tout sélectionner

; ///////////////////////////////////////////////
; //      Autor :         Venom                //
; //      Project name :  Plus ou moins        //
; //      Version :       V 1.0                //
; //      Compilator :    PureBasic V5.70      //
; //      Date :          04/04/2019           //
; //      OS :            Windows 10           //
; ///////////////////////////////////////////////


;- Window Constants
Enumeration
  #Window_0
EndEnumeration

;- gadgets Constants
Enumeration
  #Fram_Fourchette
  #ComboBox_Fourchette
  
  #Fram_Button_Demarrer
  #Button_Demarrer
  
  #Fram_Valeur_Du_Joueur
  #String_Valeur_Du_Joueur
  #Button_Valeur_Du_Joueur
  
  #Fram_Affichage_Des_Resultats
  #ListIcon_Affichage_Des_Resultats
EndEnumeration



;- déclarations
Declare Notice()
Declare Fourchette()
Declare Button_Demarrer()
Declare Valeur_Du_Joueur()
Declare Affichage_Des_Resultats()
Declare Valeur_Trouver()
Declare Game()



;- on ouvre la fenetre
  If OpenWindow(#Window_0, 0, 0, 220, 600, "Plus ou moins ", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
   Notice()
   Fourchette()
   Button_Demarrer()
   Valeur_Du_Joueur()
   Affichage_Des_Resultats()
   
   ;- option pour valider avec la touche ENTREE
   AddKeyboardShortcut(#Window_0, #PB_Shortcut_Return, #Button_Valeur_Du_Joueur)
    BindEvent(#PB_Event_Menu,@Game(),#Window_0,#Button_Valeur_Du_Joueur)

  EndIf 
  
;- boucle infini
  Repeat
   EventID = WaitWindowEvent()
    If EventID = #PB_Event_Gadget
      Select EventGadget()
          
        Case #Button_Demarrer
         DisableGadget(#ComboBox_Fourchette, #True) ; desactive le gadget
         DisableGadget(#Button_Demarrer, #True) ; desactive le gadget
         DisableGadget(#String_Valeur_Du_Joueur, #False) ; active le gadget
         DisableGadget(#Button_Valeur_Du_Joueur, #False) ; active le gadget
         
         ;- on regarde la difficulter choisi et on fait un random en fonction
          If GetGadgetState(#ComboBox_Fourchette) = 0
           Global Valeur_A_Trouver = Random(100, 1) ; random entre 1 et 100 
          ElseIf GetGadgetState(#ComboBox_Fourchette)  = 1
           Global Valeur_A_Trouver = Random(1000, 1) ; random entre 1 et 1000 
          ElseIf GetGadgetState(#ComboBox_Fourchette)  = 2
           Global Valeur_A_Trouver = Random(10000, 1) ; random entre 1 et 1000  
          ElseIf GetGadgetState(#ComboBox_Fourchette)  = 3
           Global Valeur_A_Trouver = Random(100000, 1) ; random entre 1 et 1000  
          EndIf 
          ;Debug Valeur_A_Trouver; debug le resultat a trouver

        Case #Button_Valeur_Du_Joueur
         Game() ; on lance la partie

      EndSelect
    EndIf
  Until EventID = #PB_Event_CloseWindow
  
  
  
  
  
Procedure Notice()
MessageRequester("Règles du jeux", "Vous devez retrouvez un nombre aléatoire en un minimum de coups. Bonne chance.", 0)
EndProcedure


Procedure Fourchette()
FrameGadget(#Fram_Fourchette, 10, 10, 200, 55, "Difficulter", 0)
 ComboBoxGadget(#ComboBox_Fourchette, 20, 30, 180, 20, 0) 
  AddGadgetItem(#ComboBox_Fourchette, 0, "Facile : Valeur entre 1 et 100", 0, 0)
  AddGadgetItem(#ComboBox_Fourchette, 1, "Moyen : Valeur entre 1 et 1000", 0, 0)
  AddGadgetItem(#ComboBox_Fourchette, 2, "Difficile : Valeur entre 1 et 10000", 0, 0)
  AddGadgetItem(#ComboBox_Fourchette, 3, "Extreme : Valeur entre 1 et 100000", 0, 0)
  
   SetGadgetState(#ComboBox_Fourchette, 0)
EndProcedure
 

Procedure Button_Demarrer()
FrameGadget(#Fram_Button_Demarrer, 10, 70, 200, 55, "", 0) 
 ButtonGadget(#Button_Demarrer, 20, 90, 180, 20, "Demarrer le jeu", 0)
EndProcedure 


Procedure Valeur_Du_Joueur()
FrameGadget(#Fram_Valeur_Du_Joueur, 10, 130, 200, 55, "Entrez votre valeur puis validez", 0) 
 StringGadget(#String_Valeur_Du_Joueur, 20, 150, 50, 20, "", #PB_String_Numeric)
  DisableGadget(#String_Valeur_Du_Joueur, #True)

ButtonGadget(#Button_Valeur_Du_Joueur, 80, 150, 120, 20, "Validez", 0)
 DisableGadget(#Button_Valeur_Du_Joueur, #True)
EndProcedure


Procedure Affichage_Des_Resultats()
FrameGadget(#Fram_Affichage_Des_Resultats, 10, 190, 200, 400, "Affichage des différentes réponses", 0)
 ListIconGadget(#ListIcon_Affichage_Des_Resultats, 20, 210, 180, 370, "Résultats", 176, #PB_ListIcon_GridLines|#PB_ListIcon_AlwaysShowSelection)
EndProcedure


;- procedure qui affiche un message quand nous avons trouver la bonne valeur
Procedure Valeur_Trouver()
Nb_De_Coups = CountGadgetItems(#ListIcon_Affichage_Des_Resultats)+1; recupere le nombres de coups

Choix = MessageRequester("Information", "Bravo, vous avez trouvez en : "+Nb_De_Coups+" coups. Souhaitez vous faire une nouvelle partie ?", #PB_MessageRequester_YesNo)
If Choix = 6; le bouton Oui a été choisi, on active et desactive les differants gadgets. Et on nettoie les gadgets
DisableGadget(#ComboBox_Fourchette, #False)
DisableGadget(#Button_Demarrer, #False)
DisableGadget(#String_Valeur_Du_Joueur, #True)
DisableGadget(#Button_Valeur_Du_Joueur, #True) 
 SetGadgetText(#String_Valeur_Du_Joueur, "")
 ClearGadgetItems(#ListIcon_Affichage_Des_Resultats)
  Nb_De_Coups = 0 ; met le nombre de coup au depart a 0
 
Else ; le bouton Non a été choisi
 End 
EndIf

EndProcedure


;- procedure principale qui gere les affichages, compare les resultats etc..
Procedure Game()
Valeur_Entree$ = GetGadgetText(#String_Valeur_Du_Joueur)

If Val(Valeur_Entree$) < Valeur_A_Trouver ; si la valeur entree est plus petite
AddGadgetItem(#ListIcon_Affichage_Des_Resultats, CountGadgetItems(#ListIcon_Affichage_Des_Resultats), "C'est plus grand que : "+Valeur_Entree$, 0, 0)

ElseIf Val(Valeur_Entree$) > Valeur_A_Trouver ; si la valeur entree est plus grande
AddGadgetItem(#ListIcon_Affichage_Des_Resultats, CountGadgetItems(#ListIcon_Affichage_Des_Resultats), "C'est plus petit que : "+Valeur_Entree$, 0, 0)

ElseIf Val(Valeur_Entree$) = Valeur_A_Trouver ; si la valeur est bonne
Valeur_Trouver()   
EndIf 

SetGadgetState(#ListIcon_Affichage_Des_Resultats, CountGadgetItems(#ListIcon_Affichage_Des_Resultats)-1)

SetGadgetText(#String_Valeur_Du_Joueur, ""); vide le stringgadget apres envoie de la valeur
EndProcedure
Rien de plus a ajouté. Le code contient des commentaires.

EDIT :
Ajout l'option de valider la valeur avec la touche Entrée (beaucoup plus pratique) :D





@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Le plus ou moins

Message par PAPIPP »

Bonjour Venon

Et merci pour ce prg.

La recherche dichotomique optimise le nombre de test de recherche.

Cette méthode consiste à tester le nombre compris à moitié chemin entre un mini et un max.
Ici au départ le mini est 0 et le max 100 donc on test 50
La suite dépend du résultat donné par le prg.
1) Si le prg me dit que le nombre est supérieur on prend comme min =50 et max=100 donc moyenne =75 ect.. jusqu’au résultat final.
2) Si le prg me dit que le nombre est inférieur on prend comme min =0 et max=50 donc moyenne =25 ect.. jusqu’au résultat final.

Le nombre de tests en recherche dichotomique N_test= Log2(de l’étendue) dans notre cas N_test=log2(100)=6.64.
On doit donc trouver le nombre cherché situé entre 0 est 100 en <=6,64 coups donc <=7.

Code : Tout sélectionner

;; la formule du nombre max de recherche avec la méthode dichotomique est Nmoy=Log2(100)
Procedure.d LOG2d(numb)
  Protected RESUL.D
EnableASM
FINIT
FLD1 
FILD  dword [p.v_numb]
FYL2X 
FST  qword [p.v_RESUL]
ProcedureReturn resul
DisableASM 
EndProcedure
Debug StrD(LOG2d(100),18)
A+
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Le plus ou moins

Message par venom »

Bonjour papipp,

Merci je ne connaissais pas le terme dichotomique :wink: Par contre j'avais la bonne façon de trouver le nombre :D (logique en même temps) :P







@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Avatar de l’utilisateur
Micoute
Messages : 2522
Inscription : dim. 02/oct./2011 16:17
Localisation : 35520 La Mézière

Re: Le plus ou moins

Message par Micoute »

C'est le même principe qu'un fil électrique qui est coupé quelque part, mais dont on veut garder la plus grande longueur possible.
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
Kwai chang caine
Messages : 6962
Inscription : sam. 23/sept./2006 18:32
Localisation : Isere

Re: Le plus ou moins

Message par Kwai chang caine »

C'est cool !!!
J'ai aussi utilisé cette méthode. (1 à 100 en 5 réponses)

Moi je la connaissais, parce qu'au boulot en 1990 on travaillait avec des HUNTER (petits ordinateurs portables) programmables en basic, qui étaient lents (Comme beaucoup de truc de l'époque)
Et la développeuse blonde, elle arrivait à trouver une référence parmi tant d'autres, en quelques secondes 8O

Je lui avait demandé comment elle faisait, et le splendide mot "Dichotomique" venu de nulle part, est sorti de sa jolie bouche
Dichotomique ça la pète déjà tout seul comme mot, faut déjà faire fort pour caser ça dans une phrase à table, mais alors dans la bouche d'une belle blonde....je vous dit pas comment ma recherche d'affection à moi personnelle, elle a été tout autant décuplée :mrgreen:
Du coups j'ai jamais oublié ce mot...comme quoi l'apprentissage passe beaucoup mieux quant on y met du cœur :lol:

Merci pour le partage 8)
ImageLe bonheur est une route...
Pas une destination

PureBasic Forum Officiel - Site PureBasic
PAPIPP
Messages : 534
Inscription : sam. 23/févr./2008 17:58

Re: Le plus ou moins

Message par PAPIPP »

Bonjour Venon

Comme on peut mesurer le nombre de coups max (voir ci-dessous le prg).

On pourrait émettre un message d’encouragement si le nombre de coups dépasse le max trouvé.

Prg du calcul de log2 avec en entrée et en sortie un flottant.

Code : Tout sélectionner

;; la formule du nombre max de recherche avec la méthode dichotomique est Nbtestmax=Log2(100)
Structure vald
  StructureUnion
    vd.d
    vq.q
  EndStructureUnion
 EndStructure 
Procedure.d LOG2dd(numb.d)
  Protected RESUL.D
EnableASM
FINIT
FLD1 
FLD  qword [p.v_numb]
FYL2X 
FST  qword [p.v_RESUL]
ProcedureReturn resul
DisableASM 
EndProcedure
i.vald\vd=10
ldd.d
While i\vd<=Pow(10,20)
  ldd=LOG2dd(i\vd)
  Debug "Nb_tests_Max=Log2("+StrD(i\vd)+")="+StrD(Ldd,18)+" donc <="+Round(ldd,#PB_Round_Up)+"      hexa="+Hex(i\vq,#PB_Quad)
  i\vd*10
Wend
Il est fort peu probable que les mêmes causes ne produisent pas les mêmes effets.(Einstein)
Et en logique positive cela donne.
Il est très fortement probable que les mêmes causes produisent les mêmes effets.
Avatar de l’utilisateur
venom
Messages : 3071
Inscription : jeu. 29/juil./2004 16:33
Localisation : Klyntar
Contact :

Re: Le plus ou moins

Message par venom »

Salut PAPIPP,

Merci pour ce sympathique code 8) Oui pourquoi pas l’intégré au jeu ça pourrait être sympa.






@++
Windows 10 x64, PureBasic 5.73 x86 & x64
GPU : radeon HD6370M, CPU : p6200 2.13Ghz
Répondre