2017년 7월 16일 일요일

Help for hire? Cannot seem to generate 3 unlike random integers.


I am still having trouble generating three random numbers that are not alike. I have tried a bunch of things, but everything I try other than the solution posted (which on very rare occasions turns up with two alike answers) changes my three answer buttons to read 'true' instead of 3 random integers that are not alike. 

Are any of the moderators of this forum available to hire to fix this problem for me? (I am a teacher so the rate must be very reasonable. I know this is an easy fix....I just cannot seem to find a way to do it.)







--
Thank you for your quick reply. I can see how your example would be beneficial for a game with fixed answers. My game is a multiplication game and I would like to generate random integers for two buttons and one fixed 'answer' button. I would also like the 'answer' button to vary in position (button 1, button 2, button 3) so that the user can't pick the answer based on the knowledge that the correct answer will always be button 1 (example.)

Attached is a pic the latest try that I have attempted (and logicTest.aia file) I am getting a runtime error. 



If you like, we have an extension that can perform useful list operations. If interested, we can add feature to remove duplicates and return a list containing unique items:
--
..And here is the correct url address:
do you store the correct answer in a list?
you example is not so much different from my example...

--
I store the correct answers in a csv file (attached) I pull the multiplication problems out of the csv file first as a row then as a column (index items). So while there is a temp list for the correct multiples and product, there is not a complete list of answers only. (I hope this makes sense.)

MultiplePairs_Level1.csv

--
Here is a working .aia which solves your problem (as I think it is). It is surprisingly complex,
- you want the questions in random order
- you want the answers to be random and randomly assigned to buttons
- there should be no duplicates in the possible answers
- you should check if all questions are asked
- you should check if the answer is correct, then ask the next question
etc.
See if you can make sense out of it, otherwise ask. And make a donation to App Inventor if you like (see the donation button at the front page).

logicTest_copy.aia

--
Thank you so much. I am working on this today. I tried Taifun's idea but it still rendered duplicate answers on the button labels (due to the nature of the necessary set up of random problems and random answers. See attached.) I will report back when I have tried your solution! (Thank you again.....this has been driving me crazy.lol.)




--
My solution does much more than just finding three different numbers for the buttons. It also sets random questions from your csv list and checks the answers. It is a complete app, that just needs some brushing up with nicer buttons and so on.

Anyway, I realized that i checked that the correct answer could not be among the random answers, but that I also should check that there are no duplicate random answers. Therefore I changed the app slightly. Here is a procedure that sets three random different numbers on the three buttons. How do you do it?

- Generate a list of numbers between 1 and 100 (or whatever the answer space for your numbers is. The highest I saw in your csv was 72, so I took 100, but of course you can take another number.
- Remove the correct answer from this list. It will be added to a random button later.
- Use the any blocks to go through the list of buttons (you have only three, but in this setup you could as easily have 5 or 7 or whatever).
- Take a random item from the number list, set the button text to it.
- Remove the item from the list.

To set the random button with the correct answer: choose a random number from 1 to length button list. Remember it in a global variable because you need it while checking whether the answer given is right.
Then, set the text of that button (using the any blocks) to the correct answer.
Try it using the attached .aia!

logicTest_copy_2.aia

--
Yes, I noticed that your original version did much more than my original thought. I am currently working on splicing your version "1" with my original work to make my game. This portion is only the second part to the entire game. I did quite a bit of work already when I noticed your additional message. I will need to take a look at your version"2" above again tomorrow morning. If I understand your notes correctly you are saying that version"1" could possibly still have repeated number labels?

--
Yes. And thinking about it, there is still a problem with the second solution too. I will correct it later.
But for you it should be easy to adapt later, because the random number stuff is in a procedure, so if you change the procedure, you do not need to change anything else.


--



This is my last attempt at getting this right, I hope ;-)
Let's start from the beginning, in the hope that you understand what is happening and can use it in your game.

At Screen1.initialize, the buttonList is defined. You cannot define this at initialization of the global, because the components are not defined at that time.
Next, the csv file is read.

