Having trouble restarting logic Tic Tac Toe game (JavaScript) - javascript

I am having trouble to look where the problem is.
I was able to create the game board and I will be implementing AI soon.
For now, I need to make it work so that everytime the game is over, it will restart a new one and resume.
However when it reaches to that point, it stops working.
From my what I've read, I may not be binding the events correctly, but I am still left puzzled.
Can anyone pinpoint what is wrong with my code?
$(document).ready(function(){
var human;
var computer;
var board = new Board()
var game;
function Human(symbol){
this.name = "Player",
this.symbol = symbol;
}
function Computer(symbol){
this.name = "Computer",
this.symbol = symbol;
}
//Modal opens when page is rendered. User can choose symbol
$("#myModal").modal()
$("#xPlayer").on('click',function(){
human = new Human("X");
computer = new Computer("O");
board.initalize();
game = new Game(human)
game.play();
})
$("#oPlayer").on('click',function(){
human = new Human("O")
computer = new Computer("X");
board.initalize();
game = new Game(computer)
game.play();
})
//Board constuctor
function Board(){
this.board = []
this.status = "";
}
//method calls for an empty board filled with "E"
Board.prototype.initalize = function(){
$("td p").empty()
this.board = ["E","E","E","E","E","E","E","E","E"]
this.status = "New Game";
}
//return true if there is a win. Otherwise, false
Board.prototype.win = function(){
var B = this.board;
//check row
for (var i = 0; i <= 6; i = i + 3){
if (B[i] !== "E" && (B[i] === B[i+1]) && (B[i+1] === B[i+2])){
board.status = "Winner is: " + game.currentPlayer.name
return true
}
}
//check column
for (var i = 0; i <= 2 ; i++ ){
if (B[i] !== "E" && (B[i] === B[i+3]) && (B[i+3] === B[i+6])){
board.status = "Winner is: " + game.currentPlayer.name
return true
}
}
//check diagonal
for(var i = 0, j = 4; i <= 2 ; i = i + 2, j = j - 2) {
if(B[i] !== "E" && (B[i] == B[i + j]) && (B[i + j] === B[i + 2 * j]) ) {
board.status = "Winner is: " + game.currentPlayer.name
return true;
}
}
return false
}
//checks if the current status is draw. If so, updates the status to "Draw"
Board.prototype.draw = function(){
//checks if the board itself is draw
for(var i = 0; i < this.board.length ; i++){
if (this.board[i] === "E"){
return false;
}
}
board.status = "Draw!"
return true;
}
//method returns array of indexes that are not empty cells in the board
Board.prototype.available = function(){
var B = this.board;
var indexes = [];
for (var i = 0; i < B.length ; i ++){
if (B[i] === "E"){
indexes.push(i)
}
}
return indexes;
}
//checks first if the User Input is valid or not
Board.prototype.validMove = function(position){
var availableCells = this.available();
return availableCells.includes(position);
}
//updates the board when using jQuery click
//it will render the webpage by prototype_writeBoard
Board.prototype.updateBoard = function(position,playerInput) {
var availableCells = this.available();
if (availableCells.includes(position)){
this.board[position] = playerInput
}
};
function Game(firstPlayer){
this.currentPlayer = firstPlayer;
this.over = false;
this.win = "";
}
Game.prototype.switchPlayer = function(){
this.currentPlayer = (this.currentPlayer === human) ? computer : human
}
Game.prototype.play = function(){
$("td").click(function(){
var position = $(this).attr("id");
var positionNumber = parseInt(position.slice(4,5))
// This here renders to the board and updates board.board
if(board.validMove(positionNumber)){
//Checks if the move is valid. If it is, append it.
//Otherwise, alert the user that it is taken
$(this).find("p").append(game.currentPlayer.symbol)
board.updateBoard(positionNumber, game.currentPlayer.symbol)
//Check if it the game is over or draw
//If either is true, play new game
if (board.win() || board.draw()){
alert(board.status)
game.restart();
}
game.switchPlayer();
}else{
alert("Already taken")
}
})
}
Game.prototype.restart = function(){
board.initalize();
game.play()
}
})
body {
background: skyblue; }
#tictactoe {
max-width: 700px;
min-height: 300px;
margin: 68px auto;
display: flex;
width: 100%; }
#tictactoe table {
width: 100%;
font-size: 65px;
text-align: center;
vertical-align: middle;
table-layout: fixed; }
td {
height: 115px;
color: #101935;
background: #F2FDFF;
border: 5px solid #DBCBD8;
border-radius: 12px;
cursor: pointer;
transition: background 0.5s ease-out, color 0.5s ease-out; }
td:hover {
background: #564787;
color: #F2FDFF; }
.modal-dialog {
text-align: center; }
.modal-dialog .modal-footer {
text-align: center; }
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TicTacToe FCC</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<link rel="stylesheet" href="css/styles.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div id="tictactoe">
<table id="game-board">
<tbody>
<tr id="row1">
<td id="cell0"><p></p></td>
<td id="cell1"><p></p></td>
<td id="cell2"><p></p></td>
</tr>
<tr id="row2">
<td id="cell3"><p></p></td>
<td id="cell4"><p></p></td>
<td id="cell5"><p></p></td>
</tr>
<tr id="row3">
<td id="cell6"><p></p></td>
<td id="cell7"><p></p></td>
<td id="cell8"><p></p></td>
</tr>
</tbody>
</table>
</div>
<!--Modal Window -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Choose your character!</h4>
</div>
<div class="modal-body">
<p>Have fun!</p>
</div>
<div class="modal-footer">
<button type="button" id="xPlayer" class="btn btn-default" data-dismiss="modal">X</button>
<button type="button" id="oPlayer" class="btn btn-default" data-dismiss="modal">O</button>
</div>
</div>
</div>
</div>
</body>
<script src="js/javascript.js" type="text/javascript"></script>
</html>

In Game.play you are binding to the onclick of the td element. Then in Game.restart you are calling Game.play which is binding to the click event again. Since you are already calling Game.play when you setup the players there is no need to call it in Game.restart since it is still bound to the click event
Game.prototype.restart = function(){
board.initalize();
/* delete-me game.play() */
}

Related

How to use the Spacebar for changing color in JS [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
i have a question about JS
i just want when i write for example Own(the 'Own' word is in the array) in the input feild and then i press spacebar the color of Own word in head gets green and when i write for example
'false' the color of the Own word in the head gets red
and i want this for the rest of them i Hope you Guys Find out what i'm saying
thanks..
var seconds = 60;
var timer;
function myFunction() {
if(seconds < 60) {
document.getElementById("timer").innerHTML = seconds;
}
if (seconds >0 ) {
seconds--;
} else {
clearInterval(timer);
}
}
document.getElementById("No1").onkeypress = function() {
if(!timer) {
timer = window.setInterval(function() {
myFunction();
}, 1000);
}
}
document.getElementById("timer").innerHTML="1:00";
var text = ["Own","food","need","turn","you"]
var i;
document.getElementById('Text').innerHTML +='';
for(i = 0; i < text.length; i++){
document.getElementById('Text').innerHTML += text[i]+" ";
}
const words = [];
const memorizer = (ev) => {
const inp = ev.target;
const val = inp.value.trim();
if(ev.key === ' ') {
const valSpl = val.split(' ');
words.push(valSpl[0]);
inp.value = valSpl[1] || '';
}
if(ev.key === ' ' && val === '' ) {
inp.value = words.length ? words.pop() : '';
}
console.clear();console.log(words);
}
document.querySelector('#No1').addEventListener('keyup', memorizer);
<html>
<body style="background-color: teal !important;">
<div class="container">
<div class="row">
<div id="col" class="col-12 font-weight-bold" style="background-color: white;
font-family: 'Times New Roman', Times, serif;
text-align: center;
font-size: 30px;">
<span id="Text"></span>
</div>
<div class="col-12">
<input id="No1" type="text" class="bg-white form-control" style="width: 80% !important;
display: inline-block;
margin-top: 20px;">
<div id="timer" style=" background-color: rgb(53, 53, 53);
width: 60px;
display: inline-block;
text-align: center;
font-size: 20px;
color: white;"></div>
</div>
</div>
</div>
<script src="js/index-1.js"></script>
</body>
</html>
Change your "Text" span to a div container to put multiple span text in html file
In js file, use createElement("span") to put each text and append span to div container
when press whitespace, compare last element in words array with text array
Here is the code:
var seconds = 60;
var timer;
function myFunction() {
if (seconds < 60) {
document.getElementById("timer").innerHTML = seconds;
}
if (seconds > 0) {
seconds--;
} else {
clearInterval(timer);
}
}
document.getElementById("No1").onkeypress = function () {
if (!timer) {
timer = window.setInterval(function () {
myFunction();
}, 1000);
}
};
document.getElementById("timer").innerHTML = "1:00";
// create span to put text in Text div
var text = ["Own", "food", "need", "turn", "you"];
var i;
var textNode = document.getElementById("Text");
for (i = 0; i < text.length; i++) {
var s = document.createElement("span");
s.id = text[i];
s.innerHTML = text[i] + " ";
textNode.appendChild(s);
}
const words = [];
const memorizer = (ev) => {
const inp = ev.target;
const val = inp.value.trim();
if (ev.key === " ") {
const valSpl = val.split(" ");
words.push(valSpl[0]);
inp.value = valSpl[1] || "";
// compare the word is correct or not, and change color
if (words[words.length - 1] === text[words.length - 1]) {
document.getElementById(text[words.length - 1]).style.color = "green";
} else {
document.getElementById(text[words.length - 1]).style.color = "red";
}
}
if (ev.key === " " && val === "") {
inp.value = words.length ? words.pop() : "";
}
console.clear();
console.log(words);
};
document.querySelector("#No1").addEventListener("keyup", memorizer);
<html>
<body style="background-color: teal !important">
<div class="container">
<div class="row">
<div
id="col"
class="col-12 font-weight-bold"
style="
background-color: white;
font-family: 'Times New Roman', Times, serif;
text-align: center;
font-size: 30px;
"
>
<!-- use Text div as a container to put text span -->
<div id="Text"></div>
</div>
<div class="col-12">
<input
id="No1"
type="text"
class="bg-white form-control"
style="
width: 80% !important;
display: inline-block;
margin-top: 20px;
"
/>
<div
id="timer"
style="
background-color: rgb(53, 53, 53);
width: 60px;
display: inline-block;
text-align: center;
font-size: 20px;
color: white;
"
></div>
</div>
</div>
</div>
<script src="js/index-1.js"></script>
</body>
</html>

Need advice (mentoring)

Created a validation form in vanilla JS. Due to my little experience, I have a bunch of "if" here, I can not transfer the coordinates of Yandex.Maps to another function for validation, and it is still unknown what. With the coordinates, I "crutch" by saving them to an invisible div :-) I deleted my Api key, so I won't be able to get the coordinates in the example, I don't know if it's worth giving the key to public access :-) The code is working.
Tell me how you can reduce the code or how to do button validation without my crutch with a div :-)
let errorName = document.querySelector(".name-error");
let errorNumber = document.querySelector(".number-error");
let errorEmail = document.querySelector(".email-error");
let errorMap = document.querySelector(".map-error");
let completed = document.querySelector(".mailForm__completed");
function viodChecker() {
let name = document.querySelector(".mailForm__name").value;
let number = document.querySelector(".mailForm__number").value;
let Email = document.querySelector(".mailForm__email").value;
let Coords = document.querySelector(".coords");
if (name === "") {
errorName.style.display = "block";
}
if (name !== "") {
errorName.style.display = "none";
}
if (number === "") {
errorNumber.style.display = "block";
}
if (number !== "") {
errorNumber.style.display = "none";
}
if (Email.indexOf("#") === -1) {
errorEmail.style.display = "block";
}
if (Email.indexOf("#") !== -1) {
errorEmail.style.display = "none";
}
if (Email.indexOf("#") !== -1) {
errorEmail.style.display = "none";
}
if (Coords.textContent === "") {
errorMap.style.display = "block";
}
if (Coords.textContent !== "") {
errorMap.style.display = "none";
}
if (name !== "" && number !== "" && Email.indexOf("#") !== -1 && Coords.textContent !== "") {
completed.style.display = "block";
}
}
ymaps.ready(init);
function init() {
var myPlacemark,
myMap = new ymaps.Map('map', {
center: [40.391917, -73.524590],
zoom: 17,
controls: ['geolocationControl', 'searchControl']
});
// We listen to the click on the map.
myMap.events.add('click', function (e) {
var coords = e.get('coords');
// If the label has already been created, just move it.
if (myPlacemark) {
myPlacemark.geometry.setCoordinates(coords);
}
// If not, we create.
else {
myPlacemark = createPlacemark(coords);
myMap.geoObjects.add(myPlacemark);
// Listen to the drag-and-drop event on the label.
myPlacemark.events.add('dragend', function () {
getAddress(myPlacemark.geometry.getCoordinates());
});
}
getAddress(coords);
});
// Create a label.
function createPlacemark(coords) {
return new ymaps.Placemark(coords, {
iconCaption: 'search...'
}, {
preset: 'islands#violetDotIconWithCaption',
draggable: true
});
}
// Coords
function getAddress(coords) {
myPlacemark.properties.set('iconCaption', 'поиск...');
ymaps.geocode(coords).then(function (res) {
var firstGeoObject = res.geoObjects.get(0);
myPlacemark.properties
.set({
// We form a line with data about the object.
iconCaption: [
firstGeoObject.geometry.getCoordinates(),
].filter(Boolean).join(', '),
// We set the line with the object address as the balloon content.
balloonContent: firstGeoObject
});
document.querySelector(".coords").textContent = firstGeoObject.geometry.getCoordinates();
});
}
}
body, .mailForm {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
}
input, textarea {
font-size: 14px;
margin: 10px 0 0 0;
width: 350px;
resize: none;
}
.mailForm__map {
margin-top: 10px;
}
button {
margin: 10px 0 0 0;
font-size: 14px;
cursor: pointer;
}
.mailForm__comment {
display: inline-block;
height: 200px;
}
.mailForm__error, .mailForm__completed, .coords {
display: none;
color: red;
font-size: 16px;
font-weight: bold;
margin-top: 10px;
}
.mailForm__completed {
color: green;
font-size: 20px;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link href="style.css" rel="stylesheet">
<title>Mail Form</title>
<script src="https://api-maps.yandex.ru/2.1/?apikey=5200498b-0123-4796-1-bee4ea5473212&lang=ru_RU" type="text/javascript">
</script>
</head>
<body>
<div class="mailForm">
<input class="mailForm__name" placeholder="Name" type="text" value="">
<input class="mailForm__number" placeholder="Tel" type="tel" value="">
<input class="mailForm__email" placeholder="Email" type="email" value="">
<div id="map" class="mailForm__map" style="width: 100%; height: 200px">
</div>
<textarea class="mailForm__comment" maxlength="500" placeholder="Comment" type="text" value=""></textarea>
<button onclick="viodChecker()">SEND</button>
<div class="mailForm__error name-error">NAME ERROR</div>
<div class="mailForm__error number-error">TEL ERROR</div>
<div class="mailForm__error email-error"># ERROR</div>
<div class="mailForm__error map-error">COORDS ERROR</div>
<div class="mailForm__completed">NICE!</div>
<div class="coords"></div>
</div>
<script src="script.js"></script>
</body>
</html>

Need help fixing a bug in a browser game

This is a very simple browser memory game which you need to to flip all the matched cards in order to win.
The bug :
In the game if you click fast enough you can flip more than 2 cards.
I've tried a lot to fix it but couldn't figure it out by myself. I would appreciate any help in solving this issue as I am new to JavaScript and it's still hard for me fix those basic bugs.
Game files:
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>My App</title>
<link rel="stylesheet" href="css/game.css" />
</head>
<body>
<button class="Change User" onclick="change(this)">Change User</button>
<div class="header">
<img src="img/layout/logo.png">
<h1>Memory Monsters</h1>
<p id="Play Again"></p>
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="img/cards/1.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="img/cards/7.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="1" onclick="cardClicked(this)">
<img src="img/cards/1.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="7" onclick="cardClicked(this)">
<img src="img/cards/7.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="img/cards/5.png">
<img class="back" src="img/cards/back.png">
</div>
<div class="card" data-card="5" onclick="cardClicked(this)">
<img src="img/cards/5.png">
<img class="back" src="img/cards/back.png">
</div>
<script src="js/game.js"></script>
</body>
</html>
javascript:
var getElementsByClassName = prompt ('What is your name?');
window.localStorage.setItem ('name', 'dan');
function change(username) {
prompt('What is your name?');
}
// Those are global variables, they stay alive and reflect the state of the game
var elPreviousCard = null;
var flippedCouplesCount = 0;
// This is a constant that we dont change during the game (we mark those with CAPITAL letters)
var TOTAL_COUPLES_COUNT = 3;
// Load an audio file
var audioWin = new Audio('sound/win.mp3');
// This function is called whenever the user click a card
function cardClicked(elCard) {
// If the user clicked an already flipped card - do nothing and return from the function
if (elCard.classList.contains('flipped')) {
return;
}
// Flip it
elCard.classList.add('flipped');
// This is a first card, only keep it in the global variable
if (elPreviousCard === null) {
elPreviousCard = elCard;
} else {
// get the data-card attribute's value from both cards
var card1 = elPreviousCard.getAttribute('data-card');
var card2 = elCard.getAttribute('data-card');
// No match, schedule to flip them back in 1 second
if (card1 !== card2){
setTimeout(function () {
elCard.classList.remove('flipped');
elPreviousCard.classList.remove('flipped');
elPreviousCard = null;
}, 1000)
} else {
// Yes! a match!
flippedCouplesCount++;
elPreviousCard = null;
// All cards flipped!
if (TOTAL_COUPLES_COUNT === flippedCouplesCount) {
audioWin.play();
// and finally add a button to call resetCard()
document.getElementById("Play Again").innerHTML =
'<button onclick="resetCard();">Play Again</button>';
}
}
}
}
function resetCard() {// to erase the flipped classes
var cardclass = document.getElementsByClassName("card");
for (i = 0; i < cardclass.length; i++) {
cardclass[i].classList.remove("flipped");
document.getElementById("Play Again").innerHTML = "";
}
}
CSS:
.header {
background-color: lightblue;
padding: 20px;
border-bottom: 10px solid darkcyan;
color:darkcyan;
font-size: 1.5em;
text-align: center;
}
.header img {
float:right;
}
.card {
background-color: pink;
height: 165px;
width: 165px;
float: left;
margin: 5px;
}
.card img {
position: absolute;
}
.flipped .back {
display: none;
}
i made a game like this. you need to create a variable that starts on 0
let tries = 0;
then add one to it each time a card is selected. make sure to not allow it to count if a card that is already flipped is clicked again. here is some of the code from the function that is run on my onclick. I am using a React framework, but if you write this logic in your JS function, it is what you will need to make it work
selected = (event) => {
if (canClick === true) {
let id = event.currentTarget.id; //card0
let idString = id.toString(); //"card0"
//ONLY ALLOW A CARD TO BE CLICKED IF ITS FACE DOWN
if (this.state[idString] === cardBack) {
idString = idString.replace(/card/g, ''); //"0"
this.setState({[id] : arrayRandom[idString]});
//FIRST PICK
if (counter % 2 == 1) {
curCard1 = arrayRandom[idString].toString();
id1 = id;
counter++;
//SECOND PICK
} else {
//MAKE SURE A CARD DOESN'T GET SELECTED TWICE IN A ROW AND STAY FACE UP
if (id === id1) {
console.log("Select a different card for your second pick");
} else {
counter++;
tries++;
canClick = false; //STOP USER FROM SELECTING ANOTHER CARD
curCard2 = arrayRandom[idString].toString();
id2 = id;
setTimeout(() => {canClick = true}, 1000); //USER CAN PICK AGAIN IN 1 SEONCD
//IF THERE'S A MATCH - CARDS STAY FLIPPED, SCORE INCREASES BY 1
if (curCard1 == curCard2) {
score = score + 1;
//IF THERE'S NO MATCH - CARDS FLIP FACE DOWN AFTER A SECOND
} else {
setTimeout(() => {
this.setState({[id1]: cardBack});
this.setState({[id2]: cardBack});
}, 1000);
}
}
}
} else {
console.log("This card has already been flipped, select another one");
}
}
}
here is my game
https://reactcardmatch.netlify.com/

Building a Wheel of Fortune game and I'm trying to get the keypress event to detect a letter in the random word array

I'm working on a Wheel of Fortune game where a random word is chosen from an array. I created a function below my game function to detect the key pressed from a list of letters displayed on screen from A-Z. My problem is that I can't get the game to detect the key pressed until the randomWord() function is fired after the playGame() button is pressed. I'm trying to get the letter pressed by the user in the buttonPress() function to match a letter in the wordChoice.length loop and display on the screen where the _ would be and then rule out the letter after it's been used. I tried creating the letterClicked variable and making it global so that my playGame() function can access it but I'm not having any luck matching the letter selected by the user and the letter in the display box above the play button. What am I doing wrong here? I tried console logging throughout the randomWord() function but the keypress is only being detected after you click play and essentially reset the game. Here is my code below. Thanks for your help!
<DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Wheel of Fortune</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="main.css">
</head>
<body>
<body>
<div id="container">
<div id="header">
<p class="welcome">Welcome to Wheel of Fortune!</p>
<!-- The letters will be tied to the number of letters in the random array -->
<p class="letters">There are <span id="numbers">0</span> letters in this word</p>
<!-- The user will be given a number of choices and with each wrong choice, they lose a turn -->
<p class="lives">You have <span id="guesses">0</span> guesses left</p>
<span id="words"></span><br>
<button id="play" onclick="playGame()">Play</button>
</div>
<div id="alphabet" onclick="buttonPress(event)">
<button>A</button>
<button>B</button>
<button>C</button>
<button>D</button>
<button>E</button>
<button>F</button>
<button>G</button>
<button>H</button>
<button>I</button>
<button>J</button>
<button>K</button>
<button>L</button>
<button>M</button>
<br>
<button>N</button>
<button>O</button>
<button>P</button>
<button>Q</button>
<button>R</button>
<button>S</button>
<button>T</button>
<button>U</button>
<button>V</button>
<button>W</button>
<button>X</button>
<button>Y</button>
<button>Z</button>
</div>
<span id="your-guess">You guessed </span>
</div>
<script src="main.js"></script>
</body>
</html>
body {
margin: 0 auto;
width: 1000px;
font-size: 20px;
background: url("http://res.cloudinary.com/angelrodriguez/image/upload/c_crop,h_624/v1534810805/wheeloffortune.jpg");
background-size: cover;
color: white;
}
#header {
margin: 20px;
}
#alphabet {
margin: 20px;
}
button {
border: 2px solid blue;
font-size: 20px;
}
#words {
font-size: 30px;
margin: 10px;
letter-spacing: 20px;
}
#play {
margin: 20px;
}
// 3. Quit the game if the player wants to.
// 5. Keep track of letters the player has guessed.
// 6. Show the player their progress.
// 7. Finish when the player has guessed the word.
// Create global variables
let gameOver = false;
var guessesLeft = 6;
var letterClicked;
var wordArray = ["JAVASCRIPT", "ARRAYS", "FUNCTIONS", "HOISTING", "RECURSION", "EVENTS", "KEYUP", "TERNARY"];
// 1. Pick a random word.
//Start a new game
function playGame() {
newGame.addEventListener("click", function() {
//fire the randomWord function to generate a new word
randomWord();
})
}
// Pass the letter event from buttonPress into the randomWord function
function randomWord(letter) {
var answerList = [];
// console.log(answerList);
// letterGuessed = "";
console.log(letterClicked);
var wordChoice = wordArray[Math.floor(Math.random() * wordArray.length)];tbw
var wordSplit = wordChoice.split('');
// console.log(wordSplit);
for (var i = 0; i < wordSplit.length; i++) {
answerList[i] = "_";
}
// if the letter is in the word
// Update the players progress with the guess
for (var z = 0; z < wordChoice.length; z++) {
if (wordChoice[z] === letterClicked) {
letterClicked = answerList[i];
// answerList[i].innerHTML = letterGuessed;
}
}
//Display underscores on page representing each word in the random word
wordDisplay.innerHTML = answerList;
//Display number of letters in the random word on the page
var remainingLetters = wordChoice.length;
letterCount.innerHTML = "The word is " + remainingLetters +
" letters long";
}
// 2. Take the player’s guess.
function buttonPress(e) {
letterClicked = e.target.textContent;
document.getElementById("your-guess").innerHTML = "You guessed the letter " + letterClicked;
//fix issue with clicking divs
}
// If the player wants to quite the game {
// Quit the game
// }
// Grab elements
var numbers = document.querySelector("#numbers");
var guesses = document.querySelector("#guesses");
var wordDisplay = document.querySelector("#words");
var letterCount = document.querySelector(".letters");
var newGame = document.querySelector("#play");
var letterBoxes = document.querySelector("#alphabet");
To get a letter in buttonPress you are able to use e.toElement.textContent.
I did some solution, but it's not a great example, i think.
let words = [ "TERNARY"], guessesLeft, chosenWord;
let getRandomWord = words => {
return words[Math.floor(Math.random()*words.length)];
}, updateGuesses = count => {
guesses.innerText = count;
guessesLeft = count;
}, updateWords = word => {
document.getElementById('words').innerHTML = word;
}, hideAlphabet = () => alphabet.style.display = 'none',
setGameStatus = status => document.getElementById("status").innerHTML = status;
play.addEventListener('click', e => {
e.target.style.display = 'none'; // hide when game started.
alphabet.style.display = 'block';
chosenWord = getRandomWord(words);
updateGuesses(chosenWord.length);
updateWords(String("*").repeat(chosenWord.length))
});
alphabet.addEventListener('click', e => {
let letter = e.toElement.textContent;
e.toElement.disabled = true;
if (!new RegExp(letter).test(chosenWord)) {
updateGuesses(guessesLeft -1);
} else {
let newString = document.getElementById('words').innerHTML.split(''), indexesOfALetter = [];
for(let i = 0; i < chosenWord.length; i += 1) // here for is a fastest way.
if (chosenWord[i] === letter) indexesOfALetter.push(i);
indexesOfALetter.forEach(i => newString[i] = letter);
updateWords(newString.join(''));
}
if (!/\*/.test(document.getElementById('words').innerHTML)) {
hideAlphabet();
setGameStatus("Congratulations! You won that game");
}
if (guessesLeft < 1) {
hideAlphabet();
setGameStatus("Unfortunately, you lost the game ;(");
updateWords(chosenWord);
}
});
body {
margin: 0 auto;
width: 1000px;
font-size: 20px;
color: black;
}
#header {
margin: 20px;
}
#alphabet {
display: none;
margin: 20px;
}
button {
border: 2px solid blue;
font-size: 20px;
}
#words {
font-size: 30px;
margin: 10px;
letter-spacing: 20px;
}
#play {
margin: 20px;
}
<div id="container">
<div id="header">
<p class="welcome">Welcome to Wheel of Fortune!</p>
<!-- The user will be given a number of choices and with each wrong choice, they lose a turn -->
<p class="lives">You have <span id="guesses">0</span> guesses left</p>
<span id="words"></span><br>
<button id="play">Play</button>
</div>
<div id="alphabet">
<button>A</button>
<button>B</button>
<button>C</button>
<button>D</button>
<button>E</button>
<button>F</button>
<button>G</button>
<button>H</button>
<button>I</button>
<button>J</button>
<button>K</button>
<button>L</button>
<button>M</button>
<br>
<button>N</button>
<button>O</button>
<button>P</button>
<button>Q</button>
<button>R</button>
<button>S</button>
<button>T</button>
<button>U</button>
<button>V</button>
<button>W</button>
<button>X</button>
<button>Y</button>
<button>Z</button>
</div>
<span id="status"></span>
</div>

