Grid of rectangle objects in p5.js - javascript

I am trying to create a path finding maze where we can add a source , a destination and walls on a grid of rectangular objects.The source , destination and walls can we added by clicking on a rectangular object.I wrote the following code in p5.js.
var rows = 20;
var cols = 20;
var source =0;
var destination =0;
var grid = new Array(cols);
function setup() {
createCanvas(400, 400);
for(var i=0;i<cols ; i++)
{
grid[i] = new Array(rows);
}
for(var j=0;j<cols;j++)
{
for(var k=0;k<rows;k++)
{
grid[j][k] = new node();
}
}
}
function draw()
{
for(var j=0;j<cols;j++)
{
for(var k=0;k<rows;k++)
{
grid[j][k].display(j*20,k*20);
}
}
}
function mouseClicked()
{
for(var j=0;j<cols;j++)
{
for(var k=0;k<rows;k++)
{
if((mouseX > (j)*20 && mouseX< (j+1) *20 )&& (mouseY > (k)*20 && mouseY< (k+1) *20 ))
{
grid[j][k].clicked();
}
}
}
}
class node
{constructor()
{this.value =255 ;}
display(x,y){
rect(x,y,20,20);
fill(this.value);
}
clicked() {
if(source == 1 ){
this.value = color(242, 39, 39);
source = 0;
}
else if(destination ==1){
this.value =color(254,200 ,150);
destination = 0;
}
else{if (this.value === 0) {
this.value = 255;
} else {
this.value = 0;
} }}}
function sourceee(){
if (source=== 0) {
source = 1;
} else {
source = 0;
}
}
function destinations(){
if (destination=== 0) {
destination = 1;
} else {
destination = 0;
}
}
This code first creates a 1d array which i named as cols.
Then I use a loop to add an array inside an array as rows.
So each col will have number of rows. Now each array is assigned with an object of class node.
so i,j combination uniquely identifies a particular object.Next in the draw() i am calling the display function for each object in my grid by supplying j,k values using loops.The display function takes the x,y position as arguments and gives me an square by using rect() function. I am supplying the arguments as multiplied by 20 of my unique row and col which identifies my object. The height and width are both 20,20 so that it create an square of size 20*20.The mouseclicked() function should colour the object which i click upon.Now the error here it colours the object below it instead.I can't use the hack of doing -1 to my k value because then it would never work on the first line of my grid.
I tried all the different ways from my understanding the problem has something to do with the arrangement of object in the grid the object [1][0] seems to be arranged before [0][0] but i don't know what exactly is the error in the code.
supporting HTML code:
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js example</title>
<style>
body {
padding: 0;
margin: 0;
}
#src{
top:500px;
left:10px;
position:absolute;
}
#des{
top:500px;
left:100px;
position: absolute;
}
#gri{
top:500px;
left:200px;
position: absolute;
}
</style>
<script src="../p5.js"></script>
<script src="../addons/p5.sound.min.js"></script>
<script src="sketch.js"></script>
</head>
<body>
<main>
</main>
<button type="button" id= "src" onclick="sourceee()">Source</button>
<button type="button" id= "des" onclick="destinations()">Destination</button>
</body>
<script>
</script>
</html>

The issue that causes the grid that is clicked to not be colored is in the display function
display(x,y){
rect(x,y,20,20);
fill(this.value);
}
Notice that fill is called after rect which causes the grid rectangle to be filled according to the previous node.
To get the clicked grid rectangle to be filled switch the order of the calls like this:
display(x,y){
fill(this.value);
rect(x,y,20,20);
}
The code could be rewritten so that the node object contains its own fill value and coordinates. This would make the connection between the color and position of the grid node more obvious.

Related

I have trouble hiding elements in my game if they don't match

