Other Quiz #10 - 2000 buttons quiz

Erel

B4X founder
Staff member
Licensed User
Longtime User
As a developer you should avoid duplicating code. I sometimes see code such as:
B4X:
Sub Button1_Click
x = 1
End Sub

Sub Button2_Click
x = 2
End Sub

...
If you like to write such code then unfortunately this quiz is not for you...

In this quiz you need to add 2000 buttons to the main activity. Each button should show a random number between 1 to 100.
When the user clicks on a button, all buttons with the same number should be brought to front:

upload_2014-1-12_14-47-46.png


A good answer is an answer that correctly implements this quiz.

An excellent answer is an answer that correctly implements this quiz and doesn't iterate over all buttons each time (finding the set of buttons in O(1)).
 

moster67

Expert
Licensed User
Longtime User
:)

I guess something like using "sender", would be a good approach.

But then after all, it depends also on how many buttons you are dealing with. Is it worthwhile for 4-6 buttons or not? For 2000 buttons, I agree.
 
Upvote 0

Yalçın Kondur

Member
Licensed User
Longtime User
Sub Globals
Dim Btn(2000) As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
Activity.LoadLayout("Layout1")
Dim i,rn,bX,bY As Int
For i=0 To 1999
bX=Rnd(0,100%x-50dip)
bY=Rnd(0,100%y-50dip)
rn=Rnd(1,100)
Btn(i).Initialize("Button")
Btn(i).Text=rn
Activity.AddView(Btn(i),bX,bY,50dip,50dip)
Next
End Sub

Sub Button_Click
Dim i As Int
Dim t As String
Dim b As Button
b=Sender
t=b.Text
For i=0 To 1999
If Btn(i).Text=t Then Btn(i).BringToFront
Next
End Sub
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
B4X:
#Region  Project Attributes
    #ApplicationLabel: Quiz10
    #VersionCode: 1
    #VersionName:
    'SupportedOrientations possible values: unspecified, landscape or portrait.
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: True
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim btnlist(101) As List
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    'Activity.LoadLayout("Layout1")
    For i = 0 To 100
        btnlist(i).Initialize
    Next
 
    For i = 0 To 1999
        Dim btn As Button
        btn.Initialize("button")
        Dim posx As Int = Rnd(0,100%x-50dip)
        Dim posy As Int = Rnd(0,100%y-50dip)
        Dim zufall As Int = Rnd(1, 101)
        Dim col As Int
        col = Colors.ARGB(Rnd(100, 150),Rnd(20, 800),Rnd(80, 160),Rnd(161, 255))
        btn.Color = col
        btn.Text = zufall
        btn.Tag = zufall
        Activity.AddView(btn,posx,posy,50dip,50dip)
     
        btnlist(zufall).Add(btn)
    Next
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub Button_Click
    Dim b As Button
    b = Sender
    Dim buttonlist As List
    buttonlist = btnlist(b.Tag)
    Log("Button "&b.Tag&" clicked. "&buttonlist.Size&" Buttons")
    ToastMessageShow("Button "&b.Tag&" clicked. "&buttonlist.Size&" Buttons", True)
    For i = 0 To buttonlist.Size -1
        Dim t As Button
        t = buttonlist.Get(i)
        t.BringToFront
    Next
End Sub
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Nice work.

We have one two good answers and one excellent answer. Well done DonManfred!

You even remembered that the max value of Rnd keyword is exclusive.

Here is my code:
B4X:
Sub Globals
   Dim views As Map
End Sub

Sub Activity_Create(FirstTime As Boolean)
   views.Initialize
   For i = 1 To 2000
     Dim b As Button
     b.Initialize("b")
     b.Text = Rnd(1, 101)
     b.Color = Rnd(0x8FFFFFFF, -1)
     Activity.AddView(b, Rnd(0, 95%x), Rnd(0, 95%y), 100dip, 100dip)
     Dim l1 As List
     If views.ContainsKey(b.Text) Then
       l1 = views.Get(b.Text)
     Else
       l1.Initialize
       views.Put(b.Text, l1)
     End If
     l1.Add(b)
   Next
End Sub

Sub b_Click
   Dim b As Button = Sender
   Dim l1 As List = views.Get(b.Text)
   For Each bb As Button In l1
     bb.BringToFront
   Next
End Sub

Do we get something as price for this quiz if we win?
Eternal respect from all the forum members :)
 
Upvote 0

boten

Active Member
Licensed User
Longtime User
Unfortunately, I saw it just now.

This quiz was too easy!

Solve this ($ 1 million to the winner):

Create an app with which I definitely win the Lotto in my Country.

:D
Fill all the lotto combinations, guaranteed to win the lottery (but lose a lot of money). Please send me $1 m.
 
Upvote 0

mc73

Well-Known Member
Licensed User
Longtime User
I would go for mapping but since I'm late and Erel already gave this type of source, here's another approach, I've tested it a bit, seems that it works, and it's a bit less straight forward, since it's using a sorting trick:
B4X:
Sub Globals
   'These global variables will be redeclared each time the activity is created.
   'These variables can only be accessed from this module.
   Dim btnArray As List,startIndex(101) As Int, btn(2000) As Button
End Sub

Sub Activity_Create(FirstTime As Boolean)
   'Do not forget to load the layout file created with the visual designer. For example:
   'Activity.LoadLayout("Layout1")
   btnArray.Initialize
   For i=0 To 1999
     Dim a As Int
     a=Rnd(0,100)
     btnArray.Add(a)
   Next
   btnArray.Sort(True)
   Dim oldNumber As Int=-1
   For i=0 To 1999
     Dim newNumber As Int
     newnumber=btnarray.Get(i)
     btn(i).Initialize ("btn")
     btn(i).Text=newNumber+1
     Activity.AddView (btn(i),Rnd(0,5)*Activity.Width /5,Rnd(0,10)*Activity.Height/10,20%x,10%y)
     If newNumber>oldNumber Then
       startIndex(newNumber)=i
       oldNumber=newNumber
       btn(i).BringToFront
     Else
       btn(i).SendToBack
     End If
   Next
   startIndex(100)=2000
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btn_click
   Dim btnTemp As Button
   btnTemp=Sender
   Dim idEnd As Int,idStart As Int
   iDend=btnTemp.Text
   iDstart=iDend-1
   For i=startIndex(idStart) To startIndex(idEnd)-1
     btn(i).BringToFront
   Next
End Sub


Edit: And now that I see it better, there exists a bug, which can appear occasionally. Anyone sees it? :)
 
Last edited:
Upvote 0

WAZUMBi

Well-Known Member
Licensed User
Longtime User
B4X:
Dim l1 As List = views.Get(b.Text) 
For Each bb As Button In l1   
bb.BringToFront  Next

I am not familiar with this.
Does this not iterate through the buttons?
Is it faster?
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
No, not familar. There are view which contains all buttons. a view for button with text "1", a view for buttons with Text "2" and so on....
So it "only" iterates through all buttons with the same Text.
In my example i´m using 100 lists of buttons... a button with Text "1" is stored in buttonlist(1).add(btn) in one of these 100 lists. I get the desired lists in the clickevent and iterate through this list. Erels version with this views are surely better

But it was fun for me to take the quiz and i´m proud of my version. Its not as good as erels but it works.

AND, by the way, my approach DO set also a different color and transparency with all buttons like in there Screenshots of the "Quiz question".
Not sure but i think i´m the only one who have did this feature (ok, it was not part of the Quiz. But to try and learn for myself i have tried to implement this too. With success i will say! ;) I speaked a loud "JA Mann!" (YES MAN!) after i get that running ;-)
 
Upvote 0
Top