I wonder how to set probability of something happens based on a variable.
Let's say:
var a = "5235235";
var b = "5235235";
var rand = Math.random();
if (rand < 0.3) {
console.log("30% chance");
} else {
console.log("70% chance");
}
I have tried the percentage chances like so, but I don't really know how to set for example 70% chance of something happened if variable a is equal to variable b. Any ideas?
Use a variable to hold the percentage, instead of hard-coding it, then assign it depending on the condition.
var pct = 0.3;
if (a == b) {
pct = 0.7;
}
var rand = Math.random();
if (rand < pct) {
console.log("Success!");
} else {
console.log("Failure. :(");
}
okay so if you want two mutually exclusive events with one occurring 30% of the time and the other occurring 70% of the time, then
chance = random.randint(1,100)
if chance <= 30:
print "30% chance of getting this"
elif chance <= 70:
print "70% change of getting this"
Related
I'm trying to make a simple rolling the dice mechanic with probabilities, if pass the level increase, if fail it decrease and if destroyed usually it resets to a certain level, but I'm having a hard time getting the right results, I am not sure if the outcome is supposed to be like this and just my intuition is wrong or something is actually messing it up.
Basically I am making a while loop that while below certain level it will roll the dice and given the results it will do something accordingly to the rates I input (40% for pass, 59.4% for fail and 0.6% to destroy). But when I do a test with 1000 tries, it always return me an average of destroyed way higher than 0.6%. I don't know if my test function is wrong, if the way I'm testing is wrong, if something on my loop is messing up the probabilities outcome.
function checkPass(successRate, failRate, destroyRate) {
let number = Math.random();
if (number < successRate) {
return 1;
} else if (number < failRate) {
return 0;
} else {
return 2;
}
}
function starforceSim(itemLevel) {
let newObj = {"level": 10, "totalMeso": 0, "destroyed": 0};
while (newObj.level < 11) {
if (newObj.level == 10) {
let passOutcome = checkPass(0.4, 0.994, 1)
if (passOutcome == 1) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.level = newObj.level + 1;
} else if (passOutcome == 0) {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
//newObj.level = newObj.level - 1;
} else {
//newObj.totalMeso = newObj.totalMeso + (Math.round(1000 + (Math.pow(itemLevel, 3)) * (Math.pow(newObj.starlevel + 1, 2.7)) / 400));
newObj.destroyed = newObj.destroyed + 1
}
}
}
return newObj;
}
let counter = 0;
for (i=0; i<1000; i++) {
let n = starforceSim(140);
if (n.destroyed > 0) {
counter++
}
}
console.log(counter);
I disabled the decrease level when it fails just to focus on the destroy rates.
Is there a better way to code probabilities or to test them? Is there something wrong with my code?
Math.random is only pseudo-random1
1Source
This means you may not get a perfectly uniform distribution. In my own fiddling, it seems like randomness might get worse if you generate many values in rapid succession [citation needed].
If you want a better source of randomness, check out Crypto.getRandomValues.
I don't see anything wrong with your code. I think your expectations are just off. To verify that this is caused by lame randomness, take David Tansey's advice and study just the randomness output.
You may also notice different randomness quality in different browsers (or, different Javascript engines).
I am building a hot and Cold App in JS and jQuery.
My issue is on form submit that user input inserts a number and the game tells them if its hold or cold or hotter or holder based on how close or far from the number.
Issue is that It only works the first time. After that it does nothing.
How do I made it so that when the user input on submit it generates a new secretNumber and based on the checker I have setup outputs either hot or cold or hotter or colder.
Seems its not generating a new secret number or it is just not inputing it.
Code here http://codepen.io/mackenzieabby/pen/qOXNLg
JS
$(document).ready(function(){
// Global Variables.
var theSecret = Math.floor((Math.random() * 100) + 0); // Creates Secret Number
var userGuess = $('#userGuess').val(); // User Inut Guess
var count = 0;
var addList = document.createElement("li")
// Display information modal box
$(".what").click(function(){
$(".overlay").fadeIn(1000);
});
// Hide information modal box
$("a.close").click(function(){
$(".overlay").fadeOut(1000);
});
// Functions
// New Game
function newGame() {
// new gama data here
}
// Add To List
function addtoList() {
}
function preventRefresh() {
$("form").submit(function(event) {
event.preventDefault();
theSecret();
veryHotGuess();
hotGuess();
veryColdGuess();
coldGuess()
correctAnswer();
});
}
preventRefresh();
function addGuess() {
$("ul#guessList").append("<li>" + userGuess + "</li>");
}
// Checks if hot or cold or correct
function veryHotGuess() {
if (userGuess < 25 && theSecret < 25) {
document.getElementById('feedback').innerHTML = "Very Hot";
}
}
function hotGuess() {
if (userGuess < 50 && theSecret < 50) {
document.getElementById('feedback').innerHTML = "Hot";
}
}
function veryColdGuess() {
if (userGuess < 100 && theSecret < 100) {
document.getElementById('feedback').innerHTML = "Very Cold";
}
}
function coldGuess() {
if (userGuess < 75 && theSecret < 75) {
document.getElementById('feedback').innerHTML = "Cold";
}
}
function correctAnswer() {
if (userGuess == theSecret) {
document.getElementById('feedback').innerHTML = "You Got It";
}
}
});
Calling theSecret(); causes a JavaScript error. You are calling the variable as a function, which it isn’t obviously.
BTW, I think your calculation of guess "temperature" might be quite wrong.
You have to redefine your definition of Global variable in javascript:
$(document).ready(function(){
// Global Variables.
var theSecret = Math.floor((Math.random() * 100) + 0); // Creates Secret Number
var userGuess = $('#userGuess').val(); // User Inut Guess
var count = 0;
var addList = document.createElement("li")
...
those ARE NOT global variables, because you made then in a scope, the document.ready scope... a Global Variable must be defined outside any scope, so it's available in all scopes, including inside the document.ready as well inside any function method you wrote.
Secondly, you need to rethink what you are doing, as a rule, you are repeating yourself over and over with
document.getElementById('feedback').innerHTML = xxxx;
one day you need to change the feedback to something else, or also write something else, can you see in how many places you need to change your code? When you see several lines of almost the same code: You're doing it wrong...
And you need to simplify your calculations, you make it hard to code and see what's going on...
Third, as Alexander pointed out, you need to re-think how you're calculating, what you want to calculate if not the userGuess or the theSecret, but give an answer based on how close/far the user guess is from the correct value ... that I would call it the difference between 2 numbers.
something like: Math.abs(theSecret - userGuess)
Here's my approach:
http://codepen.io/anon/pen/wKqzvg?editors=001
(irrelevant code removed)
var theSecret = 0,
guesses = [];
$(document).ready(function() {
// Creates Secret Number
theSecret = Math.floor((Math.random() * 100) + 0);
$("form").submit(function(evt) {
evt.preventDefault();
checkTemperature();
});
});
// Functions
// Add To List
function addToList(txt) {
guesses.push(txt);
$("#count").text(guesses.length);
$("ul#guessList").append("<li>" + txt + "</li>");
}
function write(txt) {
document.getElementById('feedback').innerHTML = txt;
}
function checkTemperature() {
var userGuess = parseInt($('#userGuess').val()),
dif = Math.abs(theSecret - userGuess);
// for debug only
console.log("theSecret:" + theSecret);
console.log("userGuess:" + userGuess);
console.log("dif:" + dif);
addToList(userGuess);
if (dif < 5)
write("Vulcan Hot");
else if (dif < 25)
write("Very Hot");
else if (dif < 50)
write("Hot");
else if (dif < 75)
write("Cold");
else if (dif < 100)
write("Very Cold");
else if (dif === 0)
write("You Got It");
}
The problem isn't with theSecret but with userGuess. You were not grabbing the value on submit so it was empty. I suggest to always console.log or inspect variables to make sure they are getting populated correctly. In your submit I added this: userGuess = $('#userGuess').val(); and it will now check correctly.
However, as Alexander mentioned the math is wrong. The value will always be under 100 and so it will always be Very Cold. You have to get the absolute difference of both numbers and then do your guess check:
var difference = Math.abs(theSecret - userGuess);
if (difference < 100) {
document.getElementById('feedback').innerHTML = "Very Cold";
}
if (difference < 75) {
document.getElementById('feedback').innerHTML = "Cold";
}
if (difference < 50) {
document.getElementById('feedback').innerHTML = "Hot";
}
if (difference < 25) {
document.getElementById('feedback').innerHTML = "Very Hot";
}
if (difference == 0) {
document.getElementById('feedback').innerHTML = "You Got It";
}
I forked your project here: http://codepen.io/paulmg/pen/xwLExM
I'm writing a program in JS and im feeling i'm repeating code, which is not good. I'm trying to avoid an if then else block that has two similar for loop and re-write it without an if then else using just one for loop.
Consider this: minimum has value 0. maximum has value 10. if new_value is less than old_value i wanna execute a for loop from minimum to new_value, else i wanna execute it from maximum DOWNto new_value
Lets see it in action, lets say javascript (language-agnostic answers are welcome and upvoted -but will not grant you an extra cookie)
var minimum = 0;
var maximum = 10;
var old_value = 5;
/* var new_value = taken from user input whatever ... */
if(new_value<old_value)
{
for(i=minimum;i<new_value;i++)
{
// whatever
}
}
else
{
for(i=maximum;i>new_value;i--)
{
// whatever
}
}
I have a feeling these two for loops are similar enough to be written as one in a mathematical approach maybe. Have tried a bit using absolute values Math.abs() Math.max.apply() but had no luck.
I don't want to set other helping variables using if then else to give appropriate values.
So, whats the question: I'm wondering if this can be rewritten in one for ... loop without being nested in an if then else.
A complete solution using built-in js functions will grant you an extra cookie.
Edit: Didn't see your original thing about not using the if/else with variables. Why not do something like this then? Just go from 0 to 10, using that value or 10 minus that value depending on the conditional.
for(var j = 0; j <= 10; j++) {
var i = new_value < old_value ? j : 10 - j;
// whatever
}
Assign your min, max and increment as variables, define them based on your if condition and then use them in the for loop:
var old_value = 5, start, end, inc;
if(new_value<old_value) {
start = 0;
end = 10;
inc = 1;
} else {
start = 10;
end = 0;
inc = -1;
}
for( i = start;i >= start && i <= end; i += inc) {
// whatever
}
You could abuse of the ternary operator just for fun:
var minimum = 0;
var maximum = 10;
var old_value = 5;
var new_value = 7;
/* var new_value = taken from user input whatever ... */
var check =(new_value<old_value);
var foo1 = function () { console.log("foo1") }
var foo2 = function () { console.log("foo2") }
for(i=check?minimum:maximum;
check?(i<new_value):(i>new_value);
check?i++:i--)
{
check?foo1():foo2();
}
Does the second loop have to iterate in reverse? If not you can simply use
var i0 = new_value<old_value ? minimum : new_value+1;
var i1 = new_value<old_value ? new_value : maximum+1;
for(i=i0;i<i1;++i)
{
//whatever
}
Edit: In the light of your comment, if you can be sure that you're dealing with integers you can use
var i0 = new_value<old_value ? minimum : maximum;
var d = new_value<old_value ? 1 : -1;
for(i=i0;i!=new_value;i+=d)
{
//whatever
}
If not
var i0 = new_value<old_value ? minimum : maximum;
var d = new_value<old_value ? 1 : -1;
for(i=i0;d*i<d*new_value;i+=d)
{
//whatever
}
I did it!
With this +(old_value>new_value) instead of getting true/false i am getting 1/0. I am using the 1 and 0 as multipliers to emulate the if then else functionality.
lets assume
var minimum = 0;
var maximum = 10;
var old_value = 5;
for(expression1;expression2;expression3)
For expression1:
if new value is bigger than old value then we need minimum
if new value is smaller than old value then we need maximum
I am multiplying be zero the maximum depending the above conditions with (maximum*(+(old_value>new_value)))
I am multiplying by zero the minimum depending the above conditions with (minimum*(+(old_value<new_value))
by adding these two the sum is what i am supposed to get! (maximum*(+(old_value>new_value)))+(minimum*(+(old_value<new_value)))
This will give minimum if new_value > old value and maximum if new_value < old_value
For expression2:
while i!=new_value; simple. (we just have to be sure the maximum is bigger than new_value and minimum is smaller than new_value or we have an endless loop.)
For expression3:
if new value is bigger than old value then we need i=i +1
if new value is smaller than old value then we need i=i -1
this
(+(old_value<new_value)+1)+(-1*(+(old_value>new_value)+1))
will give either 2+-1=1 or 1+(-2)=-1 so we simply use it in expression3 as
i=i+(+(old_value<new_value)+1)+(-1*(+(old_value>new_value)+1))
complete code:
http://jsfiddle.net/eBLat/
var minimum = 0;
var maximum = 10;
var old_value = 5;
var new_value = 3; // change this value
// if new value is bigger than old value then for loop from maximum downto new_value (dont include new value)
// if new value is smaller than old value then for loop from minimum upto new_value (dont include new value)
for(i=(maximum*(+(old_value>new_value)))+(minimum*(+(old_value<new_value)));i!=new_value;i=i+(+(old_value<new_value)+1)+(-1*(+(old_value>new_value)+1)) )
{
alert("Iteration:"+i);
}
Another question would be if this is actually better than just write two for in a if then else ... anyway i had fun. And i got the cookie :D :D
Hope someone will find useful in some way the fact that +true gives 1 and +false gives 0 in javascript
okay i guys i just got into java script and i made a simple game it works and does everything i wanted but now i want to make it difficult so that every time the enemy health is 0 it refill but comes back stronger as in it has more health this is what i came up with this is the part that makes it refill it adds 100 but only stays 200 when it refills i want it to increase by 100 every time it becomes 0
if (enemyHealth<=0) {
enemyHealth=0;
alert("you win");
gold=gold+500;
document.FGame.Output.value=gold;
enemyHealth=100+100;
}
It's because you always set the enemyHealth to 100 + 100, which will always equal 200. What you could do is to have a totalEnemyHealth variable which increase by 100 every time the enemy dies. When you revive that enemy, you would set it's health to the new totalEnemyHealth value.
//make sure not to re-initialize this variable every time
var totalEnemyHealth = 100;
//then in your function
if (enemyHealth<=0){
enemyHealth = totalEnemyHealth += 100;
alert("you win")
gold=gold+500;
document.FGame.Output.value=gold;
}
However if you have multiple ennemies, that approach will not give the desired results. To solve your problem you will need something more object-oriented, such as all ennemies represented by an Enemy instance, where the instance would have the capability of tracking how many times it died and use this as a health multiplier.
Simple example:
var Enemy = {
baseHealth: 100,
health: 100,
deathCount: 0,
takeDamage: function (amount) {
if ((this.health -= amount) <= 0) {
this.die();
this.respawn();
}
},
die: function () {
this.deathCount++;
},
respawn: function () {
this.health = (this.deathCount + 1) * this.baseHealth;
}
};
var someEnemy = Object.create(Enemy);
console.log(someEnemy.health); //100
someEnemy.takeDamage(150); //violent attack
console.log(someEnemy.health); //200
Here is an example:
http://jsfiddle.net/9zhqg/1/
var gold = 0;
for(i = 0; i < 20; i++){
var num = Math.floor(Math.random()*10);
var enemyHealth = num *i;
if (enemyHealth<=0){
//enemyHealth=0
alert(i + "you win")
gold+= 500;
//document.FGame.Output.value=gold;
enemyHealth += 100
alert(enemyHealth);
}
}
You can see when it runs, the number of times it hit 0 out of a for loop of 20 times. Then it bounces the health back to 100. I think this is what you need. - not 100% sure if I understand your use case.
You could just add a counter. Something simple like:
var counter=1; //at start of game
if (enemyHealth<=0)
{
enemyHealth=0
alert("you win")
gold=gold+500;
document.FGame.Output.value=gold;
enemyHealth=100+(100*counter);
counter++;
}
Here is the assignment so it's clear what I'm trying to do.
Write a program that calculates the price of a hotel room based on three factors. First, how many will be in one room: 1-2, 3-4, or 5-6? No more than six are allowed in a room. Second, are the guests members of AAA? Third, do they want a room with a view? The rate is calculated as follows:
Basic room rate is:
1-2 people = $50/night
3-4 people = $60/night
5-6 people = $70/night
There is a discount for AAA members off of the basic room rate per night:
1-2 people = 15%
3-4 people = 10%
5-6 people = 5%
A room with a view costs 10% more per night after all other calculations are performed.
The program should prompt the user for all the inputs, perform the calculations and output the total cost per night. It is suggested to use at least some nested if/else structures to calculate the cost.
Debuggers like firebug and JSLint haven't been any help and I suspect I'm just doing something completely wrong, though I haven't had trouble with "nested if" logic assignments before. Regardless I am a complete and utter newby.
When I test by inputting 1 for numberOfGuests, N for tripleAStatus, and N for roomView, finalRate is returning as isNaN (I know this means not a number), and I can't figure out why.
//Variable Declaration
var numberOfPeople;
var tripleAStatus;
var roomView;
var discountRate;
var roomRate;
var finalRate;
var discountPercent;
//Input
numberOfPeople = prompt("How many guests will their be? 6 Maximum.");
tripleAStatus = prompt("Are you a AAA Member? Y/N.");
roomView = prompt("Would you like your room to have a view?");
//Logic
if ((numberOfPeople <= 2) && (numberOfPeople > 0)) {
roomRate = 50;
discountPercent = .15;
} else if ((numberOfPeople <= 4) && (numberOfPeople > 2)) {
roomRate = 60;
discountPercent = .10;
} else if ((numberOfPeople <= 5) && (numberOfPeople > 4)) {
roomRate = 70;
discountPercent = .5;
} else {
alert("Your number of guests must be at least 1 and no more than 6");
}
if (tripleAStatus = "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus = "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
if (roomView = "Y") {
finalRate = (discountRate) + ((discountRate) * .10);
} else if (roomView = "N") {
finalRate = discountRate;
} else {
alert("You need to answer with either Y or N");
}
//Output
document.write("Total cost per night is " + "$" + finalRate);
It looks like
discountRate = roomRate - (roomRate * discountRate);
Should read
discountRate = roomRate - (roomRate * discountPercent);
Which is why you're getting NaN in finalRate; discountRate hasn't been defined at this point, so your code actually reads discountRate = 1 - (1 * undefined).
As other posters have mentioned, you also need to change your conditionals to use == or ===; = is an assignment operator, so rather than checking if tripleAStatus is "Y", you're actually checking if "Y" evaluates to true (which it always will).
tripleAStatus = 'N';
if (tripleAStatus = 'Y') {
// tripleAStatus is now "Y", and the code inside this if will always be executed
}
Working changes: http://jsfiddle.net/5ZVkE/
In your If statements, you are assigning values by using single "=". Since the assignment always occurs, it will return true. In order to compare values, you need to use double "==" in the if statement. like this:
if (tripleAStatus == "Y") {
discountRate = roomRate - (roomRate * discountRate);
} else if (tripleAStatus == "N") {
discountRate = roomRate;
} else {
alert("You need to answer with either Y or N");
}
Replace the single '=' in your 'if' statements with '=='. You're currently using assignment operators instead of equality.
e.g.:
if (tripleAStatus == "Y") ...
You are using assignments instead of equality operators in your if statements. i.e. change
if (tripleAStatus = "Y")
to
if (tripleAStatus == "Y")
Please use ===!! this way, the type in the statement isn't casted and therefor more strictly checked if its the same type.
if (tripleAStatus === "Y") {
discountRate = roomRate - roomRate * discountRate;
} else if (tripleAStatus === "N") {
discountRate = roomRate;
}
/e -> & its faster!
prompt() returns a STRING not a NUMBER.
Use parseInt() with numberOfPeople.
And the other problem, you copied and pasted the wrong variable names in your formulas. Look at how you are using discountRate instead of discountPercent.