JavaScript : Can't stop a function from running [Tic-Tac-Toe Game] - javascript

My code is intended to be a Tic-Tac-Toe Game. It's working quite alright: the players can make their moves and the program alerts "Player X won!" when the game is over. But I just can't implement the game draw code nor make the main function called game() stops running once a player wins the game.
I'm a beginner at programming, and I've been struggling with this question: how do I stop a function from running in JavaScript? I have to admit that I'm kinda lost, and I'd appreciate all the help.
The code is the one that follows:
//TIC-TAC-TOE
let tl = $('.tl');
let tm = $('.tm');
let tr = $('.tr');
let ml = $('.ml');
let mm = $('.mm');
let mr = $('.mr');
let bl = $('.bl');
let bm = $('.bm');
let br = $('.br');
var tabuleiro = {
'tl': tl,
'tm': tm,
'tr': tr,
'ml': ml,
'mm': mm,
'mr': mr,
'bl': bl,
'bm': bm,
'br': br
};
function game() {
var turno = true;
for (let casa in tabuleiro) {
tabuleiro[casa].on("click", function() {
if (tabuleiro[casa].is(':empty')) {
if (turno == true) {
tabuleiro[casa].append("<img class='cross' src='cross.svg'></img>");
tabuleiro[casa].addClass("x");
turno = false;
} else {
tabuleiro[casa].append("<img class='circle' src='circle.svg'></img>");
tabuleiro[casa].addClass("o");
turno = true;
}
}
ganhou();
});
}
}
function ganhou() {
if (tl.hasClass('x') && tm.hasClass('x') && tr.hasClass('x') ||
ml.hasClass('x') && mm.hasClass('x') && mr.hasClass('x') ||
bl.hasClass('x') && bm.hasClass('x') && br.hasClass('x') ||
tl.hasClass('x') && ml.hasClass('x') && bl.hasClass('x') ||
tm.hasClass('x') && mm.hasClass('x') && bm.hasClass('x') ||
tr.hasClass('x') && mr.hasClass('x') && br.hasClass('x') ||
tl.hasClass('x') && mm.hasClass('x') && br.hasClass('x') ||
tr.hasClass('x') && mm.hasClass('x') && bl.hasClass('x')) {
alert("Jogador 1 Venceu!");
} else if (tl.hasClass('o') && tm.hasClass('o') && tr.hasClass('o') ||
ml.hasClass('o') && mm.hasClass('o') && mr.hasClass('o') ||
bl.hasClass('o') && bm.hasClass('o') && br.hasClass('o') ||
tl.hasClass('o') && ml.hasClass('o') && bl.hasClass('o') ||
tm.hasClass('o') && mm.hasClass('o') && bm.hasClass('o') ||
tr.hasClass('o') && mr.hasClass('o') && br.hasClass('o') ||
tl.hasClass('o') && mm.hasClass('o') && br.hasClass('o') ||
tr.hasClass('o') && mm.hasClass('o') && bl.hasClass('o')) {
alert("Jogador 2 Venceu!");
}
}
game();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