Then, at when File1.GotText, you read the text into a list of lists, global QuestionList. Each element in the list is a list itself. For example the, 20th line in MultiplePairs_Level.csv looks like this: 5,2,10
It will become the element with index 20 in the list global QuestionList, and this element is a list itself consisting of three elements: the two numbers to be multiplied and the answer to this multiplication. In fact, you do not need the third element, as AppInventor can easily calcultate it, but I used the values in the hope they are right.
Then, still in the when File1.GotText event block, the number of questions is displayed in a label (the number of elements in global questionList) and the nextQuestion procedure is called.

Procedure nextQuestion:
- Find a random question from the questionList (this question is removed from the list when checking the answer, so no question will be asked twice)
- Retrieve the question list. So, for example, if the random number we found, and set in de globalQuestionIndex, were 20, the global currentQuestion would become the list (5,2,10).
- For convenience, set the current answer in global currentAnswer. It is the 3rd element in global currentQuestion.
- Set a label with the exercise text. Self explanatory I hope.
- Then, set the random button where the correct answer should be shown. It is a random number between 1 and 3, because our button list has length 3. Save it in global rightAnswerNr, because we need it later.
- The procedure setButtons is called. The result of this will be three random answers in the three buttons, but the right answer will not be one of them.
- We overwrite the number in the button with index rightAnswerNr in the buttonlist with the right answer. We are doing it this way because otherwise we would have to do many checks to see if the right answer is in one of the other buttons already. Doable if you have three, but very complex later.
- Then we wait until the user presses a button. But let's look first at setButtons, in our 3rd attempt to get it right.

Procedure setButtons
It assumes that you have the right answer to the multiplication question in global currentAnswer. This global is set in the nextQuestion procedure as we saw, before calling setButtons.
- We start with creating a list of all possible random answers. Here a list of 100 numbers, from 1 to 100. We use a local variable to store this list, because we do not need it elsewhere and it is recreated everytime we cal setButtons.
- Next, we need to remove the correct answer from this list. We check whether the answer is indeed within the range of the random numbers. Otherwise, we would get a runtime error trying to remove it. I thought this would be true by design, but because you are saying it is part of a larger game. I am not so sure. Here, the index is the same as the value of the list element, therefore we remove it from the list by index number.
- This was my last mistake (a classical stupid), after we removed one element from the list, the element indexes are not necessarily the same as the element values.
- anyway, for each item in the buttonList, find a random answer index, set the current button the the value of that element and remove the element from the list.

That's it.

If  you have question about checking the answer, please ask. 


logicTest_copy_3.aia

--
Thank you so much. I am still re-reading your notes above to make sure I understand and learn from your work. You make it sound so easy!!!! I am working on this now and will report back on how it is meshing with the larger game. So far I have integrated your original idea with just a few bumps. I am hoping that the last iteration of the 'no repeat' random buttons above works. Thank you so much for all of your time and help.

p.s. I will be donating from my monthly paycheck to MIT App Inventor. :)


--
I got a runtime error the first time I tried to play. I disabled the piece of code that you explain like this above: " Next, we need to remove the correct answer from this list. We check whether the answer is indeed within the range of the random numbers. Otherwise, we would get a runtime error trying to remove it. I thought this would be true by design, but because you are saying it is part of a larger game. I am not so sure. Here, the index is the same as the value of the list element, therefore we remove it from the list by index number." ...And it is working. The occurrence of repeated buttons with your original solution was so infrequent. So far I have played with you most recent revision (and the block disabled) and I have not found duplicates. Do you think that the block I disabled is needed? (Sorry for my ignorance...I am still studying your work for complete understanding.)

(The runtime error said something like: Trying to find "0" in a list of 1, 2, 3,....100.)

--
I just came across a duplicate. The block I disabled is needed to prevent the duplicates. I am not sure how to resolve the runtime error.

