Trouble with JS while loops and if statements :( - javascript

I want to have a function that picks a random number, and depending on the number, selects a global variable and adds it to an array, repeating 5 times. I don't know if the idea even works. Its basically for a online 2D game, It needs to pick a random card, and then have the information of the card available, so later in the game the cards can vs each other.
Ive been googling stuff for like 2 hours and it still doesnt work, im probably missing something obvious or silly.
Right now i have an empty array outside of the function, and then a random number is picked and i have if statements that will correspond to the right card which will be put in the array. I also want the array to be accesible later in other functions, like I'll have to make functions where the cards have to be compared, so i just need something that gets a random selection of 5 cards and saves their information to be used in later functions.(later i will add more else if statements since there will be 16 cards total)
<script src="https://randojs.com/1.0.0.js"></script>
<script>
let centaur = { name:'Centaur', class:'Common', health:50, attack:25, defence:15, strength:10, magic:10, image:'images/Cards/2_Common/CENTAUR.png' };
let dryad = {name:'Dryad', class:'Common', health:10, attack:10, defence:10, strength:10, magic:50, image:'images/Cards/2_Common/DRYAD.png'};
/*let = {name:'', class:'', health:, attack:, defence:, strength:, magic:, image:''};*/
var listofran = {};
function findcard(){
var random = rando(0,6);
while (let i=5; i>0;i--){
if (random == 0){
listofran.push = centaur;
}
else if (random ==1) {
listofran.push = dryad;
}
else if (random ==2) {
listofran.push = gryffin;
}
else if (random ==3) {
listofran.push = giant;
}
else if (random ==4) {
listofran.push = harpy;
}
else if (random ==5){
listofran.push = satyr;
}
else{
listofran.push = mermaid;
}
i--;
}
}
document.getElementById('rand').innerHTML=listofran;
</script>
Then in the body im just trying to see if it works, so i only have this just to see if i can make the list appear.
<p>random list<span id="rand"></span></p>>
Honestly I struggle with like what components need to go in what functions and where, so yeah, just any help would be very appreciated.

You can try this code. You need an array to hold the values and add the item inside for loop.
let centaur = { name:'Centaur', class:'Common', health:50, attack:25, defence:15, strength:10, magic:10, image:'images/Cards/2_Common/CENTAUR.png' };
let dryad = {name:'Dryad', class:'Common', health:10, attack:10, defence:10, strength:10, magic:50, image:'images/Cards/2_Common/DRYAD.png'};
/*let = {name:'', class:'', health:, attack:, defence:, strength:, magic:, image:''};*/
var listofran = [];
function findcard(){
for (let i=5; i>0;i--)
{
var random = rando(0,6);
if (random == 0){
listofran.push(centaur);
}
else if (random ==1) {
listofran.push(dryad);
}
}
}
findcard();
document.getElementById('rand').innerHTML=listofran.map(x => x.name).join(',');
<script src="https://randojs.com/1.0.0.js"></script>
<p>random list</p><span id="rand"></span>

You can pick a (pseudo random) creature from an array of creatures without the need for some loop. Refactored your code to minimal reproducable example.
document.addEventListener("click", handle);
const creatures = [
{ name:'Centaur', },
{ name:'Dryad', },
{ name:'Gryffin', },
{ name:'Giant', },
{ name:'Harpy', },
{ name:'Satyr', },
{ name:'Mermaid', },
];
let listOfRan = [];
// the function tho tame the creatures
function findCard(){
// next 2 lines are what the answer is all about
const randomIndex = Math.floor(Math.random() * creatures.length);
listOfRan.push(creatures[randomIndex]);
// output for this example
document.querySelector('#rand').textContent = `Last added: ${
JSON.stringify(listOfRan.slice(-1)[0])}\n`;
document.querySelector('#all').textContent = `All of listOfRan: ${
JSON.stringify(listOfRan, null, 2)}\n`;
}
// Not specific for this answer
// Function to handle all events in document
function handle(evt) {
if (evt.target.dataset.handleid === "1") {
return findCard();
}
if (evt.target.dataset.handleid === "2") {
return document.querySelectorAll("pre")
.forEach( elem => elem.textContent = "");
}
if (evt.target.dataset.handleid === "3") {
if (confirm(`Are you sure?`)) {
listOfRan = [];
document.querySelector('#all').textContent = "Empty";
}
return;
}
}
<button data-handleid="1">Random creature please</button>
<button data-handleid="2">Clear output</button>
<button data-handleid="3">Clear [listOfRan]</button>
<pre id="rand"></pre>
<pre id="all"></pre>

Related

Passing arguments through multiple functions in Javascript

I'm currently writing a tic tac toe game in javascript, and I've written the following class to represents the "Computer".
I've included the entire class below, but the method I'm struggling with is atRiskSquare(). Here's how it's supposed to work: the method move() should get called with a board object, and then it should pass that board object into atRiskSquare() which checks whether any of the squares are at risk (in which case the computer would play a defensive move).
When I console.log the "board" inside of the move() method I get an array that represents the board. however, when I console.log the board inside of the atRiskSquare() method I get undefined. I'm not sure if I'm missing something simple, but I can't seem to figure out why this is happening.
Any help would be greatly appreciated
class Computer extends Player {
constructor() {
super();
}
static COMPUTER_MOVE = 'O';
move(board) {
console.log(board); // **Logs the board**
if (this.atRiskSquare(board)) {
this.defensiveMove(this.atRiskSquare(board));
} else {
this.randomMove(board, this.atRiskSquare());
}
}
atRiskSquare(board) {
console.log(board); // **logs undefined**
let humanMoves = board.findSpaces('X'); // Throws an error. Can't iterate over undefined
for (let winningCombo of Game.WINNING_COMBOS) {
let atRiskSquare;
let count;
for (let square of winningCombo) {
if (humanMoves.includes(square)) {
count += 1;
} else {
atRiskSquare = square;
}
}
if (count === 2) {
return atRiskSquare;
}
}
return null;
}
defensiveMove(board, square) {
board.addMove(square, Computer.COMPUTER_MOVE);
this.moves.push(square);
}
randomMove(board) {
let openSpaces = board.findSpaces(' ');
let randomSpace = Math.floor(Math.random() * openSpaces.length);
let move = openSpaces[randomSpace].toString();
board.addMove(move, Computer.COMPUTER_MOVE);
this.moves.push(move);
}
}

Tiles dont turn right

I am making a website, http://phaidonasgialis.xyz. I want to make the tiles to turn and every other tile back. Until now it works except one small bug, the tile that you pressed does not turn back until you click second time.Any help would be thankful.
Here is the code:
$(document).ready(function() {
var previous = [];
$('.flip-card').each(function(i, obj) {
$(this).click(function() {
if ($(this).find('.flip-card-inner').hasClass('flip-card-transform')) {
$(this).find('.flip-card-inner').removeClass('flip-card-transform');
} else {
$(this).find('.flip-card-inner').addClass('flip-card-transform');
previous.push(this);
if (previous.length >= 2 && previous[previous.length - 2] != previous[previous.length - 1]) {
for (var i = 0; i < previous.length; i++) {
if ($(this).find('.flip-card-inner').hasClass('flip-card-transform')) {
$(previous[i - 1]).find('.flip-card-inner').removeClass('flip-card-transform');
console.log("2")
} else {
$(this).find('.flip-card-inner').addClass('flip-card-transform');
console.log("3")
}
}
}
}
});
});
If I understand your question correctly, you would like a card to flip back automatically after a certain period of time? If so then you just should set a Timeout and remove the class flip-card-transform from .flip-card-inner.
Aside note: you should definitely optimize your code by using a variable instead of doing $(this).find('.flip-card-inner')– converting this to jQuery object and searching trough its children every time when you need your flip-card-inner. Also instead of $('.flip-card').each(...) you could directly use $('.flip-card').click(...). And also as Harun Yilmaz suggested in his comment you don't need previous as an array...
So something like this should work:
$(document).ready(function () {
var previous
var timeout
$('.flip-card').click(function () {
var cardInner = $(this).find('.flip-card-inner')
if (cardInner.hasClass('flip-card-transform')) {
cardInner.removeClass('flip-card-transform')
clearTimeout(timeout)
} else {
cardInner.addClass('flip-card-transform')
// Set a Timeout
timeout = setTimeout(function () {
cardInner.removeClass('flip-card-transform')
}, 2000) // set whatever time sutable for you
// Also as Harun Yilmaz suggested in his comment you don't need previous as an array
if (previous && previous.hasClass('flip-card-transform')) {
previous.removeClass('flip-card-transform')
}
previous = cardInner
}
})
})

Calling imported function within itself not working in Node.js, probably related to return statement and scope

My idea is to build an application that generates sudoku's and allows users to fill them in. I'm using Node and Mongo to do so. For generating the sudoku, I have imported my 'sudoku.js' into a route function. The sudoku generation in 'sudoku.js' runs fine only when I run it by itself, but not in the route.
In short, the sudoku generator picks a random number, checks whether it has already been used in the row/column/block, and if not, adds it to the array. If it has been used, the function is re-ran, until it does 'discover' a correct sudoku. The function should return an array consisting of nine arrays, each with 9 numbers.
It appears to go south when the function genSud() is called within itself. The function, as it is now, returns 'undefined'. When I comment out the function call within the function, it does return an array, but those are almost always unfinished sudoku's. If I leave out the return statement, which I think the issue is related to, it will just keep on rerunning the function until it hits the stack limit.
const createSudoku = {
getRandomNumber: function(array) {
return array[Math.floor(Math.random() * array.length)];
},
checkIfIn: function(array, blockNumber, blockAvailable, columnNumber, columnAvailable) {
let availableNumbers = [];
array.forEach(function(element) {
if (blockAvailable[blockNumber].includes(element) && columnAvailable[columnNumber].includes(element)) {
availableNumbers.push(element);
}
});
if (availableNumbers.length === 0) {
return false;
};
return availableNumbers;
},
genSud: function(callback) {
let availableNumbers = [];
let goodLines;
let blockAvailable = [ [1,2,3,4,5,6,7,8,9], [1,2,3,4,5,6,7,8,9], etc, etc ]
let columnAvailable = [ [1,2,3,4,5,6,7,8,9], etc, etc ]
let rowAvailable = [ [1,2,3,4,5,6,7,8,9], etc, etc ]
let blockNumber;
let randomNumber;
for (var i = 0; i < 9; i++) {
for (var j = 0; j < 9; j++) {
blockNumber = Math.floor(j / 3) + 3 * Math.floor(i / 3);
availableNumbers = this.checkIfIn(rowAvailable[i], blockNumber, blockAvailable, j, columnAvailable);
if (availableNumbers == false) {
this.genSud(callback);
return;
}
randomNumber = this.getRandomNumber(availableNumbers);
rowAvailable[i].splice(rowAvailable[i].indexOf(randomNumber), 1);
columnAvailable[j].splice(columnAvailable[j].indexOf(randomNumber), 1);
blockAvailable[blockNumber].splice(blockAvailable[blockNumber].indexOf(randomNumber), 1);
body[i].push(randomNumber);
}
}
callback(body);
}
}
// createSudoku.genSud();
module.exports = createSudoku;
Then, in my route:
var sudoku = require('../sudoku.js');
var completeSudoku = sudoku.genSud(function(result) {
return result;
});
I'm aware I could abandon the rerunning altogether by replacing numbers etc., but for now it's fast enough by itself. Also, I know I could store a bunch of sudoku's in a database and retrieve them, but I like the idea of generating them on the spot.
Thanks in advance!
Edit: I have created a CodePen here:
https://codepen.io/anon/pen/OjmGMy?editors=0000
You can run it in the console using:
createSudoku.genSud();
I have made it work by removing the callback and using #nstraub 's suggested edit. Changed:
if (availableNumbers == false) {
this.genSud();
return;
}
to
if (availableNumbers == false) {
return this.genSud();
}
I'm not sure why this works, but it does solve the issue.

Looking for a smart if condition - Javascript

I am trying to make a function to buy item but I dont want people to be able to gather more than 2 items at the same time.
I am looking for a condition that state something like.
if Axe + Sword = true then calling the function buyItem(Dagger) will say something like "You cant have more than 2 items".
But consider I want to add more items later.
var buyItem = function (name)
{
if (name === "Axe")
{
console.log("Axe");
}
else if (name === "Sword")
{
console.log("Sword");
}
else if (name === "Dagger")
{
console.log("Dagger");
}
};
Thank you :)
How about having a variable that keeps track of how many items you have?
int itemsHeld = 0;
When you acquire a new item use itemsHeld++; and when you lose one use itemsHeld--;
Now when trying to get a new item you can just ask if (itemsHeld < 2) getItem();
Store bought count as private variable
// store reference to your function returned from self invoking anonymous function enclosure (to prevent internal vairables from leaking into global scope)
var buyItem = (function(){
// store local reference to number of items already bought
var bought = 0;
// return the function to be assigned to buyItem
return function (name)
{
// if we reached the maximum, don't buy any more - just log a warning and return
if(bought >= 2){
console.log("your hands are full!!");
return;
} else {
// otherwise increment the bought counter
bought++;
};
if (name === "Axe")
{
console.log("Axe");
}
else if (name === "Sword")
{
console.log("Sword");
}
else if (name === "Dagger")
{
console.log("Dagger");
}
};
})();
// try it out
buyItem('Dagger');
buyItem('Sword');
buyItem('Axe');

Javascript object functions not working

I'm not really sure why my code isn't running correctly.. what I'm trying to do is create a grocery list object that has a couple of functions to add and remove items..
I can instantiate the objects with new items but my functions don't seem to work for some reason.
If you could save me the few hairs left in my head and tell me where the issue is I would greatly appreciate it.
var groceryList = function(itemNames,quantity) {
if (Array.isArray(itemNames)) {
this.items = itemNames;
this.quantity = quantity
this.addItems = function(newItems){
if ( Array.isArray(newItems) ) {
this.items.concat(newItems);
} else {
console.log("Please enter the items in an array fashion!");
};
};
this.removeItem = function(name) {
var listSize = this.items.length;
for (var i = 0; i < listSize; i++) {
if (this.items[i] == name) {
this.items.splice(i,1);
break;
} else {
console.log("Please enter the items in an array fashion!")
};
};
};
} else {
console.log("Please enter the items in an array fashion!")
};
};
.concat() returns a new array so you have to assign the result back to your instance variable.
So this:
this.items.concat(newItems);
needs to be changed to this:
this.items = this.items.concat(newItems);
or, you could actually use this to append to the array directly:
this.items.push.apply(this.items, newItems);
Because .push() can take more than one argument.
Then, in your .removeItem() function, you need to remove the item you actually found by changing this:
this.items.splice(2,1);
to this:
this.items.splice(i,1);

Categories