The output of my password generator is less than desired - javascript

I'm trying to make a password generator for a coding bootcamp but I'm running into an issue that has 2 outcomes both of which aren't desired. The HTML is very basic and I'm supposed to use prompts for the selection. I included my code but took out a few unnecessary things, the other 14 if-else statements, and a few variables. I'm turning in the project with the ugly formatting and spaces but still would like to know where I went wrong. The two outcomes are
The selections won't be unique and instead use the same character over and over
It comes out looking sloppy and adds spaces into it
function randomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
//random uppercase from character code
function randomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
//random number from character code
function randomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48);
}
// random symbol from character code
function randomSymbol() {
let symbol = "!##$%^&*()_-><[]}{";
return symbol[Math.floor(Math.random() * symbol.length)];
}
// Get references to the #generate element
var generateBtn = document.querySelector("#generate");
// Write password to the #password input
function writePassword() {
var password = generatePassword();
var passwordText = document.querySelector("#password");
passwordText.value = password;
}
// Add event listener to generate button
generateBtn.addEventListener("click", writePassword);
// function for generatePassword
function generatePassword() {
//Confirms # of characters needed
click = parseInt(prompt("How many characters?", "8-128"));
if (!click) {
alert("Input is needed");
//Ensures the character count isn't too high or low
} else if (click < 8 || click > 128) {
click = parseInt(prompt("Answer must be between 8 and 128"));
} else {
//The procedding few lines will confirm other variables
useNumbers = confirm("Include numbers?");
useLower = confirm("Include lowercase letters?");
useUpper = confirm("Include uppercase letters?");
useSymbol = confirm("Include special characters?");
}
//If all prompts are denied
if (!useLower && !useUpper && !useNumbers && !useSymbol) {
choices = alert("At least one option is needed");
//If all prompts are accepted
} else if (useLower && useUpper && useNumbers && useSymbol) {
choices = randomLower().concat(randomUpper, randomNumber, randomSymbol);
//code only makes repeating characters
//choices = randomLower().concat(randomUpper(), randomNumber(), randomSymbol())
//placeholder for an array for user choices
var pWord = [];
//for loop to randomize selection
for (let i = 0; i < click; i++) {
var selected = choices[Math.floor(Math.random() * choices.length)];
pWord.push(selected);
}
//.join will take all choices in the array pWord and turns it into a string
var pass = pWord.join("");
UserInput(pass);
return pass;
}
// This puts the new password into the textbox
function UserInput(pass) {
document.getElementById("password").value = pass;
}

You only set choices if the user selects all the options.
When you set choices, you don't call the functions in the arguments to concat(). So you're concatenating the function definitions, not the random letters returned by the functions.
Even if you fix that to call the functions, you'll just get 4 characters. You need to call the randomXXX functions in the loop that generates each character.
In my code I've made choices an array of functions, not characters. I add each function to the array conditionally from the prompts. Then the loop picks a random function first, and calls it to get a random character of that type.
// function for generatePassword
function generatePassword() {
//Confirms # of characters needed
let click = parseInt(prompt("How many characters?", "8-128"));
let choices = [];
if (!click) {
alert("Input is needed");
//Ensures the character count isn't too high or low
} else if (click < 8 || click > 128) {
click = parseInt(prompt("Answer must be between 8 and 128"));
} else {
//The procedding few lines will confirm other variables
if (confirm("Include numbers?")) {
choices.push(randomNumber);
}
if (confirm("Include lowercase letters?")) {
choices.push(randomLower);
}
if (confirm("Include uppercase letters?")) {
choices.push(randomUpper);
}
if (confirm("Include special characters?")) {
choices.push(randomSymbol);
}
}
//If all prompts are denied
if (choices.length == 0) {
alert("At least one option is needed");
return;
}
//placeholder for an array for user choices
var pWord = [];
//for loop to randomize selection
for (let i = 0; i < click; i++) {
let selected = choices[Math.floor(Math.random() * choices.length)];
pWord.push(selected());
}
//.join will take all choices in the array pWord and turns it into a string
var pass = pWord.join("");
return pass;
}
console.log(generatePassword());
function randomLower() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 97);
}
//random uppercase from character code
function randomUpper() {
return String.fromCharCode(Math.floor(Math.random() * 26) + 65);
}
//random number from character code
function randomNumber() {
return String.fromCharCode(Math.floor(Math.random() * 10) + 48);
}
// random symbol from character code
function randomSymbol() {
let symbol = "!##$%^&*()_-><[]}{";
return symbol[Math.floor(Math.random() * symbol.length)];
}