I am working on a memory game and I asked a previous question earlier which was answered. I've had this problem and I haven't been able to find a solution with effort. So it's a memory game and when the cards are clicked, they are pushed into an array which can hold two elements at max (you can only click two cards) and then the two elements' frontSrc is checked if they are the same. I set that using an expando property. If so, have them visible and then clear the array so I can do more comparisons. However, it doesn't seem to be working as intended. I'll attach a video below. I've tried using timeout to set the length again, but that didn't work. It works for the first cards, but the other ones after that, it doesn't work.
Here is my code.
<!DOCTYPE html>
<!--
Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
Click nbfs://nbhost/SystemFileSystem/Templates/Other/html.html to edit this template
-->
<html>
<head>
<title>TODO supply a title</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
.card{
width: 35%;
}
#cards{
display: grid;
grid-template-columns:25% 25% 25% 25%;
row-gap: 25px;
}
</style>
</head>
<body onload="init()">
<section id="cards">
</section>
<script>
var arrCards = [];
var arrShowedCards = [];
//appendElements();
function init(){
createCards();
shuffleCards();
appendElements();
}
function createCards(){
var arrCardNames = ["Mouse","Penguin","Pop","Mouse","Penguin","Pop"];
for(var i = 0; i<6; i++){
var card = document.createElement("IMG");
card.src = "Images/red_back.png";
card.className = "card";
card.frontSrc = "Images/" + arrCardNames[i] + ".png";
card.id = "card" + i;
card.addEventListener("click", showCard);
document.getElementById("cards").appendChild(card);
arrCards.push(card);
}
}
function shuffleCards(){
for (let i = arrCards.length-1; i > 0; i--)
{
const j = Math.floor(Math.random() * (i + 1));
const temp = arrCards[i];
arrCards[i] = arrCards[j];
arrCards[j] = temp;
}
return arrCards;
}
function appendElements(){
for(var i = 0; i<arrCards.length; i++){
document.getElementById("cards").appendChild(arrCards[i]);
}
}
function showCard(){
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if(arrShowedCards.length === 2){
if(arrShowedCards[0].frontSrc === arrShowedCards[1].frontSrc){
console.log("Match!");
arrShowedCards = [];
}
else{
console.log("No match!");
setTimeout(function(){
arrShowedCards[0].src = sourceString;
arrShowedCards[1].src = sourceString;
}, 1000);
}
}
}
</script>
</body>
</html>
I am not sure how come it doesn't work for it for the other cards.
Here is the video.
https://drive.google.com/file/d/1aRPfLALHvTKjawGaiRgD1d0hWQT3BPDQ/view
If anyone finds a better way to approach this, let me know.
Thanks!
I think when not match, you need to reset arrShowedCards otherwise its length will be greater than 2 forever.
function showCard() {
var sourceString = "Images/red_back.png";
this.src = this.frontSrc;
arrShowedCards.push(this);
if (arrShowedCards.length === 2) {
var a = arrShowedCards[0], b = arrShowedCards[1];
arrShowedCards.length = 0;
if (a.frontSrc === b.frontSrc) {
console.log("Match!");
} else {
console.log("No match!");
setTimeout(function () {
a.src = sourceString;
b.src = sourceString;
}, 1000);
}
}
}

Javascript Can Push() and Pop() and Image Replacement Work within an Array

