How to remove edge cases for string and number expressions - javascript

I'm building a rock, paper, scissors game and working on excluding edge cases.
The function is setPlayerMoves(), which is supposed to set previously undefined global variables for player moves and give them a 'value' between 1-99. how do I excluded edge cases like wrong move type (eg. 'rok') or wrong value (eg. 100).
Here is my incorrect code:
function setPlayerMoves(player, moveOneType, moveOneValue, moveTwoType, moveTwoValue, moveThreeType, moveThreeValue) {
if (player === 'Player One' && (moveOneType && moveTwoType && moveThreeType === 'rock' || 'paper' || 'scissors') && (moveOneValue && moveTwoValue && moveThreeValue === (>= 1 && <= 99))) {
playerOneMoveOneType = 'rock';
playerOneMoveTwoType = 'paper';
playerOneMoveThreeType = 'scissors';
playerOneMoveOneValue = 11;
playerOneMoveTwoValue = 33;
playerOneMoveThreeValue = 55;
} else if (player === 'Player Two') {
playerTwoMoveOneType = 'rock';
playerTwoMoveTwoType = 'paper';
playerTwoMoveThreeType = 'scissors';
playerTwoMoveOneValue = 11;
playerTwoMoveTwoValue = 33;
playerTwoMoveThreeValue = 55;
}
}

Problem
Code for checking edge cases are wrong.
(player === 'Player One' && (moveOneType && moveTwoType && moveThreeType === 'rock' || 'paper' || 'scissors') && (moveOneValue && moveTwoValue && moveThreeValue === (>= 1 && <= 99)))
Also you are checking the edge cases for only 'player one'
Solution
Check the values seperately before assigning values and create a valid variable
let valid = false
let states = ['rock','paper','scissors'];
if((states.indexOf(moveOneType) != -1) && (states.indexOf(moveTwoType) != -1) && (states.indexOf(moveThreeType) != -1)){
// valid state
valid = true;
}else{
valid = false;
}
if((moveOneValue >=1 && moveOneValue <= 99) && (moveTwoValue >=1 && moveTwoValue <= 99) && (moveThreeValue >=1 && moveThreeValue <= 99)){
//valid value
valid = true;
}else{
valid = false
}
Then assign the values.
if ((player === 'Player One') && valid) {
playerOneMoveOneType = moveOneType;
playerOneMoveTwoType = moveTwoType;
playerOneMoveThreeType = moveThreeType;
playerOneMoveOneValue = moveOneValue;
playerOneMoveTwoValue = moveTwoValue;
playerOneMoveThreeValue = moveThreeValue;
} else if ((player === 'Player Two') && valid) {
playerTwoMoveOneType = moveOneType;
playerTwoMoveTwoType = moveTwoType;
playerTwoMoveThreeType = moveThreeType;
playerTwoMoveOneValue = moveOneValue;
playerTwoMoveTwoValue = moveTwoValue;
playerTwoMoveThreeValue = moveThreeValue;
}
Also if possible
Create an object each for player1 and player2 like below and use.
let player1 = {
moveOneType:'rock'
moveTwoType:'paper'
moveThreeType:'scissors'
moveOneValue: 23
moveTwoValue: 33
moveThreeValue: 98
}

Related

How can I make this JS repetitive code shorter

