how can i check winners by using jquery [duplicate] - javascript

This question already has answers here:
JavaScript TicTacToe if... Winner detection
(7 answers)
Closed 2 years ago.
I am tryin to implement a tic tac to game using jquery, and here is my code:
$(document).ready(function() {
let turn = 1;
$(".smallbox").click(function() {
if (turn == 1) {
$(this).text("X");
$(this).addClass("X");
turn = 2;
} else {
$(this).text("O");
$(this).addClass("O");
turn = 1;
}
$("#tune").text(turn);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box" id="mainbox">
<!-- creat 9 small box -->
<div class="smallbox" id="square1"></div>
<div class="smallbox" id="square2"></div>
<div class="smallbox" id="square3"></div>
<div class="smallbox" id="square4"></div>
<div class="smallbox" id="square5"></div>
<div class="smallbox" id="square6"></div>
<div class="smallbox" id="square7"></div>
<div class="smallbox" id="square8"></div>
<div class="smallbox" id="square9"></div>
</div>
however I have difficulty detecting the winner, due to X and Y. Since my code is providing X information but not Y, how can I improve my code in this regard?

$(document).ready(function() {
let gameArray = [];
let turn = 1;
let gameOver = false;
$("#turn").text(turn === 1 ? 'X' : 'O');
$(".smallbox").click(function() {
let squereIndex = $(this).attr('id').replace('square', '') - 1;
if (turn == 1 && !gameOver && gameArray[squereIndex] === undefined) {
$(this).text("X");
$(this).addClass("X");
turn = 2;
gameArray[squereIndex] = 1;
} else if (!gameOver && gameArray[squereIndex] === undefined) {
$(this).text("O");
$(this).addClass("O");
turn = 1;
gameArray[squereIndex] = -1;
}
checkWinner();
$("#turn").text(turn === 1 ? 'X' : 'O')
});
function checkWinner() {
let result;
//check Rows
for (let i = 0; i <= 6; i += 3) {
result = gameArray[i] + (gameArray[i + 1]) + (gameArray[i + 2]);
if (result === 3) {
$("#winner").text('X win');
gameOver = true;
}
if (result === -3) {
$("#winner").text('O win');
gameOver = true;
}
}
//check Columns
for (let i = 0; i <= 3; i++) {
result = gameArray[i] + (gameArray[i + 3]) + (gameArray[i + 6]);
if (result === 3) {
$("#winner").text('X win');
gameOver = true;
}
if (result === -3) {
$("#winner").text('O win');
gameOver = true;
}
}
//check Diagonal
result = gameArray[0] + (gameArray[4]) + (gameArray[8]);
if (result === 3) {
$("#winner").text('X win');
gameOver = true;
}
if (result === -3) {
$("#winner").text('O win');
gameOver = true;
}
result = gameArray[2] + (gameArray[4]) + (gameArray[6]);
if (result === 3) {
$("#winner").text('X win');
gameOver = true;
}
if (result === -3) {
$("#winner").text('O win');
gameOver = true;
}
}
});
.smallbox {
width: 50px;
border: 1px solid black;
height: 35px;
margin: 2px;
text-align: center;
padding-top: 15px;
}
.row-container {
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="box" id="mainbox">
Turn: <span id='turn'></span>
<!-- creat 9 small box -->
<div class='row-container'>
<div class="smallbox" id="square1"></div>
<div class="smallbox" id="square2"></div>
<div class="smallbox" id="square3"></div>
</div>
<div class='row-container'>
<div class="smallbox" id="square4"></div>
<div class="smallbox" id="square5"></div>
<div class="smallbox" id="square6"></div>
</div>
<div class='row-container'>
<div class="smallbox" id="square7"></div>
<div class="smallbox" id="square8"></div>
<div class="smallbox" id="square9"></div>
</div>
<span id='winner'></span>
</div>

Related

Button background changes when the value is 0 and the value is max (jQuery)

I'm trying to figure out how to change the background color of the button when the value is 0 and the maximum value. I have made the code as below but it still doesn't work. Can anyone help me with this problem?
when i add this code in initial conditioning, it doesn't work. When i click + value dissapear
if( sum == 0 ){
$('.btn__decrement').css('background-color', '#dadada');
}
The condition what i want:
$(document).ready(function(){
$(".base-quantity .btn").on("click", function () {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
var sum = 0;
$('.base-quantity input[type="text"]').each(function () {
sum += Number($(this).val());
});
if(sum==0){
$('.btn__decrement').css('background-color', '#dadada');
}else if ($button.hasClass('btn__increment') && sum < 10) {
var newVal = parseFloat(oldValue) + 1;
$('btn__decrement').css('background-color', 'blue');
} else if ($button.hasClass('btn__decrement')) {
// nilai tidak bisa berkurang jika dibawah 0
if (oldValue > 0) {
var newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
} else {
return false;
}
$button.parent().find("input").val(newVal);
});
})
.base-quantity{
background-color: rgba(239,239,239,0.3);
display: flex;
align-items: center;
}
.base-quantity input{
height: 100%;
width: 100%;
text-align: center;
border: none;
background-color: transparent;
}
.base-quantity .btn{
background-color: #cc4645 ;
color: #fff;
border-radius: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="base-quantity">
<button type="button" class="btn btn__decrement">-</button>
<input type="text" id="quantityVal" value="0" disabled>
<button type="button" class="btn btn__increment">+</button>
</div>
when i add this code in initial conditioning, it doesn't work
if( sum == 0 ){
$('btn__decrement').css('background-color', '#dadada');
}
Instead of
$('btn__decrement').css('background-color', '#dadada');
use
$('.btn__decrement').css('background-color', '#dadada');
Update
I don't know what you want to achieve but but add this snap to you code may be it will give you a hint
$(document).ready(function () {
var sum = 0;
if (sum == 0) {
$('.btn__decrement').css('background-color', '#dadada');
}
$('.btn__increment').click(function () {
var oldValue = parseFloat($("#quantityVal").val());
sum = oldValue + 1;
if (sum < 10) {
$('.btn__decrement').css('background-color', 'blue');
}
$("#quantityVal").val(sum);
});
$('.btn__decrement').click(function () {
var oldValue = parseFloat($("#quantityVal").val());
if (sum > 0) {
sum = oldValue - 1;
$('.btn__decrement').css('background-color', 'blue');
}
if (sum == 0) {
$('.btn__decrement').css('background-color', '#dadada');
}
$("#quantityVal").val(sum);
});
})
This is more of a variable hoisting issue, as you have declared var newVal in if blocks so var variable will get hoisted so you will not get an error as a variable is not defined but it will be undefined as you are initializing them in the if-else condition and on the first click, those will not get executed so the value of newVal remains undefined that is why you see blank on the click.
I have provided the fix int the below code ,by the way i am not sure what are you trying to do.
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
.base-quantity{
background-color: rgba(239,239,239,0.3);
display: flex;
align-items: center;
}
.base-quantity input{
height: 100%;
width: 100%;
text-align: center;
border: none;
background-color: transparent;
}
.base-quantity .btn{
background-color: #cc4645 ;
color: #fff;
border-radius: 0;
}
</style>
</head>
<body>
<div class="base-quantity">
<button type="button" class="btn btn__decrement">-</button>
<input type="text" id="quantityVal" value="0" disabled>
<button type="button" class="btn btn__increment">+</button>
</div>
<script>
$(document).ready(function(){
$('.btn__increment').css('background-color', 'blue');
$(".base-quantity .btn").on("click", function () {
var $button = $(this);
var oldValue = $button.parent().find("input").val();
var sum = 0;
var newVal=0;
$('.base-quantity input[type="text"]').each(function () {
sum += Number($(this).val());
});
if ($button.hasClass('btn__increment') && sum < 10) {
newVal = parseFloat(oldValue) + 1;
$('.btn__decrement').css('background-color', 'blue');
} else if ($button.hasClass('btn__decrement')) {
if (oldValue > 0) {
newVal = parseFloat(oldValue) - 1;
} else {
newVal = 0;
}
} else {
return false;
}
if(newVal==0){
clicked=false;
$('.btn__decrement').css('background-color', '#dadada');
$('.btn__increment').css('background-color', 'blue');
}
else if(newVal>0 && newVal<=10){
$('.btn__decrement').css('background-color', 'blue');
}
if(newVal < 10){
$('.btn__increment').css('background-color', 'blue');
}
else if(newVal == 10){
$('.btn__increment').css('background-color', '#dadada');
}
$button.parent().find("input").val(newVal);
});
})
</script>
</body>
</html>

Jquery UI Dragabble is not enabled

class Cell {
constructor(game, index) {
this.isEmpty = false;
this.game = game;
this.index = index;
this.height = (game.height / game.dimension);
this.width = (game.width / game.dimension);
this.id = "cell-" + index;
this.cell = this.createCell();
$("#content").append(this.cell);
if (this.index === this.game.dimension * this.game.dimension - 1) {
this.isEmpty = true;
return;
}
this.setImage();
this.setPosition(this.index)
}
createCell() {
const cell = document.createElement("div");
$(cell).css({
"width": this.height + "px",
"height": this.width + "px",
"position": "absolute",
"border": "1px solid #fff"
})
$(cell).attr("id", this.id);
//On click Move to the Empty Space
$(cell).on("click", () => {
if (this.game.gameStarted) {
let validCells = this.game.checkValidCells();
let compareCells = [];
if (validCells.right) {
compareCells.push(this.game.cells[validCells.right].cell);
}
if (validCells.left || validCells.left === 0) {
compareCells.push(this.game.cells[validCells.left].cell);
}
if (validCells.top || validCells.top === 0) {
compareCells.push(this.game.cells[validCells.top].cell);
}
if (validCells.bottom) {
compareCells.push(this.game.cells[validCells.bottom].cell);
}
let i = this.game.cells.findIndex(item => item.cell === cell);
let j = this.game.findEmptyCell();
if (compareCells.indexOf(cell) != -1) {
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0;
this.game.gameStarted = false;
}
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
}
this.game.dragTheTile();
}
})
return cell;
}
setImage() {
const left = this.width * (this.index % this.game.dimension);
const top = this.height * Math.floor(this.index / this.game.dimension);
const bgPosition = -left + "px" + " " + -top + "px";
const bgSize = this.game.width + "px " + this.game.height + "px"
$(this.cell).css({
"background": 'url(' + this.game.imageSrc + ')',
"background-position" : bgPosition,
"background-size": bgSize
})
}
setPosition(index) {
const {left, top} = this.getPosition(index);
$(this.cell).css({
"left": left + "px",
"top": top + "px"
})
}
makeDraggable(index) {
let emptyCellIndex = this.game.findEmptyCell();
$(this.cell).draggable({
containment: "parent",
snap: this.game.cells[emptyCellIndex],
cursor: "move",
snapMode: "inner",
snapTolerance: 20,
helper: "clone",
opacity: 0.5
})
}
makeDroppable(index) {
$(this.cell).droppable({
drop: (event, ui) => {
let draggedCell;
draggedCell = ui.draggable;
let i = this.game.cells.findIndex(item => item.cell === draggedCell[0]);
let j = this.game.findEmptyCell();
[this.game.cells[i], this.game.cells[j]] = [this.game.cells[j], this.game.cells[i]];
this.game.cells[i].setPosition(i);
this.game.cells[j].setPosition(j);
this.game.clearDrag();
this.game.numberOfMoves++;
$("#moves").html("Moves: " + this.game.numberOfMoves);
if (this.game.checkWin()) {
alert("you won the game!!");
this.game.numberOfMoves = 0;
this.game.gameStarted = false;
} else {
this.game.dragTheTile();
}
}
})
}
getPosition(index) {
return {
left: this.width * (index % this.game.dimension),
top: this.height * Math.floor(index / this.game.dimension)
}
}
}
class GameBoard {
constructor(dimension){
this.dimension = dimension;
this.imageSrc = 'https://i.ibb.co/1XfXq6S/image.jpg'
this.cells = [];
let length = Math.min(window.innerHeight, window.innerWidth);
this.width = length - 100;
this.height = length - 100;
this.setup();
this.gameStarted = false;
this.numberOfMoves = 0;
}
setup() {
for(let i = 0;i < this.dimension * this.dimension; i++) {
this.cells.push(new Cell(this, i));
}
}
shuffle() {
for (let i = this.cells.length -1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
}
}
findEmptyCell() {
return this.cells.findIndex(cell => cell.isEmpty)
}
checkValidCells() {
const emptyCell = this.findEmptyCell(),
topCell = emptyCell - this.dimension,
leftCell = emptyCell - 1,
rightCell = emptyCell + 1,
bottomCell = emptyCell + this.dimension;
const mod = emptyCell % this.dimension;
let left, right, top, bottom;
if (mod != 0) {
left = leftCell;
}
if (mod != this.dimension -1) {
right = rightCell;
}
if (emptyCell >= this.dimension) {
top = topCell;
}
if (emptyCell < this.dimension * (this.dimension - 1)) {
bottom = bottomCell
}
return {right: right, left: left, top: top, bottom: bottom};
}
findPosition(index) {
return this.cells.findIndex(cell => cell.index === index);
}
checkWin() {
for (let i = 0; i < this.cells.length; i++) {
if (i != this.cells[i].index) {
return false;
}
}
return true;
}
clearDrag() {
this.cells.forEach(cell => {
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
dragTheTile() {
this.clearDrag();
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
this.cells[cell].makeDraggable(cell);
this.cells[emptyCellIndex].makeDroppable(cell);
})
}
solve() {
let i;
for (i = 0; i < this.cells.length; i++) {
let j = this.cells[i].index;
if (i != j) {
[this.cells[i], this.cells[j]] = [this.cells[j], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[j].setPosition(j);
i--;
}
if (i === this.cells.length - 1) {
[this.cells[i], this.cells[i - 1]] = [this.cells[i - 1], this.cells[i]];
this.cells[i].setPosition(i);
this.cells[i - 1].setPosition(i - 1);
}
}
}
}
$(document).ready(() => {
let gb;
$("#startGame").on("click", () => {
gb.gameStarted = true;
gb.shuffle();
gb.numberOfMoves = 0;
$("#moves").html("Moves: " + gb.numberOfMoves);
gb.clearDrag();
gb.dragTheTile();
})
$("#solve").on("click", () => {
if (gb.gameStarted) {
gb.solve();
gb.clearDrag();
gb.dragTheTile();
}
})
$("#generate-puzzle").on("click", () => {
let number = parseInt($("#dimension").val());
if(number >= 3 && Number.isInteger(number)) {
gb = new GameBoard(number);
$("#content").css("display", "block");
$("#solve").css("display", "block");
$("#startGame").css("display", "block");
$("#enter-dimension").css("display", "none");
$("#content").css({
width: gb.width + "px",
height : gb.height + "px"
})
} else {
$("#alert").css("display", "block");
}
})
})
body {
background-color: #3d3d3d;
}
#content {
width: 400px;
height : 400px;
background-color: #fff;
margin: auto;
position: relative;
display: none;
}
#startGame {
margin: auto;
display: none;
}
#solve {
margin: auto;
display: none;
}
#alert {
display: none;
}
#moves {
margin: auto;
padding: 5px;
text-align: center;
color: #FFFF00;
}
#enter-dimension {
margin: auto;
}
#label-dimension {
color: #ddd;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- JQuery -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js" integrity="sha512-uto9mlQzrs59VwILcLiRYeLKPPbS/bT71da/OEBYEwcdNUk8jYIy+D176RYoop1Da+f9mvkYrmj5MCLZWEtQuA==" crossorigin="anonymous"></script>
<title>Image Puzzle</title>
</head>
<body>
<div class="container col-md-6">
<div id="moves">
Moves : 0
</div>
<div class="d-flex justify-content-center row">
<div class="col-md-6">
<div class="mt-5" id="enter-dimension">
<form>
<div class="form-group">
<label id="label-dimension" for="dimension">Enter the Dimension of the puzzle</label>
<input type="number" class="form-control" id="dimension">
</div>
<div class="alert alert-danger" id="alert" role="alert">
Enter a Valid Positive Integer Greater than or Equal to 3
</div>
<button type="button" class="btn btn-primary" id="generate-puzzle">Generate the Puzzle</button>
</form>
</div>
</div>
</div>
<div class="row">
<!--The GRid Layout and the tiles -->
<div class="mt-3" id="content">
</div>
</div>
<!--Button to Start the Game -->
<div class="row buttons">
<button type="button" class="btn btn-info mt-2" id="startGame">Start Game</button>
<button type="button" class="btn btn-success mt-2" id="solve">Solve This!</button>
</div>
</div>
</body>
</html>
The puzzle works perfectly but with one issue. If I drag-drop a cell to an empty cell I am unable to drag and drop that tile again to its previous position which is the current empty cell. The way I see it there is a problem somewhere in makeDraggable() and dragTheTile() functions.
When I move a cell with a mouse click I can drag and drop that same cell to its previous position (which is the current empty cell) or If I drag and drop a cell to an empty space I can move it to its previous position (which is the current empty cell) with mouse click. But after dragging the same cell cannot be dragged again. looks like draggable() is disabled for that particular cell.
Once a cell is dragged, The next move it should be a draggable cell (since it is a neighbour cell to the empty cell) When I make it draggable the "ui-draggable" class is added to it but "ui-draggable-handle" class is missing.
The problem was with the function where I cleared the draggable property:
clearDrag() {
this.cells.forEach(cell => {
if($(cell.cell).data('ui-draggable')) $(cell.cell).draggable("destroy");
})
}
The "destroy" method gives some conflicts.
The alternative method I found was to first initialize all the cells with draggable property but disable it in the beginning and enabling it again when I need.
the property used here was "disabled: true" and "disabled: false".
Instead of the dragTheTile() function I wrote a new function called dragTile() as follows:
dragTile() {
this.cells.forEach(cell => {
cell.makeDraggable();
})
const validCells = this.checkValidCells();
let availableCells = [];
if (validCells.right) {
availableCells.push(this.cells[this.findPosition(validCells.right)].index);
}
if (validCells.left || validCells.left === 0) {
availableCells.push(this.cells[this.findPosition(validCells.left)].index);
}
if (validCells.top || validCells.top === 0) {
availableCells.push(this.cells[this.findPosition(validCells.top)].index);
}
if (validCells.bottom) {
availableCells.push(this.cells[this.findPosition(validCells.bottom)].index);
}
let emptyCellIndex = this.findEmptyCell();
availableCells.forEach(cell => {
$(this.cells[cell].cell).draggable({disabled: false});
})
this.cells[emptyCellIndex].makeDroppable(availableCells);
}
This solved the problem very easily.

How to change the content of a span element to that of a variable

I'm doing a rock paper scissors game and most of the coding is done except that I didn't add a functionality to the buttons, no matter what you click on you'll choose paper.
Before adding that functionality I want for the score to be updated on the webpage but whenever it tries to update I get :
Uncaught TypeError: Cannot set property 'textContent' of null
let choices = ["rock", "paper", "scissors"]
let localPlay = "paper"
let cpuChoice;
let scorePlayer = 0
let scoreCPU = 0
let playerPoints = document.getElementById("pScore")
let cpuPoints = document.getElementById("cScore")
function cpuPlay() {
cpuChoice = choices[Math.floor(Math.random() * choices.length)];
return cpuChoice
}
function gameConditions() {
// DRAW
if (localPlay === cpuChoice) {
console.log("draw")
// ROCK
} else if (localPlay === choices[0] && cpuChoice === choices[1]) {
scoreCPU = scoreCPU + 1
return cpuPoints.textContent = scoreCPU;
//cpu
} else if (localPlay === choices[0] && cpuChoice === choices[2]) {
scorePlayer = scorePlayer + 1
return playerPoints.textContent = scorePlayer;
//player
// PAPER
} else if (localPlay === choices[1] && cpuChoice === choices[0]) {
scorePlayer = scorePlayer + 1
return playerPoints.textContent = scorePlayer;
//player
} else if (localPlay === choices[1] && cpuChoice === choices[2]) {
scoreCPU = scoreCPU + 1
return cpuPoints.textContent = scoreCPU;
//cpu
// SCISSORS
} else if (localPlay === choices[2] && cpuChoice === choices[0]) {
scoreCPU = scoreCPU + 1
return cpuPoints.textContent = scoreCPU;
//cpu
} else if (localPlay === choices[2] && cpuChoice === choices[1]) {
scorePlayer = scorePlayer + 1
return playerPoints.textContent = scorePlayer;
//player
// DEBUG
} else {
console.log("not working")
}
}
function shoot() {
cpuPlay();
gameConditions();
console.log(cpuChoice)
imageChanger();
console.log("Player score: " + scorePlayer)
console.log("Cpu score: " + scoreCPU)
}
function imageChanger() {
let cpuImage = document.getElementById("cpuImg")
if (cpuChoice === choices[0]) {
cpuImage.src = "https://rodpa715.github.io/rock-paper-scissors/images/rock.png"
} else if (cpuChoice === choices[1]) {
cpuImage.src = "https://rodpa715.github.io/rock-paper-scissors/images/paper.png"
} else if (cpuChoice === choices[2]) {
cpuImage.src = "https://rodpa715.github.io/rock-paper-scissors/images/scissors.png"
}
}
* {
background-color: #9f85db;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
h1 {
font-size: 24px;
}
h2 {
font-size: 18px;
}
.choices {
display: inline-block;
height: 175px;
width: 175px;
border: 2px solid black;
border-radius: 5px;
padding: 10px;
margin: 10px;
text-align: center;
cursor: pointer;
}
.choices img {
height: 150px;
width: 150px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Rock Paper Scissors</title>
<script type="text/javascript" src="./game.js"></script>
<!--<link href="./style.css" type="text/css" rel="stylesheet">-->
</head>
<body>
<h1>Rock Paper Scissors</h1>
<div class="score">
<h3>Player score: <span id="pScore"> 0 </span></h3>
<h3>Cpu score: <span id="cScore"> 0 </span> </h3>
</div>
<div class="cpu">
<h2>Cpu has chosen :</h2>
<div class="choices"><img id="cpuImg" src=""></div>
</div>
<div class="player">
<h2>Choose one :</h2>
<div class="choices">
<img src="https://rodpa715.github.io/rock-paper-scissors/images/rock.png" onclick="shoot();">
</div>
<div class="choices">
<img src="https://rodpa715.github.io/rock-paper-scissors/images/paper.png" onclick="shoot();">
</div>
<div class="choices">
<img src="https://rodpa715.github.io/rock-paper-scissors/images/scissors.png" onclick="shoot();">
</div>
</div>
</body>
</html>
Here is my JsFiddle here is my Github Repo and here is the GitHub Page
Does it have something to do with the fact that I'm trying to set the .textcontent with a variable?
This is most common problem with JS and HTML. JS will load before whole HTML, so when you trying to make a DOM variables, there is nothing (spans aren't loaded yet). So you can make a onLoad event, that will meke these variables, or don't make these variables, and setting value directly to spans.
Just add your script tag inside body tag instead of head.
It will work!!!
Try this:
else if (localPlay === choices[0] && cpuChoice === choices[1]){
scoreCPU = scoreCPU + 1
cpuPoints.innerText = scoreCPU;
}

How to implement Pagination in [JavaScript]

My Next button on my quiz breaks, if I answer up to a particular question then return back a few questions and then proceed to continue the quiz. After you hit next you won't be able to proceed until you re-select an answer even though there already is an answer selected.
Full JSFiddle:
JSFiddle Link
The issue is with this: (line 121 JSFiddle)
btnNxt.onclick = function() {
if(document.getElementById('btnNxt').hasAttribute('disabled')){
return false;
}
document.getElementById('btnNxt').setAttribute('disabled', true);
buildQuiz(page + 1)
}
When the next button is clicked it disables the attribute. I believe I need to wrap
document.getElementById('btnNxt').setAttribute('disabled', true);
Within an if statement that checks if an answer has already been provided or if it's on a new question
I tried to create something to check if there was a class with the value myAns before setting the attribute but didn't have much success
var element = document.getElementsByClassName('btnAns');
for(var i = 0; i < element.length; i++){
if(element[i].classList.contains('selAnswer')) {
document.getElementById('btnNxt').setAttribute('disabled', true);
break;
} else {
document.getElementById('btnNxt').removeAttribute('disabled');
}
console.log(element[i].classList.contains('selAnswer'));
}
I think you need to put this "if there's already an answer to this question" check into your buildQuiz function, because the selected answer will only be visible to a DOM query after the next (but previously answered) question has been built:
function buildQuiz(pg) {
//code omitted for clarity...
if (page >= 0) {
//code omitted for clarity...
} else {
//code omitted for clarity..
if(!document.querySelector('.selAnswer')) {
document.getElementById('btnNxt').setAttribute('disabled', true);
console.log("no answer yet, disabling button.");
} else {
console.log("success! we found an answer, enabling button.");
}
}
}
}
var startButton = document.getElementById("startButton");
startButton.addEventListener("click", startClick);
function startClick() {
/* Declare global variables to use throughout the quiz */
var output = document.getElementById('output'); //Declare variable output for the element "output"
var btn = document.getElementsByClassName('btnAns'); //Declare a variable for the class "btnAns"
var myObj = ''; //Declare variable myObj as empty string
var page = 0; //Declare variable page and set it to 0
var result = 0; //Declare variable result and set it to 0
var myQueRep = []; //Declare variable myQueRep and set as empty array
loadQuestions(); //Fire off function loadQuestions to bring in data
/* Create a function to retrieve JSON Object. Once object is retrieved fire the buildQuiz function*/
function loadQuestions() { //Create a function called loadQuestions
var xhttp = new XMLHttpRequest(); //Declare variable xhttp and asign it to create a new XMLHttpRequest
xhttp.open('GET', 'https://api.myjson.com/bins/1453rb', true); //
xhttp.onreadystatechange = function() { //
if (this.readyState == 4 && this.status == 200) { //if XMLHttpRequest readyState is 4 and status code is 200
myObj = JSON.parse(this.responseText); //Asign global variable myObj to parse the JSON string into a JavaScript object
buildQuiz(0); //Fire off the build quiz function passing value 0
}
}
xhttp.send(); //Sends the XMLHttpRequest to the server
}
document.getElementById('btnNxt').setAttribute('disabled', true); //Disable the next button until an answer is provided
/* Create a function to build a quiz */
function buildQuiz(pg) { //Create a function called buildQuiz with variable pg that contains the value 0 that was passed through the function when fired
page = pg; // Asign the pg to global variable page
hideshow(); //Fire hideshow function
if (page >= 0) { //Check if variable page is greater or equal to 0
if (myObj.length < (page + 1)) { //Check if the object
page = myObj.length;
var holderHTML = '';
var score = 0;
var answerTxt = '';
for (var item in myObj) {
if (myObj[item].correct == myQueRep[item]) {
score++;
answerTxt = '<p class="correct"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span> ' + myObj[item].answers[myQueRep[item]] + '</p>';
} else {
answerTxt = '<p class="incorrect"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> ' + myObj[item].answers[myQueRep[item]] + '</p>';
}
holderHTML += '<div class="col-sm-12"><h4><strong>Question: ' + myObj[item].question + '</strong></h4>' + answerTxt + '</div>';
}
var outCome = '';
if (score === 0) {
outCome = 'A Dummy!';
} else if ((score / myObj.length) * 100 <= 25) {
outCome = 'Not So Smart';
} else if ((score / myObj.length) * 100 <= 50) {
outCome = ' Kinda Smart!';
} else if ((score / myObj.length) * 100 <= 75) {
outCome = 'Smart!';
} else if ((score / myObj.length) * 100 <= 90) {
outCome = 'Very Smart!';
} else {
outCome = 'Extremely Smart!';
}
output.innerHTML = '<h1>Quiz Results</h1>';
output.innerHTML += '<h3>You Are ' + outCome + '</h3>';
output.innerHTML += '<p><strong>You Got ' + score + ' Answers Correct</p></strong>';
output.innerHTML += '<div class="endScore">' + holderHTML + '</div>';
output.innerHTML += 'Retake Quiz';
} else {
var myQuestion = myObj[page].question;
var myCorrect = myObj[page].correct;
result = myObj[page].answers[myCorrect];
var questionHolder = '';
var yesCor = '';
for (var i in myObj[page].answers) {
var aClass = '';
if (myObj[page].mySel == i) {
aClass = ' selAnswer';
}
if (i == myCorrect) {
yesCor = '*';
} else {
yesCor = '';
}
questionHolder += '<div class="btnAns ' + aClass + '" data-id="' + parseInt(i) + '">' + myObj[page].answers[i] + '</div>';
}
output.innerHTML = 'Question ' + (page + 1) + ' / ' + (myObj.length);
output.innerHTML += '<h4 class="myQ">' + myQuestion + ' </h4>';
output.innerHTML += questionHolder;
for (var x = 0; x < btn.length; x++) {
btn[x].addEventListener('click', myAnswer, false);
}
document.getElementById('quiz-buttons').classList.remove("hidden");
if (!document.querySelector('.selAnswer')) {
document.getElementById('btnNxt').setAttribute('disabled', true);
console.log("no answer yet, disabling button.");
} else {
console.log("success! we found an answer, enabling button.");
}
}
}
}
function myAnswer() {
document.getElementById('btnNxt').removeAttribute('disabled');
var myResult = '';
var iId = this.getAttribute('data-id');
myObj[page].mySel = iId;
if (this.innerText == result) {
myResult = 'correct';
} else {
myResult = 'incorrect';
}
myQueRep[page] = iId;
for (var x = 0; x < btn.length; x++) {
if (iId == x) {
btn[x].classList.add('selAnswer');
} else {
btn[x].classList.remove('selAnswer');
}
}
}
//event listeners
btnPre.onclick = function() {
buildQuiz(page - 1);
document.getElementById('btnNxt').removeAttribute('disabled');
}
btnNxt.onclick = function() {
if (document.getElementById('btnNxt').hasAttribute('disabled')) {
return false;
}
buildQuiz(page + 1)
}
function hideshow() {
if (0 >= page) {
document.getElementById('btnPre').style.display = 'none';
} else {
document.getElementById('btnPre').style.display = 'block';
}
if (myObj.length <= page) {
document.getElementById('quiz-buttons').classList.add('hidden');
}
}
}
#intro h2 {
margin-top: 0;
}
#output h1 {
margin-top: 0;
}
#output h3 {
margin-top: 10px;
}
#output .btn-restart {
margin-top: 10px;
}
.myQ {
font-size: 12px;
font-weight: bold;
}
.btnAns {
border: 1px solid #ddd;
padding: 10px;
text-align: center;
display: block;
font-size: 12px;
background: #fff;
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
}
.endScore p {
font-size: 18px;
}
.endScore .correct {
color: #5cb85c;
}
.endScore .incorrect {
color: #d9534f;
}
.endScore h4 {
margin-bottom: 3px;
}
.endScore span {
font-size: 15px;
}
.btnAns:hover {
background-color: #6c757d;
color: #ffffff;
cursor: pointer;
}
.selAnswer {
background-color: #337ab7;
color: #ffffff;
}
.selAnswer:hover {
background-color: #337ab7;
}
#quiz-buttons {
margin: 1px 0;
}
#quiz-buttons .col-xs-6 {
padding: 0;
}
.quiz {
margin: 50px auto;
}
#media(min-width: 700px) {
.quiz {
width: 650px;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="quiz container">
<div class="quiz-output row">
<div class="col-xs-12">
<div id="output">
<div id="intro">
<h2>Online Quiz</h2>
<p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. </p>
<div id="startButton" class="btn btn-success">Start quiz</div>
</div>
</div>
</div>
</div>
<div id="quiz-buttons" class="row hidden">
<div class="col-xs-6">
<div id="btnPre" class="btn btn-primary pull-left"><span class="glyphicon glyphicon-chevron-left"></span></div>
</div>
<div class="col-xs-6">
<div id="btnNxt" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-chevron-right"></span></div>
</div>
</div>
</div>
I would suggest using the mySel object on your myObj. That way you aren't depending on css and classes, but rather the data your using. Here is a fiddle.
//event listeners
btnPre.onclick = function() {
buildQuiz(page - 1);
document.getElementById('btnNxt').removeAttribute('disabled');
}
btnNxt.onclick = function() {
if (document.getElementById('btnNxt').hasAttribute('disabled')) {
return false;
}
// change is here. Checking to see if next question has been answered.
if (typeof myObj[page + 1].mySel === "undefined") {
document.getElementById('btnNxt').setAttribute('disabled', true);
}
buildQuiz(page + 1)
}

Bug with minimax/computer move selection (TicTacToe/Javascript)?

I'm trying to implement a single player tic tac toe game in which the computer player never loses (forces a draw or wins every time). After searching around it seems using the minimax strategy is pretty standard for this, yet I can't seem to get my algorithm to work correctly, which causes the computer to pick a really bad move. Can anyone help me find where my code has gone wrong?
'O' is the user (max) and 'X' is the computer (min)
EDIT: I re-posted my code, I've fixed some things within getComputerNextMove and a few minor bugs...now my code is finding better scores, but it doesn't always pick up if someone wins (the functions seem to be alright, I think I'm just not checking in the right spots). It also isn't picking the best move. There are some tester functions at the bottom to look at how minimax works/to test game states (winners/draw).
tictactoe.js:
// Setup
var user = new Player('user', 'O', 'green');
var computer = new Player('computer', 'X', 'pink');
window.players = [user, computer];
var gameBoard = new GameBoard();
gameBoard.initializeBoard();
// Trackers for the board and moves
var wins = ['012', '345', '678', '036', '147', '258', '048', '246'];
var moves = 1;
var currentPlayer = players[0];
var game = true;
function Player(name, selector, color) {
this.name = name;
this.moves = [];
this.selector = selector;
this.color = color;
this.makeMove = function(boxId){
if(!gameBoard.isGameOver() && gameBoard.isValidMove(boxId)){
markBox(this, boxId);
this.updateMoves(boxId);
gameBoard.updateBoard(this.selector, boxId);
setTimeout(function () { nextTurn() }, 75);
}
else{
if(gameBoard.isXWinner())
endGame("Computer");
else if(gameBoard.isOWinner())
endGame("You");
else
endGame();
}
}
this.updateMoves = function(boxId){
moves = moves + 1;
this.moves.push(boxId);
}
}
function Square(mark){
this.mark = mark;
this.position;
this.id;
this.score = 0; //for minimax algorithm
}
function GameBoard(){
this.state = [9];
this.initializeBoard = function(){
for(var space = 0; space < 9; space++){
var square = new Square("-");
this.state[space] = square;
this.state[space].position = space;
this.state[space].id = space;
this.state[space].score = 0;
}
}
this.getAvailableSpaces = function(){
var availableSpaces = [];
for(var space = 0; space < this.state.length; space++){
if(this.state[space].mark === "-")
availableSpaces.push(this.state[space]);
}
return availableSpaces;
}
this.updateBoard = function(selector, position){
this.state[position].mark = selector;
}
this.getPositionOfMarks = function(){
var positionOfMarks = [];
for(var sqr=0; sqr<this.state.length; sqr++){
var positionOfMark = {
'position' : this.state[sqr].position,
'mark' : this.state[sqr].mark
}
positionOfMarks.push(positionOfMark);
}
return positionOfMarks;
}
this.getXMovesAsString = function(){
var positionOfMarks = this.getPositionOfMarks();
var xMoves = "";
for(var pm=0; pm < positionOfMarks.length; pm++){
if(positionOfMarks[pm].mark === "X"){
var m = parseInt(positionOfMarks[pm].position);
xMoves += m;
}
}
return xMoves;
}
this.getOMovesAsString = function(){
var positionOfMarks = this.getPositionOfMarks();
var oMoves = "";
for(var pm=0; pm < positionOfMarks.length; pm++){
if(positionOfMarks[pm].mark === "O"){
var m = parseInt(positionOfMarks[pm].position);
oMoves += m;
}
}
return oMoves;
}
this.isValidMove = function(boxId){
return this.state[boxId].mark === "-"
}
this.isOWinner = function(){
var winner = false;
var oMoves = this.getOMovesAsString();
for(var win=0; win<wins.length; win++){
if(oMoves.search(wins[win]) >= 0)
winner = true
}
return winner;
}
this.isXWinner = function(){
var winner = false;
var xMoves = this.getXMovesAsString();
for(var win=0; win<wins.length; win++){
if(xMoves.search(wins[win]) >= 0)
winner = true;
}
return winner;
}
this.isDraw = function(){
var draw = true;
if(!this.isOWinner() && !this.isXWinner()){
for(var space=0; space < this.state.length; space++){
if(this.state[space].mark === "-"){
draw = false;
}
}
}
return draw;
}
this.isGameOver = function(){
var gameOver = false;
if(gameBoard.isDraw() ||
gameBoard.isOWinner() ||
gameBoard.isXWinner())
gameOver = true;
return gameOver;
}
this.printBoardToConsole = function(){
var row1 = [];
var row2 = [];
var row3 = [];
for(var space=0; space<this.state.length; space++){
if(space < 3)
row1.push((this.state[space].mark));
else if(space >= 3 && space < 6)
row2.push((this.state[space].mark));
else
row3.push((this.state[space].mark));
}
console.log(row1);
console.log(row2);
console.log(row3);
}
GameBoard.prototype.clone = function(){
var clone = new GameBoard();
clone.initializeBoard();
for(var square=0; square < this.state.length; square++){
clone.state[square].mark = this.state[square].mark;
clone.state[square].position = this.state[square].position;
clone.state[square].id = this.state[square].id;
clone.state[square].score = this.state[square].score;
}
return clone;
}
}
// Handle clicks
$(".box").click(function (event) {
if (getCurrentPlayer() === user && game == true){
user.makeMove(event.target.id);
}
else overlay("Wait your turn!");
});
// *** MOVES ***
// With every move, these functions update the state of the board
function getComputerNextMove(board){
var availableSquares = board.getAvailableSpaces();
var prevScore = -100000;
var bestMove;
for(var square = 0; square < availableSquares.length; square++){
var gameBoardChild = board.clone();
gameBoardChild.updateBoard("X", availableSquares[square].position);
console.log("gameBoardChild: " + gameBoardChild.printBoardToConsole());
console.log("===================");
var currentScore = min(gameBoardChild);
console.log("Child Score: " + currentScore);
if(currentScore > prevScore){
prevScore = currentScore;
bestMove = availableSquares[square].position;
console.log("Best Move: " + bestMove);
}
}
console.log("====================================");
return bestMove;
}
function max(board){
if(board.isOWinner()) return 1;
else if(board.isXWinner()) return -1;
else if(board.isDraw()) return 0;
var availableSquares = board.getAvailableSpaces();
var bestScore = -100000;
for(var square=0; square<availableSquares.length; square++){
var gameBoardChild = board.clone();
gameBoardChild.updateBoard("O", availableSquares[square].position);
var move = min(gameBoardChild);
if(move > bestScore)
bestScore = move;
}
return bestScore;
}
function min(board){
if(board.isOWinner()) return 1;
else if(board.isXWinner()) return -1;
else if(board.isDraw()) return 0;
var availableSquares = board.getAvailableSpaces();
var bestScore = 100000;
for(var square=0; square<availableSquares.length; square++){
var gameBoardChild = board.clone();
gameBoardChild.updateBoard("X", availableSquares[square].position);
var move = max(gameBoardChild);
if(move < bestScore)
bestScore = move;
}
return bestScore;
}
function markBox(player, boxId) {
$("#" + boxId).text(player.selector).addClass(player.color);
}
// *** SETTERS & GETTERS
function getCurrentPlayer() {
return currentPlayer;
}
function setCurrentPlayer(player) {
currentPlayer = player;
return currentPlayer;
}
function nextTurn() {
if(!gameBoard.isGameOver()){
if (getCurrentPlayer() === user) {
setCurrentPlayer(computer);
computer.makeMove(getComputerNextMove(gameBoard));
}
else setCurrentPlayer(user);
}
else{
if(gameBoard.isOWinner())
endGame("You");
else if(gameBoard.isXWinner())
endGame("Computer");
else
endGame();
}
}
function endGame(winner) {
game = false;
if (winner) {
overlay(winner.name + " wins!");
} else overlay("It's a draw!");
}
//Toggles info box (to avoid using alerts)
function overlay(message) {
$("#info").text(message);
$el = $("#overlay");
$el.toggle();
}
function buildTestBoard(test){
var board = new GameBoard();
board.initializeBoard();
if(test === "minimax"){
board.updateBoard("O", 0);
board.updateBoard("O", 2);
board.updateBoard("O", 4);
board.updateBoard("O", 8);
board.updateBoard("X", 1);
board.updateBoard("X", 6);
board.updateBoard("X", 7);
}
else if(test === "xwin"){
board.updateBoard("X", 6);
board.updateBoard("X", 4);
board.updateBoard("X", 2);
}
board.printBoardToConsole();
return board;
}
function testMinimax(){
var board = buildTestBoard("minimax");
var move = getComputerNextMove(board);
console.log("Best move: " + move);
}
function testWinner(){
var board = buildTestBoard("xwin");
return board.isXWinner();
}
index.html:
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/main.css">
<script src="js/vendor/modernizr-2.6.2.min.js"></script>
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an <strong>outdated</strong> browser. Please
upgrade your browser or
activate Google Chrome Frame
to improve your experience.
</p>
<![endif]-->
<h2 id="title">Single Player Tic Tac Toe</h2>
<div id='0' class='box'></div>
<div id='1' class='box'></div>
<div id='2' class='box'></div>
<br />
<div id='3' class='box'></div>
<div id='4' class='box'></div>
<div id='5' class='box'></div>
<br />
<div id='6' class='box'></div>
<div id='7' class='box'></div>
<div id='8' class='box'></div>
<div id="overlay">
<div>
<p id="info"></p>
</div>
</div>
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
<script>
var _gaq=[['_setAccount','UA-XXXXX-X'],['_trackPageview']];
(function(d,t){var g=d.createElement(t),s=d.getElementsByTagName(t)[0];
g.src='//www.google-analytics.com/ga.js';
s.parentNode.insertBefore(g,s)}(document,'script'));
</script>
</body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.9.1.min.js"><\/script>')</script>
<script src="js/plugins.js"></script>
<script src="js/main.js"></script>
<script src="js/game/tictactoe.js"></script>
</html>
css:
.box {
width:100px;
height:100px;
display:inline-block;
background:#eee;
margin:3px 1px;
text-align:center;
font-size:24px;
font-family:arial;
vertical-align:bottom;
line-height:450%
}
.box:hover {
cursor: pointer;
}
a {
text-decoration:none;
}
.label {
position:relative;
bottom:0;
right:0
}
.green {
background:#90EE90;
}
.pink {
background:#FDCBBB;
}
.credit {
color:#333;
font-family:arial;
font-size:13px;
margin-top:40px;
}
#overlay {
position: absolute;
left: 300px;
top: 0px;
width:20%;
height:20%;
text-align:center;
z-index: 1000;
}
#overlay div {
width:100px;
margin: 100px auto;
background-color: #fff;
border:1px solid #000;
padding:15px;
text-align:center;
align: right;
}

Categories

Resources