Can Push() and Pop() and Image Replacement Work within an Array?
8th Gr math teacher attempting to create a slide show of question images that pop() and push() through an image array based on student responses. If the student answers correctly the question is popped, but if they answer incorrectly it is added to the end of the queue. Additionally, since deleting elements in the DOM is bad, I am replacing the current image's src and id with that of the next element in queue. The array is then popped and pushed along, but whenever I enter in the incorrect answer twice the same image appears.
I have moved the global variable that holds the array, domEls, inside of the function retrieveAnsForImage to force it to randomize the images in the array. When I do this, the images change correctly so I believe it is the push() and pop() commands.
I included a snippet that doesn't work here, but works like a champ in Notepad ++. I just took a crash course in Javascript, HTML and CSS last month on Codecademy, I am very new to this. Thank you for reading.
//Jquery
$(document).ready(function() {
$(function() {
$('img.card').on('contextmenu', function(e) {
e.preventDefault();
//alert(this.id);
openPrompt(this.id);
});
});
});
//Provide and Shuffle array function
function shuffleImgs() {
var imgArr = [
"image1",
"image2",
"image3",
"image4",
"image5",
"image6",
"image7",
"image8",
"image9"
];
var currentIndex = imgArr.length, temporaryValue, randomIndex;
// While there remain elements to shuffle...
while (0 !== currentIndex) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex -= 1;
// And swap it with the current element.
temporaryValue = imgArr[currentIndex];
imgArr[currentIndex] = imgArr[randomIndex];
imgArr[randomIndex] = temporaryValue;
}
alert("shuffle");
return imgArr;
}
function arrStack() {
var imgArr = shuffleImgs();
//Map over the array to create Dom elements
var domElements = imgArr.map(function (imgName, index) {
var cardDiv = document.createElement('div');
var cardImage = document.createElement('img');
//Add img id and class
cardImage.id = imgName;
cardImage.classList.add('card');
//Set img source
cardImage.src = `images/${imgName}.jpg`;
//Put it all together
cardDiv.appendChild(cardImage);
return cardDiv;
});
//this notation to call nested function for Global var stack
this.nDomElements = function () {
stackDomEl = domElements;
return stackDomEl;
}
//Display last element in array
//this notation to call the nested function from outside the function
this.nDisplayLastArr = function displayLastArr() {
var lastImgArr = domElements[domElements.length - 1];
//alert(lastImgArr);
//Append the elements to the DOM
var modal = document.querySelector('div.modal');
modal.appendChild(lastImgArr);
return lastImgArr; //Use brackets when your are returning more than one variable
}
}
//Function called from Jquery to open prompt to answer question
function openPrompt(imageId) {
var userAns = prompt("Please enter your answer below and click OK");
if (userAns == null || userAns == "") {
alert("User cancelled the prompt. Exit and please try again!");
}
else {
/*Vain hope that I can pass imageId from click event through the user prompt
to the answer checking function retrieveAnsForImage*/
retrieveAnsForImage(imageId, userAns); //out of scope?
}
}
//Global variable
func = new arrStack();
window.domEls = func.nDomElements();
//Compare user responses with the question image by use of the click image id
function retrieveAnsForImage(imageId, userAns) {
//Change these variables to the correct answer whenever this website is reused in other assignments
var ansImage1 = "1";
var ansImage2 = "2";
var ansImage3 = "3";
var ansImage4 = "4";
var ansImage5 = "5";
var ansImage6 = "6";
var ansImage7 = "7";
var ansImage8 = "8";
var ansImage9 = "9";
//Give students a second chance to retry a question
//var hintCounter = 0; //include a while statement above the if statements to allow students a retry
/*Compare user response with correct case answer and correct clicked image.
Students may enter the right answer for the wrong image hence the &&.
Images will always be refered to as image1, image2, etc.*/
if (userAns === ansImage1 && imageId === "image1") {
correctAns(imageId);
}
else if (userAns === ansImage2 && imageId === "image2") {
correctAns(imageId);
}
else if (userAns === ansImage3 && imageId === "image3") {
correctAns(imageId);
}
else if (userAns === ansImage4 && imageId === "image4") {
correctAns(imageId);
}
else if (userAns === ansImage5 && imageId === "image5") {
correctAns(imageId);
}
else if (userAns === ansImage6 && imageId === "image6") {
correctAns(imageId);
}
else if (userAns === ansImage7 && imageId === "image7") {
correctAns(imageId);
}
else if (userAns === ansImage8 && imageId === "image8") {
correctAns(imageId);
}
else if (userAns === ansImage9 && imageId === "image9") {
correctAns(imageId);
}
else {
window.alert("Incorrect Answer");
incorrectAns();
}
function correctAns(){
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change im
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
domEls.pop();
//Think about when the array is completely gone
//while domEls.length !== 0;
}
function incorrectAns(){
//Last element in array
var LastElArr = domEls[domEls.length - 1];
//Second to last element in array
var SecLastElArr = domEls[domEls.length - 2];
//Pull image id from second to last element in array
var nextImgId = SecLastElArr.querySelector("div > img").id;
//Pull image id from document
var imgId = document.querySelector("div > img").id;
//Student incorrect answer change image src and id to next element in queue
document.getElementById(imgId).src = `images/${nextImgId}.jpg`;
document.getElementById(imgId).id = nextImgId;
//Remove last element in array
domEls.pop();
//move the last element to the first element in the array for another attempt
domEls.push(LastElArr);
alert(domEls.length);
}
}
function overlay() {
var el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
#overlay {
visibility: hidden;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
text-align:center;
z-index: 1000;
background-color: rgba(0,191, 255, 0.8);
}
#overlay div {
width:70%;
margin: 10% auto;
background-color: #fff;
border:1px solid #000;
padding:15px;
text-align: center;
}
body {
height:100%;
margin:0;
padding:0;
}
#close-img {
float: right;
clear: right;
width: 30px;
height: 30px;
bottom: 0;
right: 0;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<span> "Left click to view any questions. Right click (two finger tap) to answer the question and claim the tile. Each player must claim 4 tiles to successfully complete the assignment."</span>
<link href="https://fonts.googleapis.com/css?family=Oswald:300,700|Varela+Round" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="Stack Rnd Temp.css">-->
<script type="text/javascript" src="Stack Rnd Temp.js"></script>
<script src="jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="StackRndTempjq.js"></script>
</head>
<body>
<div class="title">
<h1></h1>
</div>
<div id="gameboard"> <!--Container for all nine divs-->
<a href='#' onclick='overlay()'>Click here to show the overlay</a>
</div>
<div class="modal" id="overlay">
<p> "Right click to answer the question"</p>
<script>
func = new arrStack();
func.nDisplayLastArr();
</script>
<img src="images/close.png" id="close-img" onclick="overlay()">
</div>
</body>
</html>
Your issue is that pop removes the last element from the array while push adds the element to end of the array.
What you probably want to do is use shift to remove the the first element from the array and pop it back to the end if the answer is wrong.
Alternately, you could pop the last element and use unshift to insert back into the beginning of you want to work in the other direction.
Here's a quick mockup without images.
var currentTest = null;
function getTest() {
$('#answer').html("").hide();
if (tests.length > 0) {
currentTest = tests.shift(); // remove the first question
$('#question').fadeIn(450).html(currentTest.q);
return currentTest;
} else {
$('#answer').html("Finished").fadeIn(500);
$('#btnCorrect').unbind();
$('#btnWrong').unbind();
}
}
var tests = [];
for (var i = 0; i < 5; i++) {
var question = "Question " + i;
var answer = "Answer " + i;
tests.push({
q: question,
a: answer
});
}
$('#btnCorrect').click(function() {
$('#question').hide();
$('#answer').fadeIn(450).html("Correct!");
window.setTimeout(getTest, 750);
});
$('#btnWrong').click(function() {
$('#question').hide();
tests.push(currentTest); // put the question back in the array
$('#answer').fadeIn(450).html("Incorrect!");
window.setTimeout(getTest, 750);
});
$(document).ready(function() {
getTest();
})
* {
font-family: arial;
}
#panel {
height: 50px;
}
#answer {
border: 1px solid #cccccc;
background: #dedede;
width: 400px;
}
#question {
border: 1px solid #999999;
background: #dedede;
width: 400px;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
<body>
<div id="panel">
<div id="answer"></div>
<div id="question"></div>
</div>
<input id="btnCorrect" value="Mock Correct Answer" type="button">
<input id="btnWrong" value="Mock Wrong Answer" type="button">
</body>
</html>