Im writing the same pattren as per passwords generators website. you can add this javascript in your html. You can generate random alphanumeric strings in JavaScript using the following code:
function generateRandomString(length) {
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
var string_length = length || 8;
var randomstring = '';
for (var i=0; i<string_length; i++) {
var rnum = Math.floor(Math.random() * chars.length);
randomstring += chars.substring(rnum,rnum+1);
}
return randomstring;
}

Related

In which way I can validate a random password?

I wrote a code to generate a random password, but in which way i can check that in the password there is a number, uppercase, lowercase and special characters?
function randomPassword(length) {
var chars = "abcdefghijklmnopqrstuvwxyz!##$%^&*1234567890ABCDEFGHIJKLMNOPQRSTUVWYZ";
var pass = "";
for (var x = 0; x < length; x++) {
var i = Math.floor(Math.random() * chars.length);
pass += chars.charAt(i);
}
return pass;
}
Why not loop over the different sets of characters. Then you don't have to check it at all:
function randomPassword(length) {
var chars = [
"abcdefghijklmnopqrstuvwxyz",
"!##$%^&*",
"1234567890",
"ABCDEFGHIJKLMNOPQRSTUVWYZ"
];
var pass = "";
while (pass.length < length) {
chars.forEach(set => {
if(pass.length < length) {
var i = Math.floor(Math.random() * set.length);
pass += set.charAt(i);
};
});
};
return pass;
};
Every iteration of the while loop will add one character from each of the sets. We check the pass.length the second time to make sure we aren't going over the limit when in the middle of a while loop. You should probably also make sure you return early if the length parameter is less than 4.
Maybe you can leave the password like it is, but to make sure you have the four required characters (number, uppercase, lowercase and special characters), you can later add one of each. These can also be chosen at random.
What you need is RegEx. Here are a few examples:
https://www.thepolyglotdeveloper.com/2015/05/use-regex-to-test-password-strength-in-javascript/
https://gist.github.com/leandromoh/470b0b54208f02a9ba223cdbdd1534bd
https://www.w3schools.com/howto/howto_js_password_validation.asp
You could generate passwords untill you get one that satisfies RegEx which would be the most random way:
function randomPassword(length) {
var chars = "abcdefghijklmnopqrstuvwxyz!##$%^&*1234567890ABCDEFGHIJKLMNOPQRSTUVWYZ";
var pass = "";
for (var x = 0; x < length; x++) {
var i = Math.floor(Math.random() * chars.length);
pass += chars.charAt(i);
}
return pass;
}
function randomStrongPassword(length) {
const strongRegex = new RegExp(`^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{${length},})`)
let pass, valid
do {
pass = randomPassword(length)
valid = strongRegex.test(pass)
} while (valid !== true)
return pass
}
console.log(randomStrongPassword(8))
Or generate it like this and than randomize (I've added a test at end):
function randomPassword(length) {
const lower = 'abcdefghijklmnopqrstuvwxyz'
const upper = lower.toUpperCase()
const special ='!##$%^&*'
const numbers = '1234567890'
const characters = [lower, upper, special, numbers]
let pass = ""
for (var x = 0; x < length; x++) {
characters.forEach(e => {
const i = Math.floor(Math.random() * e.length)
pass += e.charAt(i)
})
}
const splice = Math.max(Math.floor(Math.random() * length) - length, 0)
return [...pass].splice(splice, length).sort(e => Math.random() - 0.5).join('')
}
console.log(randomPassword(10))
// Test password
const minLength = 8
const strongRegex = new RegExp(`^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!##\$%\^&\*])(?=.{${minLength},})`)
console.log(strongRegex.test(randomPassword(6)))
console.log(strongRegex.test(randomPassword(8)))

Why `Loop` write more than once

I try to create a guessed with javascript and this is the code:
<script>
function makeid(len)
{
var text = "";
//var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var possible = "abc";
for( var i=0; i < len; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
////////////////////////////////////////////
var password = 'abc';
var correctGuess = false
var guess;
do {
document.write(makeid(3) + "<br>");
guess = makeid(3);
if (guess === password) {
correctGuess = true;
}
} while ( ! correctGuess )
document.write("You know the secret password. Welcome.");
</script>
But unfortunately the result is repeated more than once :
The result:
abb baa aac cba cbb aba bbb aac acb cba ccc bab caa bab ccc aac ccb
aba abc bac cbb
This slows down the program,, how disband this problem
Is there a solution?
thank you
Since you want to not check the same password twice, generating random guesses is obviously not the right way to go. As klumme mentioned, storing an array of previous guesses would only increase time and space complexity, so that is also out. What you will have to do is use a brute force method, that is, trying every combination of characters until you get the correct answer. Here's how you can implement it:
NOTE: Keep in mind that brute force algorithms are typically pretty inefficient, and if you use the full alphanumeric string that you have in your original code to brute force passwords of more than 3-4 characters, it will take a significant amount of time (especially in a browser). JavaScript, by nature, is not an extremely powerful number crunching language - so this answer is more for the idea of it, than for use in most real-world environments.
function guesser(len) {
var arr = Array.apply(null, Array(len));
var propIndex = -1;
var indexes = arr.reduce(function(total, curr) {
propIndex++;
total[propIndex] = 0;
return total;
}, {});
var lastGuess = arr.map(function() {
return possible[possible.length - 1];
}).join("");
var guess = "";
var found = false;
while (guess !== lastGuess) {
guess = "";
for (var i = 0; i < propIndex; i++) {
// if on last char, reset to 0 and increment previous index start position
if (indexes[propIndex - i] >= possible.length) {
indexes[propIndex - i - 1]++;
indexes[propIndex - i] = 0;
}
}
for (var i in indexes) {
guess += possible[indexes[i]];
}
document.write(guess + "<br/>");
if (guess === password) {
found = true;
break;
}
// increment last char
indexes[propIndex]++;
}
if (found) {
document.write("You know the secret password. Welcome.");
} else {
document.write("Sorry, you do not know the secret password.");
}
}
var password = 'dcd';
var possible = "abcd";
guesser(password.length);
If I understand you correctly, the problem is that the random password function ("makeid") may return the same password several times. This is no surprise, there's no reason for the function to know which passwords have been tried already. You could keep track of already tried passwords and not try one if it has been tried before (as in Kind user's answer), but in this case it probably wouldn't speed up the program.
A better approach would probably be to iterate through the possible passwords systematically instead of randomly. For example, try "aaa" first, then "aab", "aac" "aba" and so on.
Here is something I came up with -- it's probably not very fast. I use an array of indices into the "possible" string until actually trying the password, because I don't wan't to mess around with indexOf() on the way.
const correctPassword = 'abc';
const possible = 'abc';
const maxIndex = possible.length - 1;
function next(previous) {
var i = previous.length - 1;
while (previous[i] === maxIndex) {
previous[i] = 0;
i--;
// All passwords have been tried.
if (i < 0) {
return [];
}
}
previous[i]++;
return previous;
}
var current = Array(3).fill(0);
var currentPassword;
while (current.length != 0) {
currentPassword = current.map(function (i) {
return possible[i];
}).join('');
document.write(currentPassword + '<br>');
if (currentPassword === correctPassword) {
document.write('You know the secret password. Welcome.');
break;
}
current = next(current);
}
First of all, store the results inside an array. Secondly, add a following condition: if (arr.indexOf(guess) == -1) - if the guessed number is already in the array - skip it.
function makeid(len) {
var text = "";
//var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var possible = "abc";
for (var i = 0; i < len; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
}
var password = 'abc';
var correctGuess = false;
var guess;
var arr = [];
while (!correctGuess) {
guess = makeid(3);
if (arr.indexOf(guess) == -1) {
arr.push(guess)
if (guess === password) {
correctGuess = true;
}
}
}
console.log(arr);
I got interested in this question and decided to use it as an opportunity to learn more about generators. Note: Uses ES6 syntax, so not necessarily compatible with all platforms.
I wouldn't necessarily recommend this over the other approaches already put in place, but it might be a good future reference.
/**
* Invoke `callback` with every possible combination of `elements` up to length of `length`, until `callback` returns `true`
* #param elements an array of elements to be passed to `callback`
* #param length the maximum number of elements to pass to `callback`
* #param callback a function taking an array of elements, that returns a boolean
* #returns the first combination of elements for which `callback(combination)` returns `true`. Returns undefined if no combination up to the specified `length` returns `true`.
*/
const combineAndCall = (elements = [], length = 0, callback) => {
const it = permuteIterator(elements, length);
for (const el of it) {
if (callback(el)) {
return el;
}
}
};
/**
* Returns a generator that returns permutations, with repeated elements, of an array. The maximum length of each permutation is `len`
* #param arr the array to iterate. The first iteration will always be the empty array.
*
* Example:
* const it = permuteIterator([1,2,3], 2);
* it.next().value; // []
* it.next().value; // [1]
* it.next().value; // [2]
* it.next().value; // [3]
* it.next().value; // [1,1]
* it.next().value; // [1,2]
* it.next().value; // [1,3]
* it.next().value; // [2,1]
* it.next().value; // [2,2]
* ...
* it.next().value; // [3,3]
*
* #len the maximum length of each permutation
* #returns a generator that iterates the array
*/
function *permuteIterator(arr, len) {
let current = [];
function *helper(current, arr, len) {
if (current.length >= len) {
yield current;
} else {
for (const el of arr) {
yield* helper([...current, el], arr, len);
}
}
}
for (let i = 0; i <= len; i++) {
yield* helper([], arr, i);
}
}
/**
* Validates a password
* #param elements an array of strings (usually single characters) to combine into a a single string, and compare against the password
* #returns true if the string resulting from `elements.join("")` exactly equals the real password, false otherwise
*/
const passwordValidator = (elements) => {
const guess = elements.join("");
//console.log("validating:", guess);
return guess === "abc";
};
const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
//const alphabet = "abc";
const elements = alphabet.split("");
const guessedPassword = combineAndCall(elements, 3, passwordValidator);
if (guessedPassword) {
console.log(`You know the secret password '${guessedPassword.join("")}'. Welcome.`);
} else {
console.log("You don't know the secret password. Rejected.");
}

Split a variable using mathematical equations in javascript

I have two questions actually.
What I want to do is 1st to check if the user entered value is a correct mathematical equation. For example, if the use enters x + y ( z this should detect as an invalid formula and x + y ( z ) as a correct one,
The 2nd thing I want to do is to split the formula from the + - * / () signs, so the above formula will be return as x, y, z.
What I have done is bellow
var arr = [];
var s = 'x + y ( z )';
arr = s.split("(?<=[-+*/])|(?=[-+*/])");
console.log(arr);
This returns a single array with just one data like, [x + y ( z )]
Another thing, the variables are not single letters. they could be
words like, annual price, closing price, etc
Can someone help me in this problem. Thanks in advance
UPDATE : I have tried "/[^+/*()-]+/g" also
For the second part:
var s = 'x + y ( z )';
var arr = s.match(/(\w)/g);
console.log(arr);
document.write(JSON.stringify(arr));
Of course, you have to check the validity of the input first.
Edit: using Tomer W's answer suggesting eval():
function checkExpression(str) {
// check for allowed characters only
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(s) != null)
return false;
// extract variable names, assuming they're all one letter only
var arr = s.match(/(\w+)/g);
// instantiate the variables
arr.forEach(function (variable) {
eval(variable + '= 1');
});
// ( is alone, replace it by * (
str = str.replace(/\(/g, '* (');
try {
eval(str);
return true;
}
catch (ex) {
console.log(ex);
return false;
}
}
It's dirty but it works most of the time (Tomer W pointed some edge cases like ++62+5 or 54++++6 that can be avoided with an another regex check), do you have more complicated example to test?
Word of warning
VERY VERY VERY DANGEROUS METHOD AHEAD !!!
I am posting this as it is a valid answer, but you should do it only with extreme caution as a user can totally mess up your site.
DO not let the one user input be used in eval for another user !!! EVER !!!
Actual answer
You can use the built-in java-script compiler of your browser, and use eval()
function checkEq(equ)
{
for(ch in equ){
// check that all characters in input are "equasion usable"
if(" +-*/1234567890e^&%!=".indexOf(ch) === -1)
{ // if there are invalid chars
return false;
}
}
try{
// try running the equ, will throw an exception on a syntax error.
eval(equ);
return true; // no exception
}
catch(ex){
return false; // syntax error
}
}
Plunker example
and as i noted before! extreme caution!
Using both #ShanShan and #Tomer W answers, I wrote a formula validator. the code is bellow. In this validator, I checks for opening and closing brackets, extra / * - + signs, unwanted symbols, etc.
If the user wants to create and validate a formula with x,y,z
variables, user have to add the variables to an array and pass it to
this validator with the formula written so the validator accepts the
variables which are not numbers.
I also used a custom set mentioned in this post. https://stackoverflow.com/a/4344227/918277
Important : This java script function can't validate very complex formulas with sin, cos, tan, log, etc. Script will identify them as just letters and will return false.
function StringSet() {
var setObj = {}, val = {};
this.add = function(str) {
setObj[str] = val;
};
this.contains = function(str) {
return setObj[str] === val;
};
this.remove = function(str) {
delete setObj[str];
};
this.values = function() {
var values = [];
for ( var i in setObj) {
if (setObj[i] === val) {
values.push(i);
}
}
return values;
};
}
/**
*
* #param _formulaInputs
* Array of use entered inputs to be use in formula
* #param _formula
* User entered formula
* #returns {Boolean}
*/
function validateFormula(_formulaInputs, _formula) {
var formula = _formula;
var bracketStack = new Array();
var formulaDescArray = [];
var formulaDescInForm = new StringSet();
for (var i = 0; i < _formulaInputs.length; i++) {
formulaDescInForm.add(_formulaInputs[i]);
}
/* Regex to check for unwanted symbols(! # # $ etc.) */
if (/[^\w\d\(\)\+\*\/\-\s]/.exec(formula) != null) {
return false;
}
for (var i = 0; i < _formula.length; i++) {
if ((_formula.charAt(i) == '/' || _formula.charAt(i) == '*'
|| _formula.charAt(i) == '-' || _formula.charAt(i) == '+')
&& (_formula.charAt(i + 1) == '/'
|| _formula.charAt(i + 1) == '*'
|| _formula.charAt(i + 1) == '-' || _formula
.charAt(i + 1) == '+')) {
return false;
}
}
var lastChar = formula.charAt(formula.length - 1);
if (lastChar == '/' || lastChar == '*' || lastChar == '-'
|| lastChar == '+') {
return false;
}
formulaDescArray = formula.split(/[\/\*\-\+\()]/g);
/* Remove unwanted "" */
for (var i = 0; i < formulaDescArray.length; i++) {
if (formulaDescArray[i].trim().length == 0) {
formulaDescArray.splice(i, 1);
i--;
}
}
/* Remove unwanted numbers */
for (var i = 0; i < formulaDescArray.length; i++) {
if (!isNaN(formulaDescArray[i])) {
formulaDescArray.splice(i, 1);
i--;
}
}
for (var i = 0; i < formulaDescArray.length; i++) {
if (!formulaDescInForm.contains(formulaDescArray[i].trim())) {
return false;
}
}
for (var i = 0; i < formula.length; i++) {
if (formula.charAt(i) == '(') {
bracketStack.push(formula.charAt(i));
} else if (formula.charAt(i) == ')') {
bracketStack.pop();
}
}
if (bracketStack.length != 0) {
return false;
}
return true;
}

JavaScript regexp?

This is the regexp:
$("#newpassword").keyup(function(e) {
var htm = "";
var pass = this.value;
var length = this.value.length;
if (pass) {
var score = 0;
if(length >= 8 && length <= 16) { //PASSWORD MIN/MAX NUMBER OF CHARACTERS
var upper = /[A-Z]/;
var lower = /[a-z]/;
var number = /^[0-9]+$/; //PATTERN FOR NUMBERS
var schar = /[!##$%^&*?_~+-=<>]/;
//LOOPS THROUGH PASSWORD TO CHECK FOR AT LEAST ONE OF EACH PATTERN
for (i = 0; i < length; i++) {
if (pass.substr(i, 1).match(upper)) {
var uletters = true;
score ++;
//AT LEAST ONE LETTER EXISTS
}
if(pass.substr(i,1).match(lower)) {
var lletters = true;
score++;
//AT LEAST ONE LETTER EXISTS
}
if(pass.substr(i,1).match(schar)) {
var schar = true;
score++;
}
if(pass.substr(i, 1).match(number)) {
var numbers = true;
var schar = false;
//AT LEAST ONE NUMBER EXISTS
score++;
}
}
}
}
});
The any two condition is true means password is ok, but the above code if(numbers == true && schar == true) user type only number display password ok.
Please help me what is the problem in my code.
You don't need to iterate over each character of your password, just do the following:
score += upper.test(password)?1:0;
score += lower.test(password)?1:0;
score += number.test(password)?1:0;
score += schar.test(password)?1:0;
(test returns true or false) and check the score afterwards.
In general it's recommendable not to be too restrictive about the users password. It seriously harms the user experience if they are told to how their password should look like. You can make it a recommendation though. (E.g. display a bar: weak (red) - strong (green) password. This is much more motivating than harassing the user with any error messages.) Let them pass on score 2 and higher.
You can probably use RegExp.test() or RegExp.exec() to "find" a regex match within your string, rather than iterating the characters yourself.
function validatePwd (pwd) {
if (pwd.length < 8)
return false;
if (pwd.length > 16)
return false;
var upperPatt = /[A-Z]/;
var lowerPatt = /[a-z]/;
var numberPatt = /[0-9]/; // FIXED -- this is a better pattern for numbers.
var scharPatt = /[!##$%^&*?_~+-=<>]/;
score = 0;
if (upperPatt.test( pwd))
score++;
if (lowerPatt.test( pwd))
score++;
if (numberPatt.test( pwd))
score++;
if (specialPatt.test( pwd))
score++;
// don't make it too hard for the poor user, please..
// -- they have to type all this horrible rubbish.
if (score < 3) {
return false;
}
// OK.
return true;
}

How to make a .replace loop in javascript?

I am currently trying to make a .replace function loop in javascript. What I am trying to do is replace a random character with a hyphen, but the part that I am struggling with is how to make it loop the replacing of the character to hyphen. Here is the code that I have so far:
var randHold;
var randomWord;
var randLetHold;
var dispWord;
var repLetHold;
var myWords = new Array("Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"); // random letters to make words that have more than 10 letters
function level() {
randHold = parseInt((Math.random() * 6) + 1);//code to randomly pick a word from the above array
randomWord = myWords[randHold]; //code to call the random word from the array
randLetHold = (Math.random() * randomWord.length);//code to randomly pick a character from the random word chosen
repLetHold = randomWord.charAt(randLetHold);//code to call the random character
for (i = 1; i <= 3; i++) //loop to replace three random characters with a hyphen
{
dispWord = randomWord.replace(repLetHold," - ");//code to replace a random character with a hyphen
document.write(dispWord);//But all this does is display the word(with ONE hypenated character)three times.
}
}
Your code actually seems fine, the main issue is that you're declaring your random variables outside of your for loop. Doing this will only generate them once for the entire loop. Try this instead:
var dispWord;
var myWords = new Array("Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"); // random letters to make words that have more than 10 letters
function level() {
for (i = 1; i <= 3; i++) //loop to replace three random characters with a hyphen
{
var randHold = parseInt((Math.random() * 6) + 1);//code to randomly pick a word from the above array
var randomWord = myWords[randHold]; //code to call the random word from the array
var randLetHold = (Math.random() * randomWord.length);//code to randomly pick a character from the random word chosen
var repLetHold = randomWord.charAt(randLetHold);//code to call the random character
dispWord = randomWord.replace(repLetHold," - ");//code to replace a random character with a hyphen
document.write(dispWord);//But all this does is display the word(with ONE hypenated character)three times.
}
}
For 3 random characters to be hyphenated in the word, you want something like this.
<div id="result"></div>
var myWords = ["Spectrometer", "Bandwagonjghvyjh", "jvjyvyvilvyjlvyv",
"fruitjjyvtyvjv", "seventctcvtv", "weathertfhtcthc",
"undercfxdtfv"]; // random letters to make words that have more than 10 letters
var randomWord;
var dispWord;
var repLetHold = [];
function uniqueCount(str) {
var unique = [];
Array.prototype.forEach.call(str, function (value) {
if (unique.indexOf(value) === -1) {
unique.push(value);
}
});
return unique.length;
}
function level() {
var randHold = Math.floor(Math.random() * myWords.length);
dispWord = randomWord = myWords[randHold];
if (uniqueCount(randomWord) > 2) {
var count = 0,
temp1,
temp2;
while (count < 3) {
temp1 = Math.floor(Math.random() * dispWord.length);
temp2 = dispWord.charAt(temp1);
if (temp2 !== "-" && repLetHold.indexOf(temp2) === -1) {
dispWord = dispWord.replace(new RegExp(temp2, "g"), "-");
repLetHold[count] = temp2;
count += 1;
}
}
}
document.getElementById("result").textContent = dispWord;
}
level();
console.log(randomWord, repLetHold);
on jsfiddle
If you use a regular expression, you can replace all instances at once with the g (global) flag. For example:
var str = "this is a mass Spectrometer, which is a Spectrometer to detect the spectra of different masses";
var replaced = str.replace(/Spectometer/g, 'something');
// "this is a mass something, which is a something to detect the spectra of different masses";
Just keep in mind that some characters must be escaped inside regular expressions.
http://jsfiddle.net/zt8mp/
If i got the question right:
randomWord.replace(new RegExp(repLetHold,'g')," - ")
replaces all occurences of repLetHold (as long as it is not made of special regex characters)

Categories