How can I update attributes with jQuery?

$(document).ready(function() {
var hero_image = new Array();
hero_image[0] = new Image();
hero_image[0].src = 'assets/images/link.png';
hero_image[0].id = 'image';
hero_image[1] = new Image();
hero_image[1].src = 'assets/images/bongo.png';
hero_image[1].id = 'image';
hero_image[2] = new Image();
hero_image[2].src = 'assets/images/gandondorf.jpg';
hero_image[2].id = 'image';
hero_image[3] = new Image();
hero_image[3].src = 'assets/images/queen.png';
hero_image[3].id = 'image';
var young_hero = ["Link", "Bongo Bongo", "Gandondorf", "Queen Gohma"];
var health = [100, 70, 120, 50];
var attack_power = [];
var counter_power = [];
console.log(hero_image[0]);
function it_is_over_9000(){
for (var i = 0; i < young_hero.length; i++) {
var x = Math.floor(Math.random(attack_power)*20) + 3;
var y = Math.floor(Math.random(attack_power)*10) + 3;
attack_power.push(x);
counter_power.push(y);
}
}
function ready_board(){
it_is_over_9000();
for (var i = 0; i < young_hero.length; i++) {
var hero_btns = $("<button>");
hero_btns.addClass("hero hero_button");
hero_btns.attr({
"data-name": young_hero[i],
"data-health": health[i],
"data-image": hero_image[i],
"data-attack": attack_power[i],
"data-counter": counter_power[i],
"data-index": i
});
hero_btns.text(young_hero[i]);
hero_btns.append(hero_image[i]);
hero_btns.append(health[i]);
$("#buttons").append(hero_btns);
}
}
function char(){
$(".hero_button").on("click", function() {
var hero = $(this);
var hero_select = hero.data('index');
for (var i = 0; i < young_hero.length; i++) {
//var attack = ;
if (i != hero_select){
var enemies = $("<button>");
enemies.addClass("hero enemy");
enemies.attr({
"data-power" : it_is_over_9000(),
"data-name": young_hero[i],
"data-health": health[i],
"data-image": hero_image[i],
"data-attack": attack_power[i],
"data-counter": counter_power[i],
"data-index": i
});
enemies.text(young_hero[i]);
enemies.append(hero_image[i]);
enemies.append(health[i]);
$("#battle").append(enemies);
}
}
$("#buttons").html($(this).data('name','health','image'));
defender();
});
}
function defender(){
$(".enemy").on("click", function() {
var enemy = $(this);
var enemy_select = enemy.data("index");
console.log(enemy_select);
for (var i = 0; i < young_hero.length; i++) {
if (i == enemy_select) {
var defender = $("<button>");
defender.addClass("hero defender");
defender.attr({
"data-name": young_hero[i],
"data-health": health[i],
"data-image": hero_image[i],
"data-attack": attack_power[i],
"data-counter": counter_power[i],
"data-index": i
});
defender.text(young_hero[i]);
defender.append(hero_image[i]);
defender.append(health[i]);
$("#defend").append(defender);
$(this).remove();
}
}
});
}
$(".defend_button").on("click" , function(){
if($(".defender").data("health") == 0){
$(".defender").remove();
}
$(".defender").attr({
"data-health": $(".defender").data("health") - $(".hero_button").data("attack")
});
});
ready_board();
char();
});
I am trying to make a RPG game and I have the characters being generated the way I want them too but on the $(".defend_button").on("click" , function() at the end it doesn't update the data-health as it should. It only updates once but upon many clicks on the defend-button it doesn't update past the first time.
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Zelda</title>
<script type='text/javascript' src='https://code.jquery.com/jquery-2.2.0.min.js'></script>
<script type = "text/javascript" src = "assets/javascript/game.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="assets/css/style.css">
</head>
<style type="text/css">
.hero { width: 125px; height:150px; border-style: solid; padding: 2px; float: left; margin: 2px; float: left; }
.letter-button-color { color: darkcyan; }
.fridge-color { color: orange; }
#display { margin-top:78px; height:500px; width:220px; margin-left:60px; }
#buttons { padding-top:60px; }
#clear { margin-left: 20px; font-size: 25px; color: black; border-style: solid; width: 100px; }
#image{width: 100px; height: 100px; margin-left: 10px; }
</style>
<body>
<div class="row">
<div class="col-md-8">Select Your Character</div>
</div>
<div class="row">
<div id="buttons" class="col-md-8"></div>
</div>
<div class="row">
<div id="battle" class="col-md-8">
</div>
</div>
<div class="row">
<div class="col-md-8">
<button class="btn btn-primary defend_button">Defend</button>
</div>
</div>
<div class="row">
<div id="defend">
</div>
</div>
</body>
</html>
You have to use .data() to update the health value.
var battleResult = $(".defender").data("health") - $(".hero_button").data("attack");
console.log("battleResult should be: "+battleResult );
$(".defender").data({
"health": battleResult
});
I played a little with your game.
I found how to update the health display below the image too...
Since only updating the data wasn't changing anything on the screen.
So, I left the above code there, for you to see it is effectively working.
But since you have to re-create the button to update health on scrreen... It is kind of useless.
I also fixed the death condition
from if($(".defender").data("health") == 0){
to if($(".defender").data("health") <= 0){
I have to stop here before changing to much things.
See it in CodePen
Check your loop in it_is_over_9000(), because I think it is running uselessly too often.
And a dead defender has to be "buried" (lol).
Because when it is killed, a click on the defend button is kind of ressurrecting it.
;)
Try setting the attribute like this. Also, I recommend putting $(".defender") in a variable so you aren't requerying it each time.
var defender = $(".defender");
var loweredHealth = defender.data("health") - $(".hero_button").data("attack");
defender.attr('data-health`, loweredHealth);
Update:
It looks like the $('.defender') call will return multiple items. You either need to select a specific defender or iterate through them individually like so:
$('.defender').each(function(i, nextDefender) {
var loweredHealth = nextDefender.data("health") - $(".hero_button").data("attack");
nextDefender.attr('data-health`, loweredHealth);
});`

Categories

Resources