Clone HTML elements with JS

Trying to set up a Tic-Tac-Toe board based on JS input with an alert. The alert never shows up, and the HTML is never rendered... what am I missing?
ALL HTML
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tic Tac Toe! (and more...)</title>
<meta name="description" content="Tic Tac Toe">
<meta name="author" content="SinSysOnline">
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="js.js"></script>
<style>
body{
font-family:"Lucida Console", Monaco, monospace;
}
td{
border-right:1px solid #000;
border-bottom:1px solid #000;
width:100px;
height:100px;
text-align:center;
font-size:72px;
}
td:last-child{
border-right:none;
border-bottom:1px solid #000;
}
tr:last-child td{
border-bottom:none;
}
</style>
</head>
<body>
<div id="dashboard">
<input type="text" value="How large is your grid? (default 3)" size="35" />
</div>
<table id="board">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</table>
</body>
</html>
ALL JS (minus jQuery)
/* Sadly, there is a very well known algorithm to ensure one NEVER loses at
tic-tac-toe. Ties, perhaps, but if you play right you can NEVER LOSE.
I will not institue this cheap shot into my program, and this will be
a computer vs you. I will add in potential moves :-) */
(function($) {
function create(x){
var board = [];
for(var i=0;i<x;i++){
var tempArr = [];
for(var j=0;j<x;j++){ tempArr[j] = ""; }
board.push(tempArr);
}
$('#board tr').clone(x);
return board;
}
var x = prompt("How large would you like your grid? (3-10)");
var board = create(x);
})(jQuery);
I've tried adding the JS to the bottom of my body... just kind of confused here. I know JS inside and out... except for DOM manipulation...
you didn't do any thing with your cloned element!
if you want to dynamically generate a table
the code should be like this
var $board = $('#board');
var td = "<td></td>", $tr = $("<tr></tr>");
function create(x) {
$board.empty();
var arr = [];
for(var i = 0; i < x; i++) {
arr.push(td);
}
var $trCloned = $tr.clone().append(arr.join(''));
for(var j = 0; j < x; j++) {
$board.append($trCloned);
}
}
Here is the fiddle
// JQuery
function create(board, x)
{
var row = $("<tr></tr>");
var i;
for (i = 0; i != x; i++) row.append ($("<td>x</td>")); // create a row
for (i = 0; i != x; i++) $('#'+board).append(row.clone()); // then the board
}
// sample use
var x = window.prompt ("How much, boss?");
create('board', x);
// html
<table id='board' />
I've put an 'x' inside the cells so that the board is visible
As Fiddle works, this No-Prompt problem is more like an environment/compatibility/typo issue. The problem can be solved progressively.
There is a misuse of jQuery's clone() function, the clone() function accepts boolean type (http://api.jquery.com/clone/) , which means whether or not event handlers will be copied. From the code I guess this is not what you want. Please correct it and try again.
On which browser did you test? Does this issue happen on one specific browser, or happens on all browsers in your computer? If it is the latter one, then copy your code (copy the files, not re-type) to someone else' computer and try again.
Simplify the JS code and test step by step. First, just leave the prompt() line and delete all else, will it work? Then, add an empty create() function and try again. Then, add something more. Sooner or later, you will find the line which causes the problem.
Please let us know if you deliver the above experiment and find something new.
EDITS
I'll never stop if I don't stop now. I'm stuck anyway. Hope this helps you on your way. Still needs some work (undefined references) but is functional if my fanciness didn't distract me so much:
JS Fiddle Demo (not working)
Javascript:
(function (window, document, $) {
var $board = $('#board');
var x = parseInt(prompt("How large would you like your grid? (3-10)"), 10);
var taken = [];
create(x);
function create(x) {
var tmp;
var $tr = $('<tr/>');
var $td = $('<td/><td/><td/>');
if (x <= 10 && x >= 3 && typeof x === 'number') {
for (var i = 0; i < x; i++) {
tmp = $tr.append($td);
tmp.clone().appendTo($board);
}
$('#board').on('click', 'td', function (evt) {
var e = evt || window.event;
var y = $(this).index();
var z = $(this).parent('tr').index();
taken = (!taken) ? [y, z] : taken;
userChoice(y, z, x, this);
});
} else {
alert('You entered an incorrect value. Try again!');
return false;
}
}
function userChoice(y, z, x, el) {
//if($(el).text() !== "") {
console.log(taken);
for (var d = 0; d < (x - 1); d++) {
for (var o = 0, n = 0; o < 3; o++) {
if ((taken[n].indexOf(y) && taken[n].indexOf(z)) || (taken[n].indexOf(y) && taken[n].indexOf(z))) {
alert('Already played that spot. Nice try.');
return false;
}
n++;
}
}
taken.push([y, z]);
$(el).text('O');
console.log(taken);
if ((taken.length * taken[taken.length].length) / (x - 1) === 3) {
alert('No more spaces! Game over!');
return false;
}
compChoice(x);
}
function compChoice(x) {
console.log(taken);
var a = Math.floor(Math.random(10) * x);
var b = Math.floor(Math.random(10) * x);
for (var d = 0; d < (x-1); d++) {
for (var o = 0, n = 0; o < 3; o++) {
if ((taken[n].indexOf(a) && taken[n].indexOf(b)) || (taken[n].indexOf(a) && taken[n].indexOf(b))) {
compChoice(x);
}
n++;
}
}
taken.push([a,b]);
console.log(taken);
$board.find('tr:nth-of-type(' + a + ')').find('td:nth-of-type(' + b + ')').text('X');
if ((taken.length * taken[taken.length].length) === x) {
alert('No more spaces! Game over!');
return false;
}
}
})(this, this.document, jQuery, undefined);
HTML:
<div id="dashboard">
<noscript>
<input type="text" value="How large is your grid? (default 3)" size="35" />
</noscript>
</div>
<table id="board"></table>