I just wrote this piece of code that does the thing it's supposed to do, although it's really messy and pretty repetitive and I'm wondering how can I make it much shorter and concise.
if(id==1 && player == "playerOne"){
Object.assign(playerOne, fighters[0])
}else if(id==1 && player =="playerTwo"){
Object.assign(playerTwo, fighters[0])
}
if(id==2 && player == "playerOne"){
Object.assign(playerOne, fighters[1])
}else if(id==2 && player =="playerTwo"){
Object.assign(playerTwo, fighters[1])
}
if(id==3 && player == "playerOne"){
Object.assign(playerOne, fighters[2])
}else if(id==3 && player =="playerTwo"){
Object.assign(playerTwo, fighters[2])
}
if(id==4 && player == "playerOne"){
Object.assign(playerOne, fighters[3])
}else if(id==4 && player =="playerTwo"){
Object.assign(playerTwo, fighters[3])
}
if(id==5 && player == "playerOne"){
Object.assign(playerOne, fighters[4])
}else if(id==5 && player =="playerTwo"){
Object.assign(playerTwo, fighters[4])
}
if(id==6 && player == "playerOne"){
Object.assign(playerOne, fighters[5])
}else if(id==6 && player =="playerTwo"){
Object.assign(playerTwo, fighters[5])
}
if(id==7 && player == "playerOne"){
Object.assign(playerOne, fighters[6])
}else if(id==7 && player =="playerTwo"){
Object.assign(playerTwo, fighters[6])
}
if(id==8 && player == "playerOne"){
Object.assign(playerOne, fighters[7])
}else if(id==8 && player =="playerTwo"){
Object.assign(playerTwo, fighters[7])
}
if(id==9 && player == "playerOne"){
Object.assign(playerOne, fighters[8])
}else if(id==9 && player =="playerTwo"){
Object.assign(playerTwo, fighters[8])
}
Thank you in advance!
Assuming
a) there are no more than two players
b) you don't care that this code handles id < 1 and id > 9
It looks to me like you could reduce this to a single line.
Object.assign(player == "playerOne" ? playerOne : playerTwo, fighters[id - 1])
What if you rewrite it to be something along the lines of
if (player == "playerOne") {
p = playerOne
} else if (player =="playerTwo") {
p = playerTwo
}
Object.assign(p, fighters[id - 1])
A for loop might be helpful:
for (let i = 1; i < 10; i++) {
if (id == i && player == "playerOne") {
Object.assign(playerOne, fighters[id - 1]);
} else if (id == i && player == "playerTwo") {
Object.assign(playerTwo, fighters[id - 1]);
}
}
Based on the assumptions in your example, that id must be between 1 and 9 and player can be anything, but must be playerOne or playerTwo:
for (var i = 1; i < 10; i++) {
if (id == i) {
if(player == "playerOne"){
Object.assign(playerOne, fighters[i - 1]);
} else if (player == "playerTwo") {
Object.assign(playerTwo, fighters[i - 1]);
}
}
}

Rock Paper Scissors game with JavaScript

