As the title reads, my javascript file won't append to a filtered list via a random generator function, for context it's being built in replit so perhaps its just a buggy bit of software on replits end, though I'm certain I've done something wrong and can't for the life of me figure out what. The main idea for this project is to have it randomly select an item from a list, append it to an empty list, then pass that string to an HTML textarea tag to be displayed as text.
Code in question:
var LowercaseList = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var NumList = ["1","2","3","4","5","6","7","8","9","0"];
var SpecialCharList = ["`","~","!","#","$","%","^","&","*","_","-","+","=","<",">","?","/"];
// Letter list ID's since I couldn't figure out how to run this using a database
var LetterIDList = [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];
// Number list ID's since I couldn't figure out how to run this using a database
var NumIDList = [1,2,3,4,5,6,7,8,9,10];
// Special character list ID's since I couldn't figure out how to run this using a database
var SpecialID = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
// Filtered Lists
var UpperFiltered = [];
var LowerFiltered = [];
var NumFiltered = [];
var SpecialFiltered = [];
// Global declarations of random number variables to grab values from intial lists
var UpperGenVariable;
var LowerGenVariable;
var NumGenVariable;
var SpecialGenVariable;
// Creates a basic password with 2 of each kind of character
function Basic () {
for (var i = 1; i < 2; i++) {
UppercaseGenerate();
}
for (var i = 1; i < 2; i++) {
LowercaseGenerate();
}
for (var i = 1; i < 2; i++) {
NumGenerate();
}
for (var i = 1; i < 2; i++) {
SpecialGenerate();
}
};
let passwordGen = document.getElementById("PasswordDisplay")
function UppercaseGenerate () {
var UpperFiltered = [];
UpperGenVariable = Math.random(0, LetterIDList.length);
for (var i = 0; i < LetterIDList.length - 1; i++) {
if (LetterIDList[i] == UpperGenVariable) {
appendItem(UpperFiltered, UppercaseList[i]);
}
};
console.log(UpperFiltered);
passwordGen.value = UpperFiltered
};
HTML textarea code:
<label style = "color:white;" for="PasswordDisplay">Your generated password ----></label>
<textarea readonly id="PasswordDisplay" name="PasswordDisplay" rows="10" cols="50">
Please select a password complexity setting
</textarea>
I changed how you generate the random number.
Also added the UppercaseList, added i <= 2 rather then i < 2 in the cycles so the yould really run 2 times, added += to passwordGen.value += UpperFiltered so the value would add up.
I guess that is it.
var UppercaseList = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var LowercaseList = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var NumList = ["1","2","3","4","5","6","7","8","9","0"];
var SpecialCharList = ["`","~","!","#","$","%","^","&","*","_","-","+","=","<",">","?","/"];
// Letter list ID's since I couldn't figure out how to run this using a database
var LetterIDList = [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];
// Number list ID's since I couldn't figure out how to run this using a database
var NumIDList = [1,2,3,4,5,6,7,8,9,10];
// Special character list ID's since I couldn't figure out how to run this using a database
var SpecialID = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
// Filtered Lists
var UpperFiltered = [];
var LowerFiltered = [];
var NumFiltered = [];
var SpecialFiltered = [];
// Global declarations of random number variables to grab values from intial lists
var UpperGenVariable;
var LowerGenVariable;
var NumGenVariable;
var SpecialGenVariable;
// Creates a basic password with 2 of each kind of character
function Basic () {
for (var i = 1; i <= 2; i++) {
UppercaseGenerate();
}
for (var i = 1; i <= 2; i++) {
LowercaseGenerate();
}
for (var i = 1; i <= 2; i++) {
NumGenerate();
}
for (var i = 1; i <= 2; i++) {
SpecialGenerate();
}
};
let passwordGen = document.getElementById("PasswordDisplay")
function UppercaseGenerate() {
var UpperFiltered = [];
UpperGenVariable = Math.floor(Math.random() * LetterIDList.length);
for (var i = 0; i < LetterIDList.length; i++) {
if (LetterIDList[i] == UpperGenVariable) {
UpperFiltered.push(UppercaseList[i]);
}
};
passwordGen.value += UpperFiltered
};
This is my first ever question, please give me feedback if I suck at this. Thank you
I am trying to create a JavaScript terminal game from a paid course. The game is called 'Find My Hat'.
One section of the problem requires me to create a static method called generateField(). This method generates a field, on the field there are 4 possible characters:
hat = '^';
hole = 'O';
fieldCharacter = '░';
pathCharacter = '*';
The fieldCharacter is the background for the game area. The game area is comprised of nested arrays. I haven't had problems creating the field, but I also want to replace random fieldCharacters with holes. I tried this with Math.random and nested loops to iterate over the nested arrays. I have not been able to figure out how to get this to work.
Here is the code below, sorry if I missed any details, I will try respond to everyone I can.
class Field {
constructor(field) {
this._field = field;
}
print() {
this._field = field.join('\n');
console.log(this._field.replace(/,/g, ''))
}
static generateField(height, width) {
let finalArray = []
for (let i = 0; i < height; i++) {
finalArray.push([fieldCharacter.repeat(width)]);
}
for (let i = 0; i < finalArray.length; i++) {
let randomHole = () => {
let result = Math.random() * width;
return result;
}
for (let j = 0; j < finalArray[i].length; j++) {
if (randomHole() > width - 2) {
finalArray[i][j] = hole;
}
}
}
return finalArray.join('\n').replace(/,/g, '');
}
}
console.log(Field.generateField(5, 10));
One Random Output:
O
O
░░░░░░░░░░
░░░░░░░░░░
O
Example for good output:
░░░░O░░░░░
░░░O░OO░░░
░░O░░░O░░░
░░░░O░░░░░
OO░░░░O░░O
I did some changes to your code and use the stackoverflow snippet to show you how it works
String.prototype.replaceAt = function(index, replacement) {
return this.substr(0, index) + replacement + this.substr(index + replacement.length);
}
hat = '^';
hole = 'O';
fieldCharacter = '░';
pathCharacter = '*';
class Field {
constructor(field) {
this._field = field;
}
print() {
this._field = field.join('\n');
console.log(this._field.replace(/,/g, ''))
}
static generateField(height, width) {
let finalArray = []
for (let i = 0; i < height; i++) {
finalArray.push(fieldCharacter.repeat(width));
}
//i dont know why you did this loop but i changed the inside for marking random holes
for (let i = 0; i < finalArray.length; i++) {
//pick random x and y
let randomHoleX = Math.floor(Math.random() * width);
let randomHoleY = Math.floor(Math.random() * height);
//becouse you save array of strings you need to find the correct array and replace the char at the correct index.
finalArray[randomHoleY] = finalArray[randomHoleY].replaceAt(randomHoleX, hole);
}
return finalArray.join('\n').replace(/,/g, '');
}
}
console.log(Field.generateField(5, 10));
I'm working on a visualizer for sorting algorithms. Everything is working as intended until I got to the Selection Sort. I understand that the Selection sort will make a pass and search for the MINIMUM value and then swap that the index that it started at in the array. However, each time it makes a pass, the i value doesn't change. I tested it by changing the color of the block the i index represents in my loop and it never changes, so the MINIMUM value just keeps switching to where ever the i is.
You can view my project here on GitHub Pages, just use the left Navbar to choose Selection Sort and you can see the problem I'm having. The bottom snippet is my swap function, it didn't do this with any of the other sort methods, only the selection sort.
Github Pages -- https://kevin6767.github.io/sorting-algorithm-visualization/
Selection function
async function selectionSort() {
let blocks = document.querySelectorAll('.block');
for (let i = 0; i < blocks.length; i++) {
// Assume a minimum value
let min = i;
for (let j = i + 1; j < blocks.length; j++) {
blocks[j].style.backgroundColor = '#FF4949';
blocks[min].style.backgroundColor = '#13CE66';
blocks[i].style.backgroundColor = 'orange';
await new Promise((resolve) =>
setTimeout(() => {
resolve();
}, frame_speed)
);
const value1 = Number(blocks[j].childNodes[0].innerHTML);
const value2 = Number(blocks[min].childNodes[0].innerHTML);
if (value1 < value2) {
blocks[min].style.backgroundColor = '#58B7FF';
min = j;
}
blocks[j].style.backgroundColor = '#58B7FF';
}
if (min !== i) {
let tmp = blocks[i];
blocks[i] = blocks[min];
blocks[min] = tmp;
await swap(blocks[i], blocks[min]);
blocks = document.querySelectorAll('.block');
}
// Swap if new minimun value found
blocks[i].style.backgroundColor = '#58B7FF';
}
}
Swap function
function swap(el1, el2) {
return new Promise((resolve) => {
const style1 = window.getComputedStyle(el1);
const style2 = window.getComputedStyle(el2);
const transform1 = style1.getPropertyValue('transform');
const transform2 = style2.getPropertyValue('transform');
el1.style.transform = transform2;
el2.style.transform = transform1;
// Wait for the transition to end!
window.requestAnimationFrame(function () {
setTimeout(() => {
container.insertBefore(el2, el1);
resolve();
}, 300);
});
});
}
I ended up fixing it. It seems that I had to take the Nodelist array I was getting from just .querySelectorAll and convert that into an array using .Arrayfrom() which was pretty simple after some googling. From then on I needed to figure out how to update the array each pass, which once again was as simple as just moving one index from another.
The interesting part of the answer was how I was going to update the Nodelist itself that way all my css code would still work (This is a sorting visualizer, so it would show you what element it was on and highlight it with a color). The answer however was right in front of me. Even though I turned the Nodelist array into a regular array, I was still able to apply styles to it. This meant I didn't have to mutate the Nodelist array at all and was just able to keep a seperate array within the function to work with.
PS. The algorithm did have a lot of trouble in the above snippet because I was comparing 2 strings in the if statement (value1 and value2) this is what caused a lot of the actual algorithm erroring and was simply fixed by adding a Number() function around my innerhtml code.
Selection
async function selectionSort() {
let blocks = document.querySelectorAll('.block');
let convertedBlocks = Array.from(blocks);
let len = convertedBlocks.length;
for (let i = 0; i < len; i++) {
let min = i;
for (let j = i + 1; j < len; j++) {
convertedBlocks[j].style.backgroundColor = 'red';
convertedBlocks[min].style.backgroundColor = 'green';
convertedBlocks[i].style.backgroundColor = 'orange';
await new Promise((resolve) =>
setTimeout(() => {
resolve();
}, frame_speed)
);
if (
Number(convertedBlocks[min].childNodes[0].innerHTML) >
Number(convertedBlocks[j].childNodes[0].innerHTML)
) {
convertedBlocks[min].style.backgroundColor = '#58B7FF';
min = j;
}
convertedBlocks[j].style.backgroundColor = '#58B7FF';
}
if (min !== i) {
let tmp = convertedBlocks[i];
convertedBlocks[i] = convertedBlocks[min];
convertedBlocks[min] = tmp;
await swap(convertedBlocks[i], convertedBlocks[min]);
}
convertedBlocks[min].style.backgroundColor = '#58B7FF';
convertedBlocks[i].style.backgroundColor = '#58B7FF';
}
}
I'm quite new to JS and I'm trying to do a TicTacToe game with a custom size board in an attempt to learn a bit more. I first coded just a 3x3 version and started building up from there.
Right as I got past the point where I have a custom grid size entered right after loading the page and the grid rendering, I started getting the same problem when trying to click any cell to try and play a turn.
"this.game_state[clicked_cell_i] is undefined".
I have tried opening up F12 and checking if the game_state array (which is a 2d array of strings that tracks which cell is played and which isn't) but when I do everything seems normal and the array gets printed out without problem. (picture showcases printing out the game_state array in a 4x4 grid) https://i.stack.imgur.com/gV0pY.png
I would really appreciate it if somebody could explain to me what's happening or even better - help me fix it. Thanks :)
Code: https://jsfiddle.net/z8649pxL
class game {
status_display;
is_game_active;
curr_player;
game_state;
constructor() {
this.status_display = document.querySelector('.status');
this.is_game_active = true;
this.curr_player = "X";
this.game_state = matrix(rows, rows, "");
}
cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
clicked_cell.innerHTML = this.curr_player;
if(this.curr_player === "X"){
document.getElementById((i*rows)+j).style.backgroundColor = "#ff6600";
} else if(this.curr_player === "O"){
document.getElementById((i*rows)+j).style.backgroundColor = "#33ccff";
}
}
cell_click(clicked_cellEvent){
debugger
const clicked_cell = clicked_cellEvent.target;
let clicked_cell_i = parseInt(clicked_cell.getAttribute('i'));
let clicked_cell_j = parseInt(clicked_cell.getAttribute('j'));
if(this.game_state[clicked_cell_i][clicked_cell_j] !== "" || !this.is_game_active) {
return;
}
this.cell_played(clicked_cell, clicked_cell_i, clicked_cell_j);
this.res_validation();
}
};
let ex_game = new game();
function create_grid() {
document.getElementById('hidestart').style.display = "none";
var Container = document.getElementsByClassName("grid");
Container.innerHTML = '';
rows = prompt("n?");
let i = 0, j = 0;
document.documentElement.style.setProperty("--columns-row", rows);
for (i = 0; i < rows ; i++) {
for(j = 0; j < rows; j++){
var div = document.createElement("div");
div.className = "cell";
div.id = (i*rows)+j;
div.setAttribute("cell-index", (i*rows)+j);
div.setAttribute("i", i);
div.setAttribute("j", j);
let wrapper = document.getElementsByClassName("grid");
wrapper[0].appendChild(div);
}
}
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', (e) => {
ex_game.cell_click(e);
e.stopPropagation();
}));
document.getElementById('hidestart').style.display = "block";
}
function matrix(rows, cols, defaultValue){
var arr = [];
// Creates all lines:
for(var i=0; i < rows; i++){
// Creates an empty line
arr.push([]);
// Adds cols to the empty line:
arr[i].push(new Array(cols));
for(var j=0; j < cols; j++){
// Initializes:
arr[i][j] = defaultValue;
}
}
return arr;
}```
When you call
new game()
the constructor is been called of that class.
And in that constructor you are calling matrix which requires the value of rows.
But initially the class do not have any value.
So the state is not getting initialized at that point of time.
That why when you use the array, it is getting undefined.
So to resolve this issue, you could just try to get the object of class game after getting the rows from user, and pass that rows in the arguments when calling the constructor of the class.
let ex_game = new game(rows);
And then using this argument call the function matrix.
Edit:
I have looked into your code.
The error is in the method called cell_played. you are using i and j which are not known to it. Please replace your code with following line. This would resolve your error.
cell_played(clicked_cell, clicked_cell_i, clicked_cell_j){
this.game_state[clicked_cell_i][clicked_cell_j] = this.curr_player;
clicked_cell.innerHTML = this.curr_player;
if(this.curr_player === "X"){
document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#ff6600";
} else if(this.curr_player === "O"){
document.getElementById((clicked_cell_i*rows)+clicked_cell_j).style.backgroundColor = "#33ccff";
}
}
And also remove the parameter rows from constructor and just call the constructor after taking the number of rows from user.
let ex_game
function create_grid() {
/* document.getElementById('hidestart').style.display = "none" */
var Container = document.getElementsByClassName("grid");
Container.innerHTML = '';
rows = prompt("n?");
let i = 0, j = 0;
ex_game= new game().........