You could use it under the condition that you win, so if you use an if statement, you do If (what you're testing for) { return; }
This will just terminate the function.

There are a few things to consider.
First thing is the case where there are no moves left.
For this, after a space is clicked, perform a check on each space and if all are occupied, then alert the user. This would be a very niave solution, and you can optimize it however you would like (possibly keep track of the number of moves, and if the number of moves is 9, then its a draw.
Also when the game ends, you may want to consider setting a variable playing = false or something like that. Then on click you can check this variable. If it is false then just return. That way when the game ends you can no longer play.
There are many ways of implementing these things, they are just suggestions to solve the problems you are having.

Related

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();

missing ) after argument list when creating a variable right after a for statement

I am trying to create the Bagel game and keep getting missing ) after argument list when I try to create the guess variable right after the for statement. Can someone tell me how to fix this?
alert('Lets play the bagel game! If you can guess my three digit number (with each digit being unique) within 20 turns, then you win! I will only provide you with three hints. Pico, which means one digit is correct, but in the wrong position. Fermi, which means one digit is correct and in the right position. Bagels, which means no digits are correct');
//computer generates number
function numberRange(){
var number = Math.round(Math.random()*1000);
var num =number.toString();
if (number <= 100 || number == 1000){
numberRange();
}
else if (num[0] == num[1] || num[0] == num[2] || num[1]==num[2]){
numberRange();
}
else if (number == undefined || num == undefined){
numberRange();
}else{
var numSave = JSON.stringify(num);
sessionStorage.setItem('number',numSave);
}}
numberRange();
var numGet = sessionStorage.getItem('number');
var numUse = JSON.parse(numGet);
//game start
for (i=1;i<21;i++){
var validNumber = /\d{3}/;
var guess = prompt('Turn ' + i ': Guess a number!');
while (validNumber.test(guess) == false) {
alert('Put in a three digit number!');
var guess = prompt('Turn ' + i ': Guess a number!');
}
if (validNumber.test(guess)){
var guessNum = guess.toString();
if (guessNum[0] == numUse[0] && guessNum[1] && numUse[1] && guessNum[2] == numUse[2]){
alert('Congratulations! You win!');
break
}
else if ((guessNum[0] == numUse[0] || guessNum[1] == numUse[1] || guessNum[2] == numUse[2]) && (guessNum[0] == numUse[1] || guessNum[0] == numUse[2] || guessNum[1] == numUse[0] || guessNum[1] == numUse[2] || guessNum[2] == numUse[0] || guessNum[2] == numUse[3])){
alert('Pico and Fermi!');
}else if(guessNum[0] == numUse[1] || guessNum[0] == numUse[2] || guessNum[1] == numUse[0] || guessNum[1] == numUse[2] || guessNum[2] == numUse[0] || guessNum[2] == numUse[3]){
alert('Pico!');
}else if (guessNum[0] == numUse[0] || guessNum[1] == numUse[1] || guessNum[2] == numUse[2]){
alert('Fermi!');
}else (guessNum[0] != numUse[0] && guessNum[0] != numUse[1] && guessNum[0] != numUse[2] && guessNum[1] != numUse[0] && guessNum[1] != numUse[1] && guessNum[1] != numUse[2] && guessNum[2] != numUse[0] && guessNum[2] != numUse[1] && guessNum[2] != numUse[2]){
alert('Begels!');
}
}
}
I see several issues.
var guess = prompt('Turn ' + i ': Guess a number!');
is missing + after i '
It should be like this:
var guess = prompt('Turn ' + i + ': Guess a number!');
You're also defining the same variable name twice inside the for scope, just do guess = prompt('Turn ' + i ': Guess a number!'); inside the while loop.
I didn't check the rest of the code, but this should get you started.
you seem to have missed a "+" as a part of string concatenation.
prompt('Turn ' + i+': Guess a number!');
instead of
prompt('Turn ' + i': Guess a number!');
What the other folks said (there are 2 places you need + signs, l#s 25, 28) and your final else needs an if before the test clause (L# 41). After that it should at least run. A few other comments:
only var a variable the first time it is declared.
look into switch statements and use them when you have more than 2 options and a default.
try to break up long lines (as in add line feeds) and keep all the code on the screen. Javascript doesn't care at all about white space so use it. Far easier to debug things when you can see it all.
a good editor will find this stuff for you. There are a lot of free ones (Atom, Komodo) that do a decent job of syntax highlighting and error detection.

Card Game can't get my Win and Lose Div to appear in my IF statement

I'm making a card game where you begin and the computer generates a card the player then must press a button either higher lower or equal to guess if the card is higher than the computers or lower or equal.
This is my if statement in my script
if ((playerChoice == "higher") && (myCard2 > myCard) ||
(playerChoice == "lower") && (myCard2 < myCard) ||
(playerChoice == "equal") && (myCard2 == myCard)) {
document.getElementById("Win").innerHTML = "You Win"
} else {
document.getElementById("Lost").innerHTML = "You Lose"
}
Here is my html for the win and lose divs
<div id="Win"></div>
<div id="Lost"></div>
I just don't know why when i choose the higher button and the card is it won't show the You Win and visa versa with all the buttons and for You Lost
You problem is the values are not being set for your javascript variables. Below is the test code I created to demonstrate the problem. You can change the values of the myCard2 and the myCard values and you will see the text change inside your div elements. If you are you using an on click event to gather your user input you will have to make sure it sets the javascript variables in order to make your code work.
jsfiddle example : http://jsfiddle.net/larryjoelane/u8kf796z/5/
/* test code inserted below*/
//set myCard2 value
var myCard2 = 9;
//set myCard value
var myCard = 8;
//set playerChoice value
var playerChoice = "higher";
/*end of test code*/
if ((playerChoice == "higher") && (myCard2 > myCard) ||
( playerChoice == "lower") && (myCard2 < myCard) ||
( playerChoice == "equal") && (myCard2 == myCard))
{
document.getElementById("Win").innerHTML = "You Win"
}
else
{
document.getElementById("Lost").innerHTML = "You Lose"
}

Trouble with basic javascript

I'm trying to do some extremely simple form validation, my current problem is that my window.onload function doesn't call in the function I specify.
When I watch the flow of logic with firebug it just skips to the end of the code.
Here is an example of my code:
window.onload = init;
function init() {
var regForm = document.getElementById("registerform");
regForm.onsubmit = validatepostcode();
}
function validatepostcode() {
var postCode = document.getElementById("postcode");
var postCodeStr = postCode.charAt(0);
var state = document.getElementById("state");
var result = true;
if (postCodeStr == 3 || 8 && state == "Vic") {
result = true;
} else if (postCodeStr == (1 || 2) && state == "NSW") {
result = true;
} else if (postCodeStr == (4 || 9) && state == "QLD") {
result = true;
} else if (postCodeStr == 0 && state == "NT" || state == "ACT") {
result = true;
} else if (postCodeStr == 6 && state == "WA") {
result = true;
} else if (postCodeStr == 5 && state == "SA") {
result = true;
} else if (postCodeStr == 7 && state == "TAS") {
result = true;
} else
result = false;
if (result = false) {
alert("Your postcode does not match your state")
}
}
Five problems:
In init, you have this:
regForm.onsubmit = validatepostcode();
That calls validatepostcode and puts its return value in onsubmit. You probably meant to put the function itself it, not its return value in. Remove the parentheses:
regForm.onsubmit = validatepostcode;
In validatepostcode, you're fetching elements like this:
var postCode = document.getElementById("postcode");
…but then try to use them as values, like this:
var postCodeStr = postCode.charAt(0);
But an element and the current value of that element are not the same thing. More likely, you meant to retrieve the value on the first line:
var postCode = document.getElementById("postcode").value;
Same goes for state.
In validatepostcode, you have lines like this:
} else if (postCodeStr == (1 || 2) && state == "NSW") {
Specifically, 1 || 2 won't work like that. It will look at them like booleans and say, “one or two? well, they're both truthy…true it is!” and you'll essentially be doing
} else if (postCodeStr == true && state == "NSW") {
(Actually, it uses 1, not true, since the first operand was truthy, but that's not the important point here.)
Instead of using that abbreviated notation, you'll have to write it out longhand:
} else if ((postCodeStr == 1 || postCodeStr == 2) && state == "NSW") {
You mixed up = and == here:
if(result=false){
= will set result to false and leave the condition always false. Change it to == to test equality:
if(result==false){
You probably meant to return result at the end to prevent the form from being submitted when there is a validation error. With the other changes applied, you'd get an alert if there was a validation error, but it'd go on submitting anyway. As such, add a return result at the end of the validatepostcode function.

wordwrap for textarea using javascript or jquery

I need functionality that textarea should contain max 5 lines and
each line should contain max 15 chars, when user writes 2 words
e.g. 123456 123456789 and if that line char limit exceeds 15, then
it should bring the 2nd word in next line along with \n char in first line
(means 123456 will be in first line along with \n and 123456789 will be in 2nd)
,
I need to maintain \n(replacing <br>) in my db for some reasons.
i wrote this code, which gives fuzzy result in some conditions
<textarea onkeypress="charCountTextarea('txt1',event,'75','14')" id="txt1"></textarea>
var countLines=0;
var newLines;
function charCountTextarea(textAreaId,e,limit,lineLen)
{
newLines = $("#"+textAreaId).val().split("\n").length;
var t = $("#"+textAreaId)[0];
var lineIndex = t.value.substr(0, t.selectionStart).split("\n").length-1;
//console.log("new lines"+lineIndex);
if(newLines >= 5 && $("#"+textAreaId).val().split("\n")[lineIndex].length>lineLen)
{
if( e.keyCode!=8 && e.keyCode!=46 && e.keyCode!=33 && e.keyCode!=34 && e.keyCode!=35 && e.keyCode!=36 && e.keyCode!=37 && e.keyCode!=38 && e.keyCode!=39 && e.keyCode!=40)
{
e.preventDefault();
return false;
}
}
else
if($("#"+textAreaId).val().split("\n")[lineIndex].length>=lineLen) // which will count the total line char condition
{
console.log($("#"+textAreaId).val().split("\n")[lineIndex][lineLen-1]);
if($("#"+textAreaId).val().split("\n")[lineIndex][lineLen-1].indexOf(" ")==-1 && e.keyCode!=8 && e.keyCode!=46 && e.keyCode!=33 && e.keyCode!=34 && e.keyCode!=35 && e.keyCode!=36 && lineIndex != 4 && newLines<5)
{
// to bring the word in next line
var str = $("#"+textAreaId).val(), replacement = '\n';
str = str.replace(/ ([^ ]*)$/,replacement+'$1');
$("#"+textAreaId).val(str);
}
else
if(e.keyCode!=8 && e.keyCode!=46 && e.keyCode!=33 && e.keyCode!=34 && e.keyCode!=35 && e.keyCode!=36 && lineIndex!=4 && newLines<5)
{
// to insert next line
insertTextAtCaret(document.getElementById(textAreaId), "\n");
}
}
if(e.keyCode == 13 && newLines >= 5)
{
//linesUsed.css('color', 'red');
e.preventDefault();
return false;
}
}
function charCountTextarea(textAreaId,e,limit,lineLen)
{
var code = e.charCode || e.keyCode;
newLines = $("#"+textAreaId).val().split("\n").length;
var t = $("#"+textAreaId)[0];
var lineIndex = t.value.substr(0, t.selectionStart).split("\n").length-1;
console.log('val t :'+$("#"+textAreaId).val()+' line index : '+lineIndex+' new lines '+newLines);
if(lineIndex == 10 && $("#"+textAreaId).val().split("\n")[lineIndex].length>(lineLen+1) && code!=8 && code!=46 && code!=33 && code!=34 && code!=35 && code!=36 && code!=37 && code!=38 && code!=39 && code!=40)
{
$("#"+textAreaId).val(($("#"+textAreaId).val()).substring(0, $("#"+textAreaId).val().length - 1));
alert('You are reached to limit');
return false;
}
if(lineIndex<5)
{
$("#"+textAreaId).val($("#"+textAreaId).val().wordWrap(lineLen, "\n", 0));
}
var countLine1 = $("#"+textAreaId).val().split("\n")[0].length;
if($("#"+textAreaId).val().split("\n")[lineIndex].length>lineLen) // which will count the total line char condition
{
console.log("In condition : ");
if(code!=8 && code!=46 && code!=33 && code!=34 && code!=35 && code!=36 && code!=37 && code!=38 && code!=39 && code!=40)
{
// to insert next line
insertTextAtCaret(document.getElementById(textAreaId), "\n");
}
}
}
You can not know if the input will be fed using keyboard. I could just use the mouse to paste a text there.
I would rely on a function that would constantly check the input and take the action you want, which I would execute using the setInterval() function once the textarea is focused, which then gets cleared using clearInterval() once the textarea loses focus.
And this function would use a RegExp to process the input and split it into necessary lines.
EDIT: Here's what I mean.
$('body').on('focus','#txt1',function(e) {
$(this).data('int',setInterval(checkInput,1));
}).on('blur','#txt1',function(e) {
clearInterval($(this).data('int'));
$(this).removeData('int');
});
function checkInput() {
var val = $('#txt1').val();
// process val here
$('#txt1').val(val);
}

Categories