I have recently got into coding with JavaScript and decided to make a game, to test my knowledge. Nothing happens when I press on the objects supposed to start the game, and when I send information through the console, (most of the time) nothing happens.
const paper = document.getElementById('paper');
const scissor = document.getElementById('scissor');
const result_in = document.getElementById("result")
let computer;
let computer_pick;
let result;
//Player choice
rock.onclick = play('rock');
paper.onclick = play('paper');
scissor.onclick = play('scissor');
function play(userinput) {
computer_pick = Math.floor(Math.random() * 3);
console.log(computer_pick);
if (computer_pick === 0) {
computer = 'rock'
} else if (computer_pick === 1) {
computer = 'paper';
} else if (computer_pick === 2) {
computer = 'scissor';
} else { console.log('error') };
console.log(computer);
//
if (computer == userinput) { //tie
result = 'tie';
} else if (computer == 'rock' && userinput == 'paper' || computer == 'paper' && userinput == 'scissor' || computer == 'scissor' && userinput == "rock") {
console.log(win);
result = 'win';
} else if (computer == 'rock' && userinput == 'scissor' || computer == 'paper' && userinput == 'scissor' || computer == 'scissor' && userinput == 'paper') {
console.log(loss);
result = 'lost';
}
//output
document.getElementById('result').innerHTML = You ${result}! The computer threw ${computer}.;
}
Are you waiting until the DOM is loaded?
Where are you inject this file to DOM? in head tag or body tag!
If you inject this code in head tag you need to wait until the DOM become loaded
something like this:
window.onload = function() {
// Your script
}
There are some errors in your code:
rock.onclick is not correct - rock.addEventlistener('click', function(e) {}) is correct
console.log(win) (or loss) is not correct - you try to console.log() a variable that doesn't exist - to output a string in console.log() you should put it in quotes console.log('win')
document.getElementById('result').innerHTML = You ${result}! The computer threw ${computer}.; is not correct - you should use backticks for string interpolation
You didn't define rock as you did paper and scissor
This is not an coding error, but a simple logic problem: you have three result ALTERNATIVES: tie, win, lost. If it's not a tie and user hasn't win (won), then user lost. You don't need the last else if, only else
The same is true for the computer_pick variable - there's no room for error (the random value can only be 0, 1 or 2), so you don't need the else for error. And if computer_pick is not 0 or 1, then it has to be 2 (no need for the else if, only for else).
const rock = document.getElementById('rock');
const paper = document.getElementById('paper');
const scissor = document.getElementById('scissor');
const result_in = document.getElementById("result");
let computer;
let computer_pick;
let result;
//Player choice
rock.addEventListener('click', function(e) {
play('rock')
})
paper.addEventListener('click', function(e) {
play('paper')
})
scissor.addEventListener('click', function(e) {
play('scissor')
})
function play(userinput) {
computer_pick = Math.floor(Math.random() * 3);
console.log('computer_pick:', computer_pick);
if (computer_pick === 0) {
computer = 'rock'
} else if (computer_pick === 1) {
computer = 'paper';
} else {
computer = 'scissor';
}
console.log('computer:', computer);
//
if (computer == userinput) { //tie
result = 'tie';
} else if (computer == 'rock' && userinput == 'paper' || computer == 'paper' && userinput == 'scissor' || computer == 'scissor' && userinput == "rock") {
console.log('win');
result = 'win';
} else {
console.log('lost');
result = 'lost';
}
//output
document.getElementById('result').innerHTML = `You ${result}! The computer threw ${computer}.`;
}
<div id="rock">ROCK</div><br />
<div id="paper">PAPER</div><br />
<div id="scissor">SCISSORS</div><br />
<div>RESULT: <span id="result"></span></div>
And you could go a bit further by thinking through the logic:
// you can use a query selector with a class
const btns = document.querySelectorAll('.btn')
// gameRulesObj to define what beats what
const gameRulesObj = {
"rock": "paper",
"paper": "scissor",
"scissor": "rock"
}
btns.forEach(e => {
e.addEventListener('click', function(e) {
appendToDOMElement('result', play(this.getAttribute('id'), computerPick(gameRulesObj), gameRulesObj))
})
})
// this function decides if player wins, loses or ties
function play(userinput, computer, obj) {
let result;
if (computer === userinput) {
result = 'tie';
} else if (obj[computer] === userinput) {
result = 'win';
} else {
result = 'lost';
}
return {
result,
computer
};
}
// this function controls what the computer picks
const computerPick = (obj) => {
return Object.keys(obj)[Math.floor(Math.random() * Object.keys(obj).length)]
}
// this function adds the result to the DOM
const appendToDOMElement = (container, {
result,
computer
}) => {
document.getElementById(container).textContent = `You ${result}! The computer threw ${computer}.`
}
<div id="rock" class="btn">ROCK</div><br />
<div id="paper" class="btn">PAPER</div><br />
<div id="scissor" class="btn">SCISSORS</div><br />
<div>RESULT: <span id="result"></span></div>
The second snippet above gives a bit of a structure to the code:
every function has one and only one purpose (they can be described with one line of comment); this means that it's easier to change parts of your app
a lot of variables are eliminated, so you don't have to keep track of them
one variable added (gameRulesObj), so you can define your base rules in one place; the functions now work with any number and set of rules
I know that this structure may be overkill for a simple game like this, but it's good for practicing :)
try < button onClick=play('rock')> and so on
and you need " " for the line document.getElementById('result').innerHTML = " "

Node.js: telnet "Rock, Paper, Scissors" Program not working

So I am trying to create this Rock, Paper, Scissors program to run on a telnet server. Except It's not allowing me to enter the words "Rock","Paper", or "Scissors".
First CPUhand is showing up as undefined and is not setting to one of the options in my if statements.
Second whenever I enter a single character in the command prompt, It gives me my "Invalid, try again!" else statement and skips to the next line.
Is anyone able to figure out why my if statements for CPUhand are not working or why I can't enter more than a single character in command prompt?
Screenshot1 Screenshot2
"use strict";
const
net = require('net'),
server = net.createServer(function(connection) { //create server
let randomNum = randomNumber(1, 3);
let CPUhand
if(randomNum == 1){
CPUhand == "Rock";
} else if(randomNum == 2){
CPUhand == "Paper";
} else if(randomNum == 3){
CPUhand == "Scissors";
}
connection.write("Enter: Rock, Paper, or Scissors!\r\n");
connection.on('data', function(chunk) { //collect data from user
let USERhand = chunk.toString();
if(CPUhand === "Rock" && USERhand === "Scissors" || USERhand === "Rock" && CPUhand === "Scissors"){
connection.write("Rock beats Scissors!\r\n");
}
else if(CPUhand === "Paper" && USERhand === "Rock" || USERhand === "Paper" && CPUhand === "Rock"){
connection.write("Paper beats Rock!\r\n");
}
else if(CPUhand === "Scissors" && USERhand === "Paper" || USERhand === "Scissors" && CPUhand === "Paper"){
connection.write("Scissors beats Paper!\r\n");
}
else if(CPUhand === USERhand){
connection.write("Draw!\r\n");
}
else{
connection.write("Invalid! Try Again! \r\n");
}
});
}); server.listen(5432); //bind port
function randomNumber(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
1) Typo in block:
if(randomNum == 1){
CPUhand == "Rock";
} else ...
Should be:
if(randomNum == 1){
CPUhand = "Rock";
} else ...
2) In user input you have also line break symbol:
let USERhand = chunk.toString();
Replace with:
let USERhand = chunk.toString().trim();