Why is my AI acting strange in a game of tic-tac-toe?

The organisation of the data for the game of tic-tac-toe is simple.
There is an array that contains a lot of HTML buttons.
The program remembers if a button is used by using the isUsed array.
It checks what image to display on the button using the isX Boolean.
The program contains a list of winning combinations that are available to everyone using freeWins array. When a human picks 5, all the winning combos containing 5 are moved to an array called yourWins. Then, the positions owned by the human will be replaced from yourWins.
Code:
<!DOCTYPE html>
<html>
<title> 1Player </title>
<style>
#stage{
width: 400px;
height: 400px;
padding: 0px;
position: relative;
}
.square{
user-select : none;
-webkit-user-select: none;
-moz-user-select: none;
width: 64px;
height: 64px;
background-color: gray;
position: absolute;
}
</style>
<body>
<div id="stage">
</div>
</body>
<script>
const ROWS = 3;
const COLS = 3;
const GAP = 10;
const SIZE = 64;
var stage = document.querySelector("#stage");
var lotOfButtons = [];
var isUsed = [false,false,false,false,
false,false,false,false,false];
var myPositions = "";
var yourPositions = "";
var youPicked = "";
var iPicked = "";
var isX = true;
var isFirstMove = true;
var myWins = [];
var yourWins = [];
var freeWins = ["123","159","147",
"258",
"369","357",
"456",
"789"];
prepareBoard();
stage.addEventListener("click",clickHandler,false);
function prepareBoard(){ //Prepare the board on which the users will play.
for(var row = 0;row<ROWS;row++){ // Prepare the rows.
for(var col = 0;col < COLS;col++){ //Prepare the columns.
var square = document.createElement("button"); //Prepare the button which represents a square.
square.setAttribute("class","square"); //Make it a square 'officially'.
stage.appendChild(square); //Add the square to the play area..
lotOfButtons.push(square); //Keep a record of squares.
square.style.left = col * (SIZE+GAP) + "px"; //Properly set the horizontal spacing.
square.style.top = row * (SIZE+GAP) + "px"; //Properly set the vertical spacing.
}
}
}
function clickHandler(event){
var index = lotOfButtons.indexOf(event.target);
if(index=== -1 || isX === false){
return;
}
isX = false;
isUsed[index] = true;
event.target.style.backgroundImage = "url(../img/X.png)";
yourMove(index+1);
}
function yourMove(someIndex){
console.log("Finding Human Winning Moves::: ");
yourWins = findWinnindMoves(yourWins,someIndex);
console.log(yourWins);
console.log("Clearing Human Owned Positions::: ");
yourWins = clearOwnedPositions(yourWins,someIndex);
console.log(yourWins + "\n");
myMove();
}
function myMove(){
var isFifthSquareUsed = isFiveUsed();
if(isFifthSquareUsed === false){ //Is fifth square used ?? --- NO!
var selectedSquare = lotOfButtons[4];
selectedSquare.style.backgroundImage = "url(../img/O.PNG)";
isUsed[4] = true;
isFirstMove = false;
isX = true;
console.log("Finding AI Winning Moves::: ");
myWins = findWinnindMoves(myWins,4);
console.log(myWins);
console.log("Clearing AI Owned Positions::: ");
myWins = clearOwnedPositions(myWins,4);
console.log(myWins + "\n");
}else if(isFifthSquareUsed && isFirstMove){ //Is fifth square used ?? --- YES, but it is first move.
//TODO add logic
}else{ //Some random square has already been chosen. Now it is time to use strategy.
//TODO add logic
}
}
function findWinnindMoves(winsArray,someIndex){//using which combination can a user or AI win ?
for(var i = 0;i<freeWins.length;i++){
if(freeWins[i].indexOf(someIndex) != -1){
winsArray.push(freeWins[i]);
i--;
freeWins.splice(i,1);
}
}
return winsArray;
}
function clearOwnedPositions(winsArray,someIndex){ //Reduce the number of squares needed to get triplets.
for(var i=0;i<winsArray.length;i++){
if(winsArray[i].indexOf(someIndex) != -1){
winsArray[i] = winsArray[i].replace(someIndex,"");
}
}
return winsArray;
}
function isFiveUsed(){ //Is AI able to get the center square ?
return isUsed[4];
}
</script>
</html>
Problem
The determination of the winning moves for the user and the AI works properly if I click the second or the third row and not on first row.
Output on Row 2
Finding Human Winning Moves:::
["147", "456"]
Clearing Human Owned Positions:::
17,56
Finding AI Winning Moves:::
["147", "456"]
Clearing AI Owned Positions:::
17,56
Output on Row 1
Finding Human Winning Moves:::
["123", "123", "123", "123", "123", "123", "123", "123"]
Clearing Human Owned Positions:::
23,23,23,23,23,23,23,23
Finding AI Winning Moves:::
[]
Clearing AI Owned Positions:::
Also, after clearing the owned squares the array brackets are gone.
Why are the two problems happening?
To Answer your second question about the Arrays, You cannot initialize a blank Array and at the same time .push() in the same area. Every time you run the JavaScript it re-creates the Array and that means goodbye to the stuff you are putting into it. Maybe you should initialize the Array outside a function and put the rest of the code inside the function. As for your game AI, I am not entirely sure. Hope this helps somewhat.

