2 randoms seem to give near identical result - java

thanks in advance for taking time to look at my Q. and anyone with the same problem i hope we get a solution...
so basicly i have an app that spins 2 coins at the same time and displays what the result is.
This method generates the first coin...
public void coinResult1(){
ImageView coin1View = (ImageView) findViewById(R.id.coin1);
Random r = new Random();
int coin1result = r.nextInt(2);
if (coin1result == 0){
coin1View.setBackgroundResource(R.drawable.coinheads);
coinresult1 = 0;
}
else if (coin1result == 1) {
coin1View.setBackgroundResource(R.drawable.cointails);
coinresult1 = 1;
}
}
and this is for the second coin
public void coinResult2(){
ImageView coin2View = (ImageView) findViewById(R.id.coin2);
Random r = new Random();
int coin2result = r.nextInt(2);
if (coin2result == 0){
coin2View.setBackgroundResource(R.drawable.coinheads);
coinresult2 = 0;
}
else if (coin2result == 1) {
coin2View.setBackgroundResource(R.drawable.cointails);
coinresult2 = 1;
}
}
this is linked to onclick() of button which check the results to a player selection
public void checkResult(){
coinResult1();
coinResult2();
coinResult = coinresult1 + coinresult2;
if (coinResult == playerSelection){
playerWins();
buttonsReset();
}
else {
playerLost();
buttonsReset();
}
}
Now the only problem i have is...
the results of both coins of 1000 presses are this...
HeadsHeads 54%
HeadsTails 2%
TailsTails 44%
of 1000000 spins was roughly the same percentages
when each coin result was counted seprately
COIN1 heads 53% tails 47%
COIN2 heads 48% tails 52%
Now my friend says their is something wrong with those odds....beacause HeadsTails wasnt a high enough percent, hes expecting it to be close to 33% each combination at random
the code seems to favour HeadsHeads and TailsTails or HeadsTails.....ive tried several times and keep getting a low % of HeadsTails
can anyone shead some light on whats going on....and what is causing HeadsTails to rarely come out?
hope to hear back soon

Your repeated instantiation of Random is ruining the statistical properties of the generator.
You need to create one instance and pass that into your functions. Better still, use a field in your class.
Please refer to this question for concerns over thread safety of the Random class:Is Random class thread safe?. It seems to suggest that you should synchronize the nextInt calls.