--
The runtime error is there for a reason and usually the error message says what the reason is, also in this case.
It says that you are trying to remove an element with index 0 from the list of possible random answers. But lists do not have an index 0. They start at 1.
What you have tried to remove is the index that is the value of global currentAnswer, the right answer to the question. If it is 0, you did not set it where it should be set: before calling setButtons.
You could prevent the runtime error by checking whether the value of currentAnswer is > 0 but that would just mask a problem elsewhere, and you would get duplicates of the right answer eventually.
Set the global currentAnswer and you should be fine.
Cheers, Ghica.
When one generates pseudo random numbers and the range of possibilities is not large, sooner or later there IS going to be a DUPLICATE.
The solution is to compare the three 'random' values and provide logic to determine if any are identical values; if identical then determine which one cannot change and change 
the other with a random number in the appropriate range. 

An alternative method is to use Saj 's methodology    http://www.imagnity.com/tutorials/app-inventor/shuffle-list-unique-random-numbers/   . He uses the  Fisher–Yates shuffle    algorithm to shuffle then randomly REMOVE one of the possibilities from the List so the result is random without repeats .   If the list is a List of integers, this could work for you.          

The difficulty is to integrate one of these possible solution into your code.  Either select the random number and eliminate the possibility of possible duplicates or after all three values are selected, to ensure using conditional statements that ALL three are different but within the limits you require.

App Inventor's random numbers are NOT truly random.  Unless the developer sets the random seed a sequence of what is generated will actually replicate.  Use the random set seed to block  with a puzzle piece representing  an supposedly random value, perhaps  the Clock seconds  or the day of the year etc..  The random seed is a number used to initialize a pseudor andom number generator. For a seed to be used in a pseudo random number generator, it does not need to be random. If one wants the best available random value, the developer must set the seed.

--
Hello again. I have tried to use conditional statements to check that all three numbers are different but the button values turn up with "true" or "false" on them instead of numbers. I am really struggling with this. As it stands Ghica's solution works fairly well to return repeat values very seldomly. (It still happens though.) I have spent two, twelve hour days reworking the entire game around Ghica's solution. I really want this to be 'perfect' but I am not sure if there is a way.

--
Oh, "all three numbers are different but the button values turn up with "true" or "false" on them instead of numbers."  this means you have a coding issue with your conditionals, show you blocks and there might be a recommendation.

Again, "I really want this to be 'perfect' but I am not sure if there is a way",   my previous post just presented a way to ensure each of the three buttons does not have the same random number.  Look at Saj's example.  There will be NO duplicates.  Your List in this case will be 1,2,3,4,5 ...etc to the range limit you set.  You shuffle the List of integers, the select possibly the first three .  If one of the values has to be a specific value, then take the value that has a higher index for the one button than the required number and the other the lower index value item.

You are attempting to do some very complex coding with very little previous experience and actually are doing fine.  When something doesn't work, move on to the next possibility. 

--
Here is a probable solution based on Saj's example tutorial::
Three buttons, each with a unique non duplicating random integer.  The csv embeded is 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,31,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50      
Extend the csv if higher random values are required,   

I am not so happy the way this discussion is going.
My method guarantees that there are no duplicates and you do not have to do if statements. It is based on Taifun's method of removing elements from a list after having chosen a random one.
Veronica, that you still have duplicates must be a programming bug. If you want I can look into it, but then you should post the relevant blocks or an .aia (you could also send me this privately if you wish).


--
Oh Ghica....thank you. When I have 'cleaned-up' the program (lots of random blocks around and disabled...and a few screens to delete) I will send the aia to you privately. While I appreciate SteveJG's help (more than he knows) I just don't know how I can integrate what he has done into what is going on right now with my app. I am working on this today and will PM you later. Thank you again!!!! :)

--
I am sure it is a simple mistake of integrating your stuff with my little procedure, we will see.

--
Thank you for looking over my file. I actually resolved the runtime error I mentioned in pm on my own. (I forgot to enable the block in the chk answer procedure. Unfortunately upon the first two rounds of the game I got a repeated button. This problem is a 'hair pulling' mess. At first glance it seems easy enough to do....and then all of this. See attached.

Thank you again for all of your help. I really appreciate your efforts.



--

댓글 없음:

댓글 쓰기