Passing arguments through multiple functions in Javascript - 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);
}
}

Related

if can't access parameter in JavaScript module

Hi I'm having problems with the scope of an if in a JavaScript module.
Here is a mock up of my code :
module.exports = {
caser(nb){
if(0 === 0){
nb = 3+2
}
}
}
The function is called from another JavaScript file. Nb however doesn't change when I do this.
My editor (visual studio code) marked nb as unused. This I tried :
module.exports = {
caser(nb){
let number = nb
if(0 === 0){
number = 3+2
}
}
}
This still doesn't seem to alter the value of nb. Does anyone know a solution to this problem?
Thanks in advance.
Reassigning nb (or number) will only change what those variable names point to in the current function. It sounds like what you need to do is return the changed value, and have the consumer of the function use it to reassign the value it passes in. Something like:
// consumer file:
const { caser } = require('./foo');
let nb = 5;
nb = caser(nb);
module.exports = {
caser(nb) {
if (0 === 0) {
nb = 3 + 2
}
return nb;
}
}
The only way to avoid having to reassign in the consumer would be for the consumer to pass an object instead, and mutate the object.
// consumer file:
const { caser } = require('./foo');
const objToPass = { nb: 5 };
caser(objToPass);
module.exports = {
caser(objToPass) {
if (0 === 0) {
objToPass.nb = 3 + 2
}
}
}

Trouble with JS while loops and if statements :(

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>

Creating game like portable module

I want to create some game. Is it good, that my view on this game has to be like view on the module? It means, anywhere on the other website I want to run my game, I'll just put my module to it.
So, if we imagine "my view" like class, will it look some like this?
class Mario {
// Whole game module
class Game {
// Game properties
class Player {
}
class Card {
}
}
class Init {
// This take care about gui etc.
class Gui {
show_cards() {
}
}
}
start() {
var init = new Init();
something to init Gui and run method show_cards();
}
}
var mario = new Mario();
mario.start();
Am I right?
But is this syntax right in JavaScript and is this even possible?
Thanks for help!
If you want the extra awesomesauce of an HTML element you can drop into your page to hold your game code, you could make a custom element, but I bet you could get by just fine with a module.
As far as your code structure, this should help you out. It's a Game class template that utilizes separate Player and Resource classes -- and I stuck in a GameHandler class at the top for you (which would be like your Mario class.)
Happy coding!
class GameHandler {
constructor(){
this.handlerSetup();
const gameResources = [ // Array of resource objects for setResources method
{
type: "card",
number: 1,
},
{
type: "card",
number: 2,
options: { category: "A", description:"special" }
}
];
this.game = new Game(4, gameResources); // This can go in a loop to allow sequential games
}
handlerSetup(){ /* Do setup tasks here */ }
}
class Game {
constructor(playerCount, resourcesArray){
this.players = this.setPlayers(playerCount);
this.resources = this.setResources(resourcesArray);
this.winnerIfAny = null;
this.turnNumber = 0;
this.output("Ready to play");
// Main loop
while(this.winnerIfAny === null){
this.winnerIfAny = this.nextTurn(++this.turnNumber);
}
this.output(`Game over -- Player number ${this.winnerIfAny.number} wins`);
}
setPlayers(count){
let i = 0, players = [];
while(i < count){
players.push(new Player(i++));
}
this.output(`${count} players added`)
return players;
}
setResources(resourcesProvided){
let resources = [];
for(let resource of resourcesProvided){
resources.push(new Resource(resource));
}
this.output(`${resources.length} resources added`)
return resources;
}
nextTurn(turnNumber){
this.output("Taking turn...");
let winnerFound = null;
// Turn loop code goes here
// (eg switch to next player, take turn, check for winner
// This demo game is not very interesting -- it randomly assigns a winner
let rand = (Math.floor(Math.random() * (11 - turnNumber * 2)));
if (turnNumber > 1 && rand < 4) { winnerFound = this.players[rand]; }
if(winnerFound){ return winnerFound; }
return null;
}
output(text){ document.querySelector("#outputDiv").innerHTML += `${text}<br/>`; }
}
class Player {
constructor(number){
this.number = number;
//etc...
}
}
class Resource {
constructor(type, number, options){
this.number = number;
//etc...
}
}
new GameHandler();
<div id="outputDiv"></div>

JS getter not returning dynamic result

I am making a simple game, it's divided into game generators, which generate values, and game engine, that interacts with user.
class Generator {
constructor() {
this.intro = 'Answer "yes" if number even otherwise answer "no"!';
this.question = null;
this.answer = null;
}
get game() {
this.question = getRandomInt(10);
this.answer = this.question % 2 === 0 ? 'yes' : 'no';
return [this.question, this.answer];
}
}
const newGame = new Generator();
const gameEven = () => game(newGame.intro, newGame.game);
However, when I launch game, I found that it cycles through the same number. I used get game() specifically because MDN states that is allows to return a dynamically computed value, why it didn't work?
Not really sure what problem you having, but I don't think it's JS getter not returning dynamic result
Below is a simple Snippet that demonstrates the dynamic nature of a getter..
As you can see you get 2 different random numbers when you call game
class Generator {
get game() {
return Math.random();
}
}
var v = new Generator();
console.log(v.game);
console.log(v.game);

How to delete a Prototype object with a pointer to it?

I have been coding a singly linked list in JavaScript.
My structure is:
function node(x)
{
this.x=x;
this.next=null;
}
function sl() //sl-singly linked list
{
this.first=null;
this.l=0; //length of list
}
Where I get the trouble :
Delete Last Method :
sl.prototype.deletel=function()
{
if(this.first)
{
var t=this.first;
while(t.next)
t=t.next;
if(t)
t=null;
}
}
Even though I made the pointer to the last element null, still Last node gets printed.
I have attached the working snippet. Operations:
Generate List :01234
Invoking Delete Last...
Expected Output : 0123
What I get : 01234
function node(x)
{
this.x=x;
this.next=null;
}
function sl()
{
this.l=0;
this.first=null;
}
sl.prototype.insertl=function(x)
{
var newnode=new node(x);
var t=this.first;
if(!this.first)
this.first=newnode;
else
{
while(t.next)
t=t.next;
t.next=newnode;
}
l++;
}
sl.prototype.deletel=function()
{
if(this.first)
{
var t=this.first;
while(t.next)
t=t.next;
if(t)
t=null;
}
}
sl.prototype.console=function()
{
var t=this.first;
while(t)
{
document.write(t.x);
t=t.next;
}
}
sl();
sl.prototype.insertl(0);
sl.prototype.insertl(1);
sl.prototype.insertl(2);
sl.prototype.insertl(3);
sl.prototype.insertl(4);
sl.prototype.deletel();
alert("check");
sl.prototype.console();
Even though I made the pointer to the last element null
No, you did not. There are no pointers in JavaScript. t is nothing but a local variable, which you did set to null indeed, but you did not alter a property of any object. You do however need to nullify the .next property of the second-to-last node:
sl.prototype.deletel = function() {
var t = this.first;
if (t) {
var n = t.next;
if (n) {
while (n.next) {
t = n;
n = n.next;
}
t.next = null; // remove last node from second-to-last
} else {
this.first = null; // remove last node from list
}
}
};

Categories