Why isn't my game ending in a tie?

I'm coding a tic-tac-toe game in pure javascript.
My program correctly checks if either Player1 or Player2 have won. For some reason, it's not able to check if it's a tie though.
I have set a counter called moveCounter. After each successful move, the counter is incremented by one. It is not possible for the counter to reach higher than 9.
Below is a function that tests the game's state.
It will check if player1 or player2 has won. It does this fine.
Below you can see I'm attempting to test for a tie. But nothing is happening. The game is just stuck and nothing is being printed to the console aside from the counter which is being incremented in my placePiece() function.
I have tried playing around with it and altering the if condition, along with it's position without the function and I'm having no luck so far.
Here's my gameState() function:
// The game ends when one player has three of their symbols in a row either horizontally, vertically or diagonally.
function gameState() {
var result;
//boxes
var a1 = document.getElementById('a1');
var a2 = document.getElementById('a2');
var a3 = document.getElementById('a3');
var b1 = document.getElementById('b1');
var b2 = document.getElementById('b2');
var b3 = document.getElementById('b3');
var c1 = document.getElementById('c1');
var c2 = document.getElementById('c2');
var c3 = document.getElementById('c3');
//See if Player 1 has won
if((a1.classList.contains("box-filled-1") && a2.classList.contains("box-filled-1") && a3.classList.contains("box-filled-1")) || (b1.classList.contains("box-filled-1") && b2.classList.contains("box-filled-1") && b3.classList.contains("box-filled-1")) || (b1.classList.contains("box-filled-1") && b2.classList.contains("box-filled-1") && b3.classList.contains("box-filled-1")) || (c1.classList.contains("box-filled-1") && c2.classList.contains("box-filled-1") && c3.classList.contains("box-filled-1")) || (a1.classList.contains("box-filled-1") && b1.classList.contains("box-filled-1") && c1.classList.contains("box-filled-1")) || (a2.classList.contains("box-filled-1") && b2.classList.contains("box-filled-1") && c2.classList.contains("box-filled-1")) || (a3.classList.contains("box-filled-1") && b3.classList.contains("box-filled-1") && c3.classList.contains("box-filled-1")) || (a1.classList.contains("box-filled-1") && b2.classList.contains("box-filled-1") && c3.classList.contains("box-filled-1")) || (a3.classList.contains("box-filled-1") && b2.classList.contains("box-filled-1") && c1.classList.contains("box-filled-1"))){
result = "player1"
return gameOver(result);
}
//See if Player 2 has won
if((a1.classList.contains("box-filled-2") && a2.classList.contains("box-filled-2") && a3.classList.contains("box-filled-2")) || (b1.classList.contains("box-filled-2") && b2.classList.contains("box-filled-2") && b3.classList.contains("box-filled-2")) || (b1.classList.contains("box-filled-2") && b2.classList.contains("box-filled-2") && b3.classList.contains("box-filled-2")) || (c1.classList.contains("box-filled-2") && c2.classList.contains("box-filled-2") && c3.classList.contains("box-filled-2")) || (a1.classList.contains("box-filled-2") && b1.classList.contains("box-filled-2") && c1.classList.contains("box-filled-2")) || (a2.classList.contains("box-filled-2") && b2.classList.contains("box-filled-2") && c2.classList.contains("box-filled-2")) || (a3.classList.contains("box-filled-2") && b3.classList.contains("box-filled-2") && c3.classList.contains("box-filled-2")) || (a1.classList.contains("box-filled-2") && b2.classList.contains("box-filled-2") && c3.classList.contains("box-filled-2")) || (a3.classList.contains("box-filled-2") && b2.classList.contains("box-filled-2") && c1.classList.contains("box-filled-2"))){
result = "player2"
return gameOver(result);
}
//If all of the squares are filled and no players have three in a row the game is a tie.
if(moveCounter === 9){
result = "tie";
console.log("tie");
return gameOver(result);
}
};
Here's where it gets called:
// Players can only click on empty squares. When the player clicks on an empty square, attach the class box-filled-1 (for O) or box-filled-2 (for X) to the square.
function placePiece() {
if(!this.classList.contains("box-filled-1") && !this.classList.contains("box-filled-2")) {
if(currentPlayer === player1){
this.classList.add("box-filled-1");
player1.currentPlayer = false;
player2.currentPlayer = true;
currentPlayer = player2;
currentPlayerFlag();
gameState();
moveCounter++;
console.log(moveCounter);
} else {
this.classList.add("box-filled-2");
player2.currentPlayer = false;
player1.currentPlayer = true;
currentPlayer = player1;
currentPlayerFlag();
gameState();
moveCounter++;
console.log(moveCounter);
}
}
};
Assume you init moveCounter = 0, then move gameState() after incrementing moveCounter
moveCounter++;
gameState();

