I have a create a list using javascript and at the end I have an iterator that goes through the list and displays the contents. Unfortunately my iterator goes into an infinite loop and I can't debug it.
This is the code -If you run the iterator your browser will crush - every other functions seems to work well.
function List(){
this.listSize = 0;
this.pos = 0;
this.dataStore = [];
this.clearList = clear;
this.find = find;
this.toString = toString;
this.insert = insert;
this.append = append;
this.remove = remove;
this.front = front;
this.end = end;
this.prev = prev;
this.next = next;
this.length = length;
this.currPos = currPos;
this.moveTo = moveTo;
this.getElement = getElement;
this.length = length;
this.contains = contains;
}
function append(element){
this.dataStore[this.listSize++]=element;
}
function find(element){
for(var i=0;i<this.dataStore.length; ++i){
if(this.dataStore[i]==element){
return i;
}
}
return -1;
}
function remove(element){
var foundAt = this.find(element);
if(foundAt > -1){
this.dataStore.splice(foundAt,1);
--this.listSize;
return true;
}
return false;
}
function length(){
return this.listSize;
}
function toString(){
return this.dataStore;
}
function insert(element, after){
var insertPos = this.find(after);
if(insertPos > -1){
this.dataStore.splice(insertPos+1,0,element);
++this.listSize;
return true;
}
return false;
}
function clear(){
delete this.dataStore;
this.dataStore = [];
this.listSize = this.pos = 0;
}
function contains(element){
for(var i = 0; i < this.dataStore.length; ++i){
if(this.dataStore[i] == elemen){
return true;
}
}
return false
}
function front(){
this.pos = 0;
}
function end(){
this.pos = this.listSize-1;
}
function prev(){
if(this.pos > 0){
--this.pos;
}
}
function next(){
if(this.pos < this.listSize -1){
++this.pos;
}
}
function currPos(){
return this.pos;
}
function moveTo(position){
this.pos = position;
}
function getElement(){
return this.dataStore[this.pos];
}
var names = new List();
names.append("Clayton");
names.append("Raymond");
names.append("Cynthia");
names.append("Jennifer");
names.append("Bryan");
names.append("Danny");
names.front();
console.log(names.getElement());
names.next();
console.log(names.getElement());
names.next();
names.next();
names.prev();
console.log(names.getElement());
//iterator starts here
for(names.front(); names.currPos() < names.length(); names.next()){
console.log(names.getElement());
}
The for loop terminates when pos >= listSize. But next() will not increment pos unless pos < listSize - 1. Once pos == listSize - 1, next() will not increment pos. So the maximum value of pos is listSize - 1. Therefore the loop will never terminate.
Related
here is the question:
Imagine the String() constructor didn't exist. Create a constructor
function, MyString(), that acts like String() as closely as possible.
You're not allowed to use any built-in string methods or properties,
and remember that String() doesn't exist. You can use this code to
test your constructor:
I created constructor however I have no clue how to re-create split method, how to implement that functionality.
If you could give an idea how to implement split method, I would be grateful
function MyString(str) {
var thisObj = this;
var innerLength = 0;
this.length;
function updateLength() {
innerLength = 0;
for (var i = 0; str[i] != undefined; i++) {
innerLength++;
thisObj[i] = str[i];
}
thisObj.length = innerLength;
}
updateLength();
this.toString = function() {
return str;
}
this.charAt = function(i) {
if (isNaN(parseInt(i))) {
return this[0]
} else {
return this[i]
}
}
this.concat = function(string) {
str += string;
updateLength();
}
this.slice = function(start, end) {
var slicedString = "";
if (start >= 0 && end >= 00) {
for (start; start < end; start++) {
slicedString += str[start];
}
}
return slicedString;
}
this.reverse = function() {
var arr = str.split("");
arr.reverse();
var reversedString = "",
i;
for (i = 0; i < arr.length; i++) {
reversedString += arr[i];
}
return reversedString;
}
}
var ms = new MyString("Hello, I am a string")
console.log(ms.reverse())
You can convert the string to an array and use Array.prototype and RegExp.prototype methods.
this.split = function(re) {
var arr = Array.prototype.slice.call(this.toString());
if (re === "") {
return arr
}
if (re === " ") {
return arr.filter(function(el) {
return /[^\s]/.test(el)
})
}
if (/RegExp/.test(Object.getPrototypeOf(re).constructor)) {
var regexp = re.source;
return arr.filter(function(el) {
return regexp.indexOf(el) === -1
})
}
}
function MyString(str) {
var thisObj = this;
var innerLength = 0;
this.length;
function updateLength() {
innerLength = 0;
for (var i = 0; str[i] != undefined; i++) {
innerLength++;
thisObj[i] = str[i];
}
thisObj.length = innerLength;
}
updateLength();
this.toString = function() {
return str;
}
this.split = function(re) {
var arr = Array.prototype.slice.call(this.toString());
if (re === "") {
return arr
}
if (re === " ") {
return arr.filter(function(el) {
return /[^\s]/.test(el)
})
}
if (/RegExp/.test(Object.getPrototypeOf(re).constructor)) {
var regexp = re.source;
return arr.filter(function(el) {
return regexp.indexOf(el) === -1
})
}
}
this.charAt = function(i) {
if (isNaN(parseInt(i))) {
return this[0]
} else {
return this[i]
}
}
this.concat = function(string) {
str += string;
updateLength();
}
this.slice = function(start, end) {
var slicedString = "";
if (start >= 0 && end >= 00) {
for (start; start < end; start++) {
slicedString += str[start];
}
}
return slicedString;
}
this.reverse = function() {
var arr = str.split("");
arr.reverse();
var reversedString = "",
i;
for (i = 0; i < arr.length; i++) {
reversedString += arr[i];
}
return reversedString;
}
}
var ms = new MyString("Hello, I am a string")
console.log(ms.split(""), ms.split(" "), ms.split(/l/))
Iterate and search:
MyString.prototype.split = function(splitter){
var tmp="", result = [];
for(var i = 0; i < this.length; i++){
for(var offset = 0; offset < this.length && offset < splitter.length;offset++){
if(this[i+offset] !== splitter[offset]) break;
}
if(offset === splitter.length){
result.push( tmp );
tmp="";
i += offset -1;
}else{
tmp+=this[i];
}
}
result.push(tmp);
return result;
};
So now you can do:
new MyString("testtest").split("t") //['','es','','','es','']
In action
I found this code on net, it's about a memory game.
var MemoryApp = (function () {
'use strict';
var size = 36;
var sizeStyle = "smallGame";
var maxpics = 18;
var gameRunning = false;
var cardOpen = null;
var time = 0;
var timer;
var s4;
var s6;
var s8;
var attempts = 0;
var found = 0;
var foundDisp;
var attDisp;
var timeDisp;
var template;
var popupImage;
var popupHolder;
var gameGrid;
var currentCardSet = 'zoo';
var currentCards = [];
window.onload = runGame;
function activated() {
WinJS.UI.processAll().then(function(){
s4 = document.getElementById("size4x4");
s6 = document.getElementById("size6x6");
s8 = document.getElementById("size8x8");
s4.addEventListener("click", gameSize, false);
s6.addEventListener("click", gameSize, false);
s8.addEventListener("click", gameSize, false);
var start = document.getElementById("startGame");
if (start) {
start.onclick = runGame;
}
var stop = document.getElementById("stopGame");
if (stop) {
stop.onclick = stopGame;
}
template = document.getElementById("cardTemplate");
popupImage = document.getElementById("popupImage");
popupHolder = document.getElementById("popupHolder");
popupHolder.addEventListener("click", closeImageView, false);
foundDisp = document.getElementById("foundDisplay");
attDisp = document.getElementById("attemptsDisplay");
timeDisp = document.getElementById("timeDisplay");
// Expose functions globally
window.updateClock = updateClock;
window.resetCards = resetCards;
window.gameTag1 = null;
window.gameTag2 = null;
buildCards();
});
}
function closeImageView() {
removeClass(popupHolder, "openImagePopup");
}
function makePictureArray() {
var pics = new Array();
for (var i = 0; i < maxpics; i++) {
pics[i] = getDefaultURL(i);
}
return pics;
}
function removeAllChildren(element) {
if (element.hasChildNodes()) {
while (element.childNodes.length > 0) {
element.removeChild(element.firstChild);
}
}
}
function buildCards() {
// Assumption: game grid size is a power of 2
var stride = Math.sqrt(size);
// Make picture selection
var pics = makePictureArray();
var sel = new Array();
for (var i = 0; i < size / 2; i++) {
var idx = parseInt(Math.random() * pics.length);
sel[i] = pics[idx];
// remove the used pic
pics.splice(idx, 1);
}
// get an array with the card content
var content = new Array();
for (var i = 0; i < size / 2; i++) {
content[i] = sel[i];
content[i + size / 2] = sel[i];
}
var gameBoard = document.querySelector('#gameBoard');
removeAllChildren(gameBoard);
var gameGrid = document.createElement("div");
gameGrid.id = "gameGrid";
addClass(gameGrid, sizeStyle);
gameBoard.appendChild(gameGrid);
for (var i=0; i<size; i++) {
var item = document.createElement("div");
item.className = "gameItem"+i;
item.addEventListener("click", cardClicked, false);
setClosed(item);
var r = parseInt(Math.random() * content.length);
// Add image
insertTemplate(item, template);
var walker = document.createTreeWalker(item, NodeFilter.SHOW_ELEMENT, imgFilter, false);
while (walker.nextNode())
walker.currentNode.setAttribute("src", content[r]);
// Add path to ease styling
var walker = document.createTreeWalker(item, NodeFilter.SHOW_ELEMENT, pFilter, false);
while (walker.nextNode())
walker.currentNode.innerText = content[r];
item.contentIndex = content[r];
content.splice(r, 1);
gameGrid.appendChild(item);
}
}
function imgFilter(node) {
if (node.tagName == "IMG") //filter IMG elements
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
}
function pFilter(node) {
if (node.tagName == "P") //filter IMG elements
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
}
function insertTemplate(parent, templateParent) {
if (templateParent.children && templateParent.children.length >= 1) {
var tchild = templateParent.children[0].cloneNode(true);
parent.appendChild(tchild);
}
}
function gameSize() {
document.size.size4x4.checked = false;
document.size.size6x6.checked = false;
document.size.size8x8.checked = false;
var newsize = 36;
var gSize = "smallGame";
if (this.name == "size4x4") {
document.size.size4x4.checked = true;
newsize = 36;
gSize = "smallGame";
}
if (this.name == "size6x6") {
document.size.size6x6.checked = true;
newsize = 36;
gSize = "mediumGame";
}
if (this.name == "size8x8") {
document.size.size8x8.checked = true;
newsize = 36;
gSize = "largeGame";
}
if (!gameRunning == true) {
size = newsize;
sizeStyle = gSize;
buildCards();
}
}
function stopGame() {
if (!gameRunning)
return;
gameRunning = false;
foundDisp.innerText = "0";
found = 0;
attDisp.innerText = "0";
attempts = 0;
clearInterval(timer);
timeDisp.innerText = "00:00";
s4.disabled = false;
s6.disabled = false;
s8.disabled = false;
}
function runGame() {
//don't do anything if game already running
if (gameRunning == true)
return;
window.gameTag1 = null;
window.gameTag2 = null;
cardOpen = null;
gameRunning = true;
buildCards();
timeDisp.innerText = "00:00";
time = 0;
foundDisp.innerText = "0";
found = 0;
attDisp.innerText = "0";
attempts = 0;
timer = setInterval("updateClock()", 1000);
s4.disabled = true;
s6.disabled = true;
s8.disabled = true;
}
function getDefaultURL(i) {
var idx = i+1;
if (idx<1)
idx = 1;
if (idx>32)
idx = 32;
var result = "/photos/" + currentCardSet + "/";
if (idx < 10)
result = result + "0";
result = result + idx.toString() + ".jpg";
return result;
}
function updateClock() {
time = time + 1;
var mins = parseInt(time / 60);
var secs = time - mins * 60;
mins = mins.toString();
secs = secs.toString();
if (mins.length < 2)
mins = "0" + mins;
if (secs.length < 2)
secs = "0" + secs;
timeDisp.innerText = mins + ":" + secs;
}
function cardClicked() {
// If an open card is clicked, bring up the full size popup
if (this.cardFoundFlag || cardOpen === this) {
popupImage.setAttribute("src", this.contentIndex);
popupHolder.style.display = "block";
addClass(popupHolder, "openImagePopup");
return;
}
// don't do anything if no game is running, or a move is in play...
if (!gameRunning || window.gameTag1 !=null || window.gameTag2 != null)
return;
if (cardOpen == null) {
setOpen(this);
cardOpen = this;
} else {
if (this.contentIndex == cardOpen.contentIndex) {
setFound(this);
setFound(cardOpen);
this.cardFoundFlag = true;
cardOpen.cardFoundFlag = true;
cardOpen = null;
found++;
foundDisp.innerText = found;
updateAttempts();
if (found == size / 2) {
gameRunning = false;
clearInterval(timer);
foundDisp.innerText = "ALL!";
}
} else {
setOpen(this);
// Hack to get around insulation of these functions
window.gameTag1 = this;
window.gameTag2 = cardOpen;
setTimeout("resetCards()", 1100);
cardOpen = null;
updateAttempts();
}
}
}
function setOpen(el) {
removeClass(el, "closedCard");
addClass(el, "openCard");
}
function setClosed(el) {
removeClass(el, "openCard");
addClass(el, "closedCard");
}
function setFound(el) {
removeClass(el, "openCard");
removeClass(el, "closedCard");
addClass(el, "foundCard");
}
function resetCardStyles(el) {
removeClass(el, "openCard");
removeClass(el, "foundCard");
addClass(el, "closedCard");
}
function updateAttempts() {
attempts++;
attDisp.innerText = attempts;
}
function resetAllCards() {
buildCards();
}
function resetCards() {
setClosed(window.gameTag1);
setClosed(window.gameTag2);
window.gameTag1 = null;
window.gameTag2 = null;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
function hasClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// no need to continue if there's no className
if (!el.className) return false;
// iterate through all the classes
var classArray = el.className.split(' ');
for (var i = 0; i < classArray.length; i++) {
if (className == classArray[i]) return true; // found? return true
}
// if we're still here, the class does not exist
return false;
}
function addClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// simply append the className to the string
el.className += ' ' + className;
return;
}
function removeClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// if the class doesn't exist, there's no need to remove it
if (!hasClass(el, className)) return;
// iterate through all the classes
var classArray = el.className.split(' ');
for (var i = 0; i < classArray.length; i++) {
// found it!
if (className == classArray[i]) {
classArray.splice(i, 1); // remove it
i--; // decrement so we don't skip over any future occurences
}
}
// reassign the className
el.className = classArray.join(' ');
return;
}
WinJS.Application.onactivated = function (e) {
if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
activated();
}
}
WinJS.Application.start();
});
var theMemoryApp = new MemoryApp();
I need to add a function which is going to check for touch or click detection on the screen. If there is no touch after some seconds, all game has to restart from the beginning. How can I do that?
I hide that start and stop buttons on the design. So with window.onload=runGame game starts automatically when its loaded. But need to be restart if children live the game play when its not finished. For example, if there is no touch after 120 seconds, all code has to restart from beginning. Or there is buildCard function in the code. This timer can trigger this function also. I will be glad for any kind of help cause this is for kids.
You can use debounce technique like shown in below snippet. I have added click event but you can add touch specific events also. timer() will be triggered every 120 secs if click event is not triggered i.e if user doesn't click or touch. I could not run your code to test. Please let me know if this doesn't work.
var MemoryApp = (function () {
'use strict';
var size = 36;
var sizeStyle = "smallGame";
var maxpics = 18;
var gameRunning = false;
var cardOpen = null;
var time = 0;
var timer;
var s4;
var s6;
var s8;
var attempts = 0;
var found = 0;
var foundDisp;
var attDisp;
var timeDisp;
var template;
var popupImage;
var popupHolder;
var gameGrid;
var currentCardSet = 'zoo';
var currentCards = [],
__timeOut = 0;
window.onload = runGame;
var timer = function() {
clearTimeout(__timeOut);
__timeOut = setTimeout(function() {
buildCards();
}, 120000);
};
window.addEventListener('click', timer);
function activated() {
WinJS.UI.processAll().then(function(){
s4 = document.getElementById("size4x4");
s6 = document.getElementById("size6x6");
s8 = document.getElementById("size8x8");
s4.addEventListener("click", gameSize, false);
s6.addEventListener("click", gameSize, false);
s8.addEventListener("click", gameSize, false);
var start = document.getElementById("startGame");
if (start) {
start.onclick = runGame;
}
var stop = document.getElementById("stopGame");
if (stop) {
stop.onclick = stopGame;
}
template = document.getElementById("cardTemplate");
popupImage = document.getElementById("popupImage");
popupHolder = document.getElementById("popupHolder");
popupHolder.addEventListener("click", closeImageView, false);
foundDisp = document.getElementById("foundDisplay");
attDisp = document.getElementById("attemptsDisplay");
timeDisp = document.getElementById("timeDisplay");
// Expose functions globally
window.updateClock = updateClock;
window.resetCards = resetCards;
window.gameTag1 = null;
window.gameTag2 = null;
buildCards();
});
}
function closeImageView() {
removeClass(popupHolder, "openImagePopup");
}
function makePictureArray() {
var pics = new Array();
for (var i = 0; i < maxpics; i++) {
pics[i] = getDefaultURL(i);
}
return pics;
}
function removeAllChildren(element) {
if (element.hasChildNodes()) {
while (element.childNodes.length > 0) {
element.removeChild(element.firstChild);
}
}
}
function buildCards() {
// Assumption: game grid size is a power of 2
var stride = Math.sqrt(size);
// Make picture selection
var pics = makePictureArray();
var sel = new Array();
for (var i = 0; i < size / 2; i++) {
var idx = parseInt(Math.random() * pics.length);
sel[i] = pics[idx];
// remove the used pic
pics.splice(idx, 1);
}
// get an array with the card content
var content = new Array();
for (var i = 0; i < size / 2; i++) {
content[i] = sel[i];
content[i + size / 2] = sel[i];
}
var gameBoard = document.querySelector('#gameBoard');
removeAllChildren(gameBoard);
var gameGrid = document.createElement("div");
gameGrid.id = "gameGrid";
addClass(gameGrid, sizeStyle);
gameBoard.appendChild(gameGrid);
for (var i=0; i<size; i++) {
var item = document.createElement("div");
item.className = "gameItem"+i;
item.addEventListener("click", cardClicked, false);
setClosed(item);
var r = parseInt(Math.random() * content.length);
// Add image
insertTemplate(item, template);
var walker = document.createTreeWalker(item, NodeFilter.SHOW_ELEMENT, imgFilter, false);
while (walker.nextNode())
walker.currentNode.setAttribute("src", content[r]);
// Add path to ease styling
var walker = document.createTreeWalker(item, NodeFilter.SHOW_ELEMENT, pFilter, false);
while (walker.nextNode())
walker.currentNode.innerText = content[r];
item.contentIndex = content[r];
content.splice(r, 1);
gameGrid.appendChild(item);
}
}
function imgFilter(node) {
if (node.tagName == "IMG") //filter IMG elements
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
}
function pFilter(node) {
if (node.tagName == "P") //filter IMG elements
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
}
function insertTemplate(parent, templateParent) {
if (templateParent.children && templateParent.children.length >= 1) {
var tchild = templateParent.children[0].cloneNode(true);
parent.appendChild(tchild);
}
}
function gameSize() {
document.size.size4x4.checked = false;
document.size.size6x6.checked = false;
document.size.size8x8.checked = false;
var newsize = 36;
var gSize = "smallGame";
if (this.name == "size4x4") {
document.size.size4x4.checked = true;
newsize = 36;
gSize = "smallGame";
}
if (this.name == "size6x6") {
document.size.size6x6.checked = true;
newsize = 36;
gSize = "mediumGame";
}
if (this.name == "size8x8") {
document.size.size8x8.checked = true;
newsize = 36;
gSize = "largeGame";
}
if (!gameRunning == true) {
size = newsize;
sizeStyle = gSize;
buildCards();
}
}
function stopGame() {
if (!gameRunning)
return;
gameRunning = false;
foundDisp.innerText = "0";
found = 0;
attDisp.innerText = "0";
attempts = 0;
clearInterval(timer);
timeDisp.innerText = "00:00";
s4.disabled = false;
s6.disabled = false;
s8.disabled = false;
}
function runGame() {
//don't do anything if game already running
if (gameRunning == true)
return;
window.gameTag1 = null;
window.gameTag2 = null;
cardOpen = null;
gameRunning = true;
buildCards();
timeDisp.innerText = "00:00";
time = 0;
foundDisp.innerText = "0";
found = 0;
attDisp.innerText = "0";
attempts = 0;
timer = setInterval("updateClock()", 1000);
s4.disabled = true;
s6.disabled = true;
s8.disabled = true;
}
function getDefaultURL(i) {
var idx = i+1;
if (idx<1)
idx = 1;
if (idx>32)
idx = 32;
var result = "/photos/" + currentCardSet + "/";
if (idx < 10)
result = result + "0";
result = result + idx.toString() + ".jpg";
return result;
}
function updateClock() {
time = time + 1;
var mins = parseInt(time / 60);
var secs = time - mins * 60;
mins = mins.toString();
secs = secs.toString();
if (mins.length < 2)
mins = "0" + mins;
if (secs.length < 2)
secs = "0" + secs;
timeDisp.innerText = mins + ":" + secs;
}
function cardClicked() {
// If an open card is clicked, bring up the full size popup
if (this.cardFoundFlag || cardOpen === this) {
popupImage.setAttribute("src", this.contentIndex);
popupHolder.style.display = "block";
addClass(popupHolder, "openImagePopup");
return;
}
// don't do anything if no game is running, or a move is in play...
if (!gameRunning || window.gameTag1 !=null || window.gameTag2 != null)
return;
if (cardOpen == null) {
setOpen(this);
cardOpen = this;
} else {
if (this.contentIndex == cardOpen.contentIndex) {
setFound(this);
setFound(cardOpen);
this.cardFoundFlag = true;
cardOpen.cardFoundFlag = true;
cardOpen = null;
found++;
foundDisp.innerText = found;
updateAttempts();
if (found == size / 2) {
gameRunning = false;
clearInterval(timer);
foundDisp.innerText = "ALL!";
}
} else {
setOpen(this);
// Hack to get around insulation of these functions
window.gameTag1 = this;
window.gameTag2 = cardOpen;
setTimeout("resetCards()", 1100);
cardOpen = null;
updateAttempts();
}
}
}
function setOpen(el) {
removeClass(el, "closedCard");
addClass(el, "openCard");
}
function setClosed(el) {
removeClass(el, "openCard");
addClass(el, "closedCard");
}
function setFound(el) {
removeClass(el, "openCard");
removeClass(el, "closedCard");
addClass(el, "foundCard");
}
function resetCardStyles(el) {
removeClass(el, "openCard");
removeClass(el, "foundCard");
addClass(el, "closedCard");
}
function updateAttempts() {
attempts++;
attDisp.innerText = attempts;
}
function resetAllCards() {
buildCards();
}
function resetCards() {
setClosed(window.gameTag1);
setClosed(window.gameTag2);
window.gameTag1 = null;
window.gameTag2 = null;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Utilities
//
//////////////////////////////////////////////////////////////////////////////////////////////////////
function hasClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// no need to continue if there's no className
if (!el.className) return false;
// iterate through all the classes
var classArray = el.className.split(' ');
for (var i = 0; i < classArray.length; i++) {
if (className == classArray[i]) return true; // found? return true
}
// if we're still here, the class does not exist
return false;
}
function addClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// simply append the className to the string
el.className += ' ' + className;
return;
}
function removeClass(el, className) {
// authors can pass in either an element object or an ID
el = (typeof (el) == 'object') ? el : document.getElementById(el);
// if the class doesn't exist, there's no need to remove it
if (!hasClass(el, className)) return;
// iterate through all the classes
var classArray = el.className.split(' ');
for (var i = 0; i < classArray.length; i++) {
// found it!
if (className == classArray[i]) {
classArray.splice(i, 1); // remove it
i--; // decrement so we don't skip over any future occurences
}
}
// reassign the className
el.className = classArray.join(' ');
return;
}
WinJS.Application.onactivated = function (e) {
if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
activated();
}
}
WinJS.Application.start();
});
var theMemoryApp = new MemoryApp();
I am building Conway's Game of Life in JavaScript. The previous issue has been fixed.
........................................................................
Now it is saying: Cannot read property 'length' of undefined in 'for(var i =0; i< this.checkneighbours.length; i++)'. But i defined checkneighbours at the top as an array. do you know what the problem is here?
//object constructor
function cell(){
this.alive = Math.random() > 0.7;
this.neighbours = 0; //number of live neighbours
this.checkneighbours = [[-1,-1],[-1,0],[0,-1],[-1,1],[1,-1],[1,0],[0,1],[1,1]];
}
function GoL(size){
this.size = size;
this.grid = this.makeGrid(size);
};
GoL.prototype.makeGrid = function(size){
var grid = [];
for(var i=0; i<size; i++){
var row=[];
for(var j =0; j<size; j++){
row.push(new cell());
}
grid.push(row);
}
return grid;
};
GoL.prototype.drawGrid = function(){
for(var i=0;i<this.size;i++){
var row =this.grid[i];
var rowCell="";
for(var j=0;j<this.size;j++){
var cell = row[j];
if(cell.alive){
rowCell += "X|";
}else{
rowCell += " |";
}
}
console.log(rowCell);
}
};
GoL.prototype.underpopulation = function(ro,col){
var cell = this.grid[ro][col];
if(cell.neighbours <2){
return true;
}else{
return false;
}
};
GoL.prototype.overpopulation = function(ro,col){
var cell = this.grid[ro][col];
if(cell.neighbours >3){
return true;
}else{
return false;
}
};
GoL.prototype.backtolife = function(ro,col){
var cell = this.grid[ro][col];
if(cell.neighbours ===3 && !cell.alive){
return true;
}else{
return false;
}
};
GoL.prototype.update = function(ro,col){
var cell = this.grid[ro][col];
cell.num_of_neighbours = 0;
for(var i =0; i<this.checkneighbours.length; i++){
var checkneighbour = this.checkneighbours[i];
var neighbour1 = direction[0];
var neighbour2 = direction[1];
if(neighbour1>=0 && neighbour1 < this.size && neighbour2 >=0 && neighbour2 < this.size){
var currentneighbour = this.grid[ro + neighbour1][col+neighbour2];
if(currentneighbour.alive){
cell.num_of_neighbours++;
}
}
}
};
GoL.prototype.updateAll = function(){
for(var i=0; i<this.size;i++){
for(var j=0; j<this.size;j++){
this.update(i,j);
}
}
}
GoL.prototype.cellstatus = function(ro,col){
var cell = this.grid[ro][col];
if(this.underpopulation(ro,col) || this.overpopulation(ro,col)){
cell.alive = false;
}else if(this.backtolife(ro,col)){
cell.alive = true;
}
};
GoL.prototype.allcellstatus = function(ro,col){
for(var i=0; i<this.size;i++){
for(var j=0; j<this.size;j++){
this.cellstatus(i,j);
}
}
};
var gameoflife = new GoL(40);
var interval = setInterval(function(){
GoL.drawGrid();
GoL.updateAll();
GoL.allcellstatus();
},200);
I think what you mean to do is
var gameoflife = new GoL(40);
var interval = setInterval(function(){
gameoflife.drawGrid();
gameoflife.updateAll();
gameoflife.allcellstatus();
},200);
You should use the following syntax to call the functions:
var gameoflife = new GoL(40);
var interval = setInterval(function(){
gameoflife.drawGrid();
gameoflife.updateAll();
gameoflife.allcellstatus();
},200);
You're calling the method drawGrid on the class, rather than the instance gameoflife
You need to call those methods on your instance, rather than the class it's self:
var interval = setInterval(function(){
gameoflife.drawGrid();
gameoflife.updateAll();
gameoflife.allcellstatus();
},200);
I created a list iterator but when trying traverse a list backward the loop runs infinitely. What I did wrong?
function List() {
this.listSize=0;
this.pos=0;
this.dataStore =[];
this.append = append;
this.currPos = currPos;
this.end = end;
this.front = front;
this.length = length;
this.moveTo = moveTo;
this.next = next;
this.prev = prev;
}
function append(element) {this.dataStore[this.listSize++]=element;}
function currPos() {return this.pos;}
function end() {this.pos = this.listSize-1;}
function front() {this.pos =0;}
function length() {return this.listSize;}
function moveTo(position) {this.pos = position;}
function prev() {if(this.pos > 0) --this.pos;}
function next() {if(this.pos < this.listSize) ++this.pos;}
var names = new List();
names.append("A"); names.append("B"); names.append("C");
for(names.end(); names.currPos() >= 0; names.prev()) {console.log(names.getElement());}
Your loop only terminates when the current list position is less than zero, but your .prev() function won't allow that to happen.
To fix it? Well, that's a matter of opinion, but if you're going to the trouble of implementing a list class you might as well make a native .forEach function:
function forEach(callback) {
for (var i = 0; i < this.listSize; ++i)
callback(this.dataStore[i], i);
}
Then you can do:
names.forEach(function(name) { console.log(name); });
I ran into a similar problem when trying to implement a list ADT from the book "Data Structures and Algorithms" and came to find out that the author re-wrote that section in later versions to look like this:
module.exports = List;
function List() {
this.listSize = 0;
this.pos = 0;
this.dataStore = [];
this.clear = clear;
this.find = find;
this.toString = toString;
this.insert = insert;
this.append = append;
this.remove = remove;
this.front = front;
this.end = end;
this.prev = prev;
this.next = next;
this.length = length;
this.currPos = currPos;
this.moveTo = moveTo;
this.getElement = getElement;
this.length = length;
this.contains = contains;
this.hasNext = hasNext;
this.hasPrevious = hasPrevious;
this.insertIf = insertIf;
}
function append(element) {
this.dataStore[this.listSize++] = element;
}
function find(element) {
for (var i = 0; i < this.dataStore.length; ++i) {
if (this.dataStore[i] === element) {
return i;
}
}
return -1;
}
function remove(element) {
var foundAt = this.find(element);
if (foundAt > -1) {
this.dataStore.splice(foundAt, 1);
--this.listSize;
return true;
}
return false;
}
function length() {
return this.listSize;
}
function toString() {
return this.dataStore;
}
function insert(element, after){
var insertPos = this.find(after);
if(insertPos > -1){
this.dataStore.splice(insertPos+1, 0, element);
++this.listSize;
return true;
}
return false;
}
function clear() {
delete this.dataStore;
this.dataStore = [];
this.listSize = this.pos = 0;
}
function contains(element) {
for (var i = 0; i < this.dataStore.length; ++i) {
if(this.dataStore[i] === element) {
return true;
}
}
return false;
}
function front() {
this.pos = 0;
}
function end() {
this.pos = this.listSize-1;
}
function prev() {
return this.dataStore[--this.pos];
}
function next(){
return this.dataStore[this.pos++];
}
function hasNext(){
if (this.pos > this.listSize -1) {
return false;
} else {
return true;
}
}
function hasPrevious() {
if(this.pos <= 0) {
return false;
} else {
return true;
}
}
function currPos() {
return this.pos;
}
function moveTo(position) {
this.pos = position;
}
function getElement() {
return this.dataStore[this.pos];
}
function insertIf(element) {
var greaterThan = true;
for(this.front(); this.hasNext(); ){
if(this.next() > element) {
greaterThan = false;
break;
}
}
console.log(element);
if(greaterThan){
this.append(element);
return true;
} else {
return false;
}
}
Your loops will then look like this:
for (list.front(); list.hasNext();) {
var listItem = list.next();
if(listItem instanceof Customer) {
console.log(listItem.name + ", " + listItem.movie);
} else {
console.log(listItem);
}
}
This has proven to be a much more reliable implementation so you may want to consider switching to this.
You need to change your for loop to:
for(names.end(); names.currPos() > 0; names.prev())
Checkout this demo/game i am building http://awebdeveloper.github.io/runners/
I wish to know when will all the players finish running. The Game class needs to know when all the player stop and who came first.
My question is is there a way to inform back the calling class when each of the animate finish after all the settimeout
Player Class
function Players(ele, ptimeout)
{
this.movePositions = [0, 40, 80, 120],
this.moveBy = 5
this.el = ele;
this.i = 0;
this.stop = 1;
this.timeout = ptimeout;
this.position = 0;
this.animate = function(){
/* Stop if stopped */
playerPosition = this.el.getBoundingClientRect();
if(this.stop || playerPosition.left > (racetrack.offsetWidth - 30)){
this.el.style.backgroundPosition = '120px 0px';
return ;
}
playerPosition = this.el.getBoundingClientRect();
if(this.stop || playerPosition.left > (racetrack.offsetWidth - 30)){
this.el.style.backgroundPosition = '120px 0px';
return ;
}
/* Prepare Next Move */
setTimeout(function(_this){
if(_this.i < _this.movePositions.length ){
_this.i ++;
}
else{
_this.i = 0;
}
_this.move();
_this.animate();
},this.timeout,this);
};
this.play = function(){
if(this.stop === 1){
this.stop = 0;
this.animate();
}
};
this.move = function(to,positionIndex){
this.position = to;
this.el.style.backgroundPosition = '-'+this.movePositions[positionIndex]+'px 0px';
this.el.style[getSupportedPropertyName('transform')] = 'translate('+to+'px)';
}
}
Game Class
function Game(noOfPlayers){
var track_tmpl = '<div class="track"><div id="player{{ x }}" class="runner"></div></div>';
this.noOfPlayers = noOfPlayers;
this.players = new Array();
for (var i = 0; i < this.noOfPlayers ; i++){
var timeout = 120 + getRandomInt(1, (this.noOfPlayers*2));
racetrack.appendChild(createNode(track_tmpl.replace('{{ x }}', i)));
this.players.push(new Players(document.getElementById('player' + i), timeout));
}
this.play = function(){
for (var i = 0; i < this.noOfPlayers; i++){
this.players[i].play();
}
};
}
on Player.play pass the this argument, to call from Person a function from Game.
So you will have a code like this
this.play = function(){
for (var i = 0; i < this.noOfPlayers; i++){
this.players[i].play(this);
}
};
then on Player modify the code like this
this.play = function(game){
if(this.stop === 1){
this.stop = 0;
this.animate(game);
}
};
after on method animate call the game.playerFinished(Player)
on Game class write a method
var i = 0;
this.playerFinished = function(player) {
console.log(player.name + " finished on position " + (i++));
}
where player.name a name you give on players class