You should never re-create random number generator over and over again:
public void coinResult1(){
ImageView coin1View = (ImageView) findViewById(R.id.coin1);
Random r = new Random(); // <- That's the source of errors!
int coin1result = r.nextInt(2);
...
Instead, create random generator instance once and for all:
// Simplest, not thread-safe amendment
private static Random s_Gen = new Random();
...
public void coinResult1(){
ImageView coin1View = (ImageView) findViewById(R.id.coin1);
int coin1result = s_Gen.nextInt(2);
...
The cause of the misbehaviour is that when you re-create Random it often re-initializes from the same seed (which is usually current time) and so generates the same values.

You must create only one instance of Random.
private Random r;
// initialize r in onCreate or somehere else only once
protected void onCreate(Bundle savedInstanceState){
// ...
r = new Random();
}
public void coinResult1(){
ImageView coin1View = (ImageView) findViewById(R.id.coin1);
int coin1result = r.nextInt(2);
if (coin1result == 0){
coin1View.setBackgroundResource(R.drawable.coinheads);
coinresult1 = 0;
}
else if (coin1result == 1) {
coin1View.setBackgroundResource(R.drawable.cointails);
coinresult1 = 1;
}
}
public void coinResult2(){
ImageView coin2View = (ImageView) findViewById(R.id.coin2);
int coin2result = r.nextInt(2);
if (coin2result == 0){
coin2View.setBackgroundResource(R.drawable.coinheads);
coinresult2 = 0;
}
else if (coin2result == 1) {
coin2View.setBackgroundResource(R.drawable.cointails);
coinresult2 = 1;
}
}

Related

Need Help sorting out nested for loops

I'm trying to make a trivia game for my English class that will randomly pick a question, but will not pick the same one twice. I currently have a prototype set up, but I can't figure out what is going wrong that is preventing it from actually printing the questions.
Here's the behemoth:
import java.io.*;
import java.util.*;
public class qpicker
{
public static void main (String args[])
{
int qs = 0;
boolean q1checker, q2checker, q3checker, q4checker, q5checker,
q6checker, q7checker, q8checker, q9checker, q10checker, q11checker,
q12checker,q13checker, q14checker, q15checker, q16checker, q17checker,
q18checker, q19checker, q20checker; //this disaster is where i declared my
q1checker = false; //booleans
q2checker = false;
q3checker = false;
q4checker = false;
q5checker = false;
q6checker = false;
q7checker = false;
q8checker = false;
q9checker = false;
q10checker = false;
q1checker = false;
q12checker = false;
q13checker = false;
q14checker = false;
q15checker = false;
q16checker = false;
q17checker = false;
q18checker = false;
q19checker = false;
q20checker = false; //here i tried to set all booleans to false,
//thinking maybe that was the issue
do
{
qs++;
Random random = new Random();
double rng = random.nextDouble();
double selecter = rng * 10;//makes the random number easier to read
if(rng <=.5)
{
if(q1checker = false)
{
System.out.println("Put first q in here");
q1checker = true;
break;
}
}
System.out.print("cheese");//code progress tracker
if(rng <=1 && rng >.5)//this is where the question would be pulled
{
if(q2checker = false)//this ensures questions aren't repeated
{
System.out.println("Put second q in here");//display quest.
q2checker = true;
break;
}
}
System.out.print("e");
if(rng <=1.5 && rng > 1)//question picked
{
if(q3checker = false)//ensures questions aren't repeated
{
System.out.println("Put third q in here");//display quest.
q3checker = true;
break;
}
}
System.out.print("y");
if(rng <=2 && rng > 1.5 )
{
if(q4checker = false)
{
System.out.println("Put fourth q in here");
q4checker = true;
break;
}
else if (q4checker = true)
{continue;}
System.out.print(" ");
}if(rng <=2.5 && rng > 2)
{
if(q5checker = false)
{
System.out.println("Put fifth q in here");
q5checker = true;
break;
}
}
System.out.print("good");
if(rng <=3 && rng > 2.5)
{
if(q6checker = false)
{
System.out.println("Put sixth q in here");
q6checker = true;
break;
}
}
System.out.print("ness");//spells out "cheesey goodness" 20 times
}while (qs < 20);//ensures all questions are printed (in final product)
}
}
static void shuffleArray(string[] ar)
{
//set the seed for the random variable
Random rnd = ThreadLocalRandom.current();
//go from the last element to the first one.
for (int i = ar.size()- 1; i > 0; i--)
{
//get a random number till the current position and simply swap elements
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
This way you shuffle the entire array and get the values in a random order but NO duplicate at all. Every single element changes position, so that no matter what element (position) you pick, you get a country from a random position. You can return the entire vector, the positions are random.
You could try this method, for shuffling your array and returning the entire array in random order since it mixes the elements.
From what I see you are trying to allow them to choose questions until they are exhausted, choosing randomly. You can do this easily with an ArrayList, where you pick randomly an index from the list to pull your question, remove the question from your list, so it is no longer available to choose from. Note that after you remove and use it from the list, the list will be smaller by 1
String[] questionArray = ["Question 1","Question 2","Question 3","Question 4","Question 5"];
ArrayList<String> questionList = Arrays.asList(questionArray);
//Get a random number within the range of 0..questionList.size()
int chosenIndex = 1; //Made up for simplicity
String chosen = questionList.remove(chosenIndex);
//Now that you have chosen a question, and it was removed from the list
//The list is one element smaller. Next time you get a random number
//make sure you use the range: 0..chosen.size()
System.out.println(chosen);
I believe this is what you are looking for.
You should use arrays.
Also remember that = is an assignment operator while == is comparation
This:
if(rng <=.5)
{
if(q1checker = false)
Is wrong, it should be:
if(rng <=.5)
{
if(q1checker == false)
Or better:
if(rng <=.5)
{
if(!q1checker)

How to retrieve value changes made from a For Loop within it's own method in Android Studio?

I have a for loop within my main activity that is used to randomly shuffle/reassign the values within an array at the beginning of every time the application is opened.
I was told that for loops in Android Studio could only exist within a method (after getting errors when it was placed without one), but by doing so the random shuffling of the array is not carried over to the rest of the click events that are outside of the method and it just continues to output the same originally assigned values of in the array.
int[] money = {1,10,5,2,20,500,50,100,1000000,5000,1000,50000,100000,500000,250000,10000};
int swap1;
int swap2;
int temp;
Random random = new Random();
void what(){
for (int j=0;j<16;j+=1)
{
swap1 = random.nextInt(16);
swap2 = random.nextInt(16);
temp = money[swap1];
money[swap1] = money[swap2];
money[swap2] = temp;
}
}
The click events that are using the values from this array are like this one:
one.setOnClickListener(new View.OnClickListener() {
public void onClick(View b) {
one.setVisibility(View.INVISIBLE);
counter++;
money[0] = 0;
Context one = getApplicationContext();
CharSequence message1 = "$1";
int duration = Toast.LENGTH_LONG; //this could also be a number
final Toast one1 = Toast.makeText(one, message1, duration);
one1.show();
for (int x = 0; x < 16; x++) {
sum += money[x];
}
banker = sum / 16;
Context oney = getApplicationContext();
CharSequence message1y = "The Banker offers you $" + banker + " for your case.";
int durationy = Toast.LENGTH_LONG; //this could also be a number
final Toast one1y = Toast.makeText(oney, message1y, durationy);
one1y.show();
}
});
The aim was that if I were to click this button this time the money output was something like $500, and the next time I opened the application it would randomly shuffle and I might get a new value like $1.
You might want to check out Collections.shuffle() instead of implementing it (don't reinvent the wheel etc).
Sounds like what you want to do is call the shuffle method from inside onCreate() and onResume()
You should do the shuffle inside of the "onCreate" method.
public void onCreate(Bundle savedInstanceState){
...
int[] money = {1,10,5,2,20,500,50,100,1000000,5000,1000,50000,100000,500000,250000,10000};
int swap1;
int swap2;
int temp;
Random random = new Random();
void what(){
for (int j=0;j<16;j+=1)
{
swap1 = random.nextInt(16);
swap2 = random.nextInt(16);
temp = money[swap1];
money[swap1] = money[swap2];
money[swap2] = temp;
}
}
}

Hide ImageView on clicks

Thanks for all suggestion and thoughts i finally achieved it by yours suggestions and it was a simple logic work to solve the problem. I want to share it if any one want to create custom Health Bar , but it is not suitable for 100 HP because then you have to write 100 IF statements,
Idea was to create simple custom Healthbar and decrease it by pressing button clicks.
This link also help me a lot.
HealthBar
Code
private TextView Message,result;
private Button play;
private float maxHP = 10;
private float currentHP = maxHP;
//private float percentHP = (float) (currentHP/maxHP);
private int user_shield;
private float healthBar;
private ImageView shieldusb1,shieldusb2,shieldusb3;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level_one);
Initialize();
}
private void Initialize(){
user_shield = R.raw.shield_blue;
shieldusb2 = (ImageView) findViewById(R.id.shield_b2);
shieldusb1 = (ImageView) findViewById(R.id.shield_b1);
shieldusb3 = (ImageView) findViewById(R.id.shield_b3);
result = (TextView) findViewById(R.id.result);
play = (Button) findViewById(R.id.playButton);
play.setOnClickListener(new OnClickListener(){
public void onClick(View arg0){
play();
}
});
}
public void play(){
{
healthBar=0;
currentHP = (float) (currentHP - 0.5);
//currentHP -= 1;
if(currentHP <= 0) //if the player died
{
currentHP = 0; //set his HP to zero, (just in case)
Message.setText("You died! :P"); //add any extra death-code here
//update the healthBar
result.setText ("WIN POINTS");
}
updateHealthBar();
}
}
private void updateHealthBar() {
// percentHP = currentHP / maxHP;
healthBar = currentHP;
if(healthBar<9.6){
shieldusb1.setVisibility(View.GONE);
}
{
if (healthBar<=9){
shieldusb2.setVisibility(View.GONE);
}
if (healthBar<=8.6){
shieldusb3.setVisibility(View.GONE);
}
}
}
My guess, is you need to remove the else if and make it just if because if you execute first statement where <= 1, else if will never get executed.
private void updateHealthBar() {
percentHP = currentHP / maxHP; / calculating points
healthBar = percentHP;
if(healthBar<=1){ // Hiding first Image View
shieldusb1.setVisibility(View.GONE);
}
if (healthBar<=0.9){
shieldusb2.setVisibility(View.GONE); // How to Hide this Image View after button click
}
}
Your healthBar is of int type, so checking against 0.9 is the same as checking against 1.
Also, in your conditions, you're first checking:
if (healthBar <= 1)
If this condition is true, you're hiding shieldusb1, and you will never reach second condition because you have used else. What you can do is to remove else in front of second condition, but as said above, your healthBar is int, so the second condition is basically the same as the first. Change healthBar to double.
You need to adjust these conditions
if(healthBar<=1)
...
else if (healthBar<=0.9)
Even if healthBar<= 0.9 evaluates true, healthBar<=1 is also true so it will always enter the first if
You check if healthBar is <= 1, and after if is <= 0.9... But this case never verify, cause 0.9 is < 1, so it always choose the first option!
Change your first if for check values between 1 and 0.9, and it will work!
It's only logical problem. Change if/else if block for if/if.
if(healthBar<=1)
shieldusb1.setVisibility(View.GONE);
if (healthBar<=0.9)
shieldusb2.setVisibility(View.GONE);

Basic App Crashing When Implementing Images Fade-In

I'm attempting to work on a simple first Android app, and while eventually it will be a shake-to-activate app, right now it still works with the click of a button because I need to be able to test it on the emulator I have.
The end goal for the app is to, when the device is shaken, choose one random number out of three (each corresponds to a Character from a show) and read that number to fade in an image of that character. Directly after, it fades in a random quote from an array of quotes from that specific character.
Currently, I'd gotten the app working to the point where, when I clicked the button, the app chose a character, and a quote from the array for that character, and was able to fade the quote in. In trying to implement the image fading in, I've done something that makes the app crash when I try to run it.
I'm sure it'll be some stupid mistake, but it would be fantastic if it could be found.
The project has four class files: MainActivity.java, DoctorWho.java, Nine.java, Ten.java, and Eleven.java. Nine, Ten, and Eleven are all nearly identical, just using different quotes.
In trying to add the image fade-in, I added it to DoctorWho.java, here:
public class DoctorWho {
private Nine mNine = new Nine();
private Ten mTen = new Ten();
private Eleven mEleven = new Eleven();
private ImageView mImageView1;
private ImageView mImageView2;
private ImageView mImageView3;
int randomNumber = 0;
public String getDoctorQuote() {
String quote = "";
// Choose a Random number out of three values
Random randomGenerator = new Random();
int randomNumber = randomGenerator.nextInt(3);
// Use that value to choose which of the Doctors to get a quote from
if (randomNumber == 0) {
// Quote from Nine
quote = mNine.getQuote();
}
else if (randomNumber == 1) {
// Quote from Ten
quote = mTen.getQuote();
}
else if (randomNumber == 2) {
// Quote from Eleven
quote = mEleven.getQuote();
}
else {
quote = "Error";
}
return quote;
}
public void animateDoctor() {
if (randomNumber == 0) {
animateNinthDoctor();
}
else if (randomNumber == 1) {
animateTenthDoctor();
}
else if (randomNumber == 2) {
animateEleventhDoctor();
}
}
private void animateNinthDoctor() {
AlphaAnimation fadeInAnimation = new AlphaAnimation(0, 1);
fadeInAnimation.setDuration(1500);
fadeInAnimation.setFillAfter(true);
mImageView1.setAnimation(fadeInAnimation);
}
private void animateTenthDoctor() {
AlphaAnimation fadeInAnimation = new AlphaAnimation(0, 1);
fadeInAnimation.setDuration(1500);
fadeInAnimation.setFillAfter(true);
mImageView2.setAnimation(fadeInAnimation);
}
private void animateEleventhDoctor() {
AlphaAnimation fadeInAnimation = new AlphaAnimation(0, 1);
fadeInAnimation.setDuration(1500);
fadeInAnimation.setFillAfter(true);
mImageView3.setAnimation(fadeInAnimation);
}
In my MainActivity.java file, I try to run the animation on-click here:
#Override
public void onClick(View arg0) {
String quote = mDoctorWho.getDoctorQuote();
mDoctorWho.animateDoctor();
// mQuoteLabel is the TextView where the quotes are displayed
mQuoteLabel.setText(quote);
animateQuoteIn();
}
The app still starts up fine, and no errors are shown before I run it on the emulator. When I click on the button that should run this sequence, the app crashes. There are no errors shown in the console, and I wasn't able to find a specific line in the LogCat view - I may be looking in the wrong place though. Let me know if updating the post with more code would be helpful in finding what is causing the crash.
Try changing you DoctorWho class as following:
Also have you initialized mImageView1,mImageView2,mImageView3 inside DoctorWho class???
public class DoctorWho {
private Nine mNine = new Nine();
private Ten mTen = new Ten();
private Eleven mEleven = new Eleven();
private ImageView mImageView1;
private ImageView mImageView2;
private ImageView mImageView3;
int randomNumber = 0;
public String getDoctorQuote() {
String quote = "";
// Choose a Random number out of three values
Random randomGenerator = new Random();
randomNumber = randomGenerator.nextInt(3);//<--- don't create new randonNumber
// Use that value to choose which of the Doctors to get a quote from
if (randomNumber == 0) {
// Quote from Nine
quote = mNine.getQuote();
}
else if (randomNumber == 1) {
// Quote from Ten
quote = mTen.getQuote();
}
else if (randomNumber == 2) {
// Quote from Eleven
quote = mEleven.getQuote();
}
else {
quote = "Error";
}
return quote;
}
public void animateDoctor() {
ImageView imageView=null;
if (randomNumber == 0) {
imageView=mImageView1;
}
else if (randomNumber == 1) {
imageView=mImageView2;
}
else if (randomNumber == 2) {
imageView=mImageView3;
}
AlphaAnimation fadeInAnimation = new AlphaAnimation(0, 1);
fadeInAnimation.setDuration(1500);
fadeInAnimation.setFillAfter(true);
imageView.setAnimation(fadeInAnimation);
}
}

Shrinking the Code

I've got some java code that is used for my games NPCs to move arround.
Those are obviously in an 1d array.
public void route11() {
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random ==1)
hunters[1].x = hunters[1].x -1;
else
hunters[1].y = hunters[1].y -1;
}
public void Update() {
route11();
route2();
route3();
route4();
route5();
}
Methods route2, route3, ..., route5 look pretty much the same, the only thing that changes is the value of the array to correspond with a different hunter.
Could this code be "shrinked"? Im pretty sure my lecturer will be happy to minus my mark for such a messy and very much anti-OO code.
Also, all my collision/score code looks something like this, and it works for individual hunters:
if(hunters[i].x==0 && hunters[i].y == 0){
hunters[i].x = 11;
hunters[i].y = 11;
Player.score = Player.score + 1;
}
Your issue has nothing to do with OOP design. This is just about learning to use the tools available to write less redundant and more manageable code. If you utilize a for loop in your update and pass each individual hunter then this becomes much more condensed.
I will note that there are some unrelated OOP issues that you would do well to correct.
Hunter's members such as X and Y should not be exposed publicly, utilize getters/setters
The same goes for the Player's score member/field
public void update()
{
for(var i = 0; i < 5; i++)
{
route(hunters[i]);
collisionAndScoring(hunters[i]);
}
}
public void route(Hunter hunter)
{
Scanner in = new Scanner(System.in);
Random number = new Random();
int random = number.nextInt(2);
if(random == 1)
{
hunters.x--;
}
else
{
hunter.y--;
}
}
public void collisionAndScoring(Hunter hunter)
{
if (hunter.x == 0 && hunter.y == 0) //You should define constants for these to give them more meaning
{
hunter.x = 11; //another opportunity for a constant
hunter.y = 11; //another opportunity for a constant
Player.score++;
}
}

Categories

Resources