Reset for game and winner issue

I'm building a simple tic-tac-toe game and I need some help with my reset button and winner function.
At the end of provided snippet I'm trying to implement a reset button, but I'm not exactly sure how to get it to work. The way I'm doing my else statement for my winner function is so, that if there are no more moves, I can't seem to get it to say: "no more moves" without it saying it every time you click on a square.
How can I implement this?
// IIFE
(function() {
angular
.module("myApp", [])
.controller("tictactoeController", tictactoeController);
// Controller
function tictactoeController() {
// Capture Variable
var self = this;
self.currentTurn = '';
self.playerOne = 'X';
self.playerTwo = 'O';
self.winner = '';
// Gameboard
self.boxes = [
{square: 1}, {square: 2}, {square: 3},
{square: 4}, {square: 5}, {square: 6},
{square: 7}, {square: 8}, {square: 9} ];
// Picks Random Player To Be X or O
self.random = function() {
if (Math.random() > 0.5) {
alert("Player One GO!");
self.currentTurn = "X";
} else {
alert("Player Two GO!");
self.currentTurn = "O";
}
};
self.random();
// Clickbox Function
self.clickbox = function($index) {
//console.log(self.boxes[$index].value + "check");
if (self.boxes[$index].value === undefined) {
self.boxes[$index].value = self.currentTurn;
self.boxes[$index].square = self.currentTurn;
if (self.currentTurn === "X") {
self.currentTurn = "O";
} else {
self.currentTurn = "X";
}
} else {
alert(
"Already Taken! Choose Another Square!"
);
}
// Check for winner after each click
self.winner(self.boxes[$index].value);
};
// Winner Fucntion
self.winner = function(input) {
// Row Wins
if ((self.boxes[0].square == input && self.boxes[
1].square == input && self.boxes[2]
.square == input) || (self.boxes[3].square ==
input && self.boxes[4].square == input &&
self.boxes[5].square == input) || (self
.boxes[6].square == input && self.boxes[
7].square == input && self.boxes[8]
.square == input)) {
alert(input + " WINS!");
// Column Wins
} else if ((self.boxes[0].square == input &&
self.boxes[3].square == input && self.boxes[
6].square == input) || (self.boxes[
1].square == input && self.boxes[4]
.square == input && self.boxes[7].square ==
input) || (self.boxes[2].square ==
input && self.boxes[5].square == input &&
self.boxes[8].square == input)) {
alert(input + " WINS!");
// Diagonal Wins
} else if ((self.boxes[0].square == input &&
self.boxes[4].square == input && self.boxes[
8].square == input) || (self.boxes[
2].square == input && self.boxes[4]
.square == input && self.boxes[6].square ==
input)) {
alert(input + " WINS!");
// No Winner
}
};
// Reset Game Button
self.resetbtn = function() {
};
}
})();
The reset function:
self.resetbtn = function() {
self.boxes.forEach(function(box, index) {
self.boxes[index].value = '';
self.boxes[index].square = index;
})
};
The no more moves else:
var hasMoves = false;
self.boxes.forEach(function(box, index) {
if(box.square != self.playerOne && box.square != self.playerTwo) {
hasMoves = true;
}
}
if(! hasMoves) {
alert ("No more moves!");
}
Also, it would be better if in the code you don't use hard coded values X and O but their variables self.playerOne and self.playerTwo. It will make it easier to change the values X and O (though in a Tic Tac Toe game you wouldn't do it).

Categories