Javascript run a function at the same time with different vars

Sorry about the confusing title, I'll explain better.
I have a 20x20 grid of div's, so its 400 of them each with an id, going from 0 to 399.
Each div is given one of three random values - red, green or blue - and when a div is clicked, a function is run to check if the div to the left, right, over and under are of the same value, if it is of the same value it will be simulated a click and the same function will run again.
The problem, is that the function sets vars, so if it finds that the div below has the same value, it will overwrite the vars set by the first click, hence never click any of the others.
JSfiddle - http://jsfiddle.net/5e52s/
Here is what I've got:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>untiteled</title>
<style>
body {
width: 420px;
}
.box {
width: 19px;
height: 19px;
border: 1px solid #fafafa;
float: left;
}
.box:hover {
border: 1px solid #333;
}
.clicked {
background: #bada55 !important;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$().ready(function(){
var colors = ['red', 'green', 'blue'];
var i = 0;
while(i<400){
var color = colors[Math.floor(Math.random() * colors.length)];
$('.test').append('<div class="box" id="'+i+'" value="'+color+'" style="background:'+color+';">'+i+'</div>');
i++;
}
$('.box').click(function(){
var t = $(this);
t.addClass('clicked');
id = t.attr('id');
val = t.attr('value');
//Set color
up = parseInt(id) - 20;
right = parseInt(id) + 1;
down = parseInt(id) + 20;
left = parseInt(id) - 1;
clickup = false;
clickdown = false;
if($('#'+down).attr('value') === val){
clickdown = true;
}
if(up > -1 && ($('#'+up).attr('value') === val)){
clickup = true;
}
if(clickdown == true){
$('#'+down).click();
}
if(clickup == true){
$('#'+up).click();
}
});
});
</script>
</head>
<body>
<div class="test">
</div>
</body>
I think the biggest root cause of your problem is you don't check if it already has class 'clicked' or not. That could make the infinite recursive. For example, if you click on the div#2 then the div#1 receives a simulated click, and div#2 receives a simulated click from div#1.
$('.box').click(function(){
var t = $(this);
if(t.hasClass('clicked')) {
return;
}
t.addClass('clicked');
var id = t.attr('id');
var val = t.attr('value');
//Set color
var up = parseInt(id) - 20;
var right = (id%20 != 19) ? ((0|id) + 1) : 'nothing' ;
var down = parseInt(id) + 20;
var left = (id%20 != 0) ? ((0|id) - 1) : 'nothing';
console.log(up, right, down, left);
if($('#'+down).attr('value') === val) {
$('#'+down).click();
}
if($('#'+right).attr('value') === val) {
$('#'+right).click();
}
if($('#'+up).attr('value') === val) {
$('#'+up).click();
}
if($('#'+left).attr('value') === val) {
$('#'+left).click();
}
});
You can schedule the clicks onto the event loop instead of calling them directly, eg:
if(clickdown == true){
setTimeout(function () {
$('#'+down).click();
});
}
I don't think that's your root cause though, it's probably a combination of global vars and scope issues. Try reformatting as such:
$('.box').click(function (event){
var t = $(this), id, val, up, right, down, left, clickup, clickdown;
//...
Your variables id and val are not in a var statement, thus are implicitly created as members of the window object instead of being scoped to the local function. Change the semicolon on the line before each to a comma so that they become part of the var statement, and your code should begin working.

Categories