Jump to content

Hadien

Members
  • Posts

    247
  • Joined

  • Last visited

Everything posted by Hadien

  1. try using local/session storage instead. it's easier to use, and in nearly every way better (security, performance, bandwidth, memory size, etc.), only downside is lack of support in pre-IE 8
  2. I remember one time of using trees in a college class (so that one could use prefix,infix,and postfix notation). if you build the tree as nodes (which will be the operator) and leaves (the operands). for example given the formula 2+5*6-13 the root node will spit the formula at it's lowest order of operation ( the plus and minus have the lowest order, but the minus comes last so it's the lowest). so the root node is split with the leaves of "2+5*6" and "13" with the operator "-" connecting them. we then look at the left leaf thats not fullt split out yet and do the same thing. so that formula is split as "2"on the left, "+" as the operator, and "5*6" on the right. now that the "+" node is split it checks the left to see if it's fully split (and "2" is fully split), then checks the right to see if "5*6" is split, its not so it splits that. In the end the tree it builds looks something like this, and in solving it, it'll take these steps working bottom up: (-) (-) (-) --> (19) / / / (+) (13) (+) (13) --> (32) (13) / / (2) (*) --> (2) (30) / (5) (6) you can then make recursive calls to calculate the overall value of the formula. +,-, and * are simple operators to code for... exponents, while needing a little more code, is also still pretty simple.
  3. you don't need eval, eval is pretty bad anyway. instead of writing n.replace(/x3/g,"Math.pow(3,3)") simply write it as: n.replace(/x3/g,""+Math.pow(3,3)) the power function will run (best of all only once) and calculate 3^3 and then cast it into a string as "27". then it will run the replace of "27" and not "Math.pow(3,3)".
  4. are you positive? are you sure oncontextmenu isn't a browser-specific attribute? that may work on some browsers but I could instead open up in like chrome and have no trouble saving the image. or again I can simply look at the href attribute in any browser and cut out the middle man.
  5. "^" is a reserved character in regEx, try escaping it first as /x/^2/g
  6. only 'good' reason I can think of is modularity. if they are running a site where they want different styles on a per-page basis. so the index page may be using main.css, but the login page may instead use a login.css. but both pages may need the "fonts" and "text" css. thats the only good reason I can think of. many times however big websites most likely use multiple css not for modularity but due to the evolution of the site. multiple developers may have come in at different times in the lifetime of the website and then applied their own styling. now the proper developer may just merge his styling in with the old css, but sometimes a previous developer might not have properly documented their own changes, making it harder for the newcomer to know where to begin or what to change, so the easy way is to simply overwrite. But this is just development in general, css doesn't have that hard of a pitfall since it is relatively easy to reverse engineer. so really the common reason for multiple css usually isn't for modularity, but lack of necessity to clean up. after the first load of the page, the css gets saved in the browser's cache so the real loss in bandwidth is minimal, even though there still is a loss.
  7. the beginning code for the slot machine is comparatively less than that of an individual slot. since each slot already has all the code it needs for itself, this makes the slot machine's job much easier: function slotMachine(element, slotscount, symbols){ if(!(this instanceof slotMachine)) return new slotMachine(element,slotscount,symbols); //default number of slots to 3 this.machine = element; slotscount = parseInt(slotscount) || 3; this.slots = []; this.machine.innerHTML = ""; for(var i = 0;i<slotscount;i++){ var s = document.createElement("div"); s.className = "slot"; this.machine.appendChild(s); this.slots[i] =slot(s,symbols); } } slotMachine.prototype.matches = function matches(){ if(this.slots.length<1) return false; var check = this.slots[0].current.className var match = function match(e,i,a){ return e.current.className == check; } //does the current symbol in each slot match? if(this.slots.every(match)) alert("match!"); } slotMachine.prototype.roll = function roll(){ for(var i=0;i<this.slots.length;i++){ this.slots[i].roll(); } setTimeout(this.stop,1000+Math.floor(Math.random()*500),this) } slotMachine.prototype.stop = function stop(self){ self = (this instanceof slotMachine) ?this :self; var index = 0; var dominoStop = function dominoStop(){ if(index==self.slots.length) return self.matches(); self.slots[index++].stop(dominoStop) } self.slots[index++].stop(dominoStop); } now when I wrote up slotMachine's stop method, I noticed that I needed to somehow pass the flow of control from slot to slot when the previous slot has finally stopped so after writing slotMachine's stop method the way I did, I went back to slot's stop method and changed it slightly: slot.prototype.stop= function stop(callback){ //if the slot isn't rolling do nothing. if(!this.rolling) return; var currentSpeed = this._rollspeed; var finalSpeed = false; var slowroll = function slowroll(self){ if(!self.rolling){ clearInterval(self._intervalID); self._intervalID = null; return callback(); } ...rest of the method ... the only change was the "callback" that was added. slot.stop() now expects a callback function to be passed in as an argument and once the slot finishes it's stopping animation it will return by running the callback. and through the glory of closures slotMachine's stop will still know the index it's iterating through and properly run the dominoStop (the callback function that was passed). html now becomes: <div id="slotMachine"></div><button onclick="sl.roll()" >spin</button> and the initialization code looks like this: var sl;window.onload = function(){ sl = slotMachine(document.getElementById("slotMachine"),3, ["red","green","green","blue","blue","blue"]);}; I spiced it up a little bit by including duplicate symbols. now there are 2 green spots and 3 blue spots in addition to the single red spot. this way the odds of each symbol aren't uniform. remember the slot constructor will take care of randomizing the symbols array for you. blue has a 50% of showing up in a slot (12.5% to match 3 blues) green now has a 1/3rds chance in a slot (~4% for 3 greens) and red has the lowest chance at 1/6th (~0.5% for 3 reds) I didn't add functionality for prizes/tokens and the match event is a simple alert for now. I can go further into this if you're curious. but for now I'm distracted in trying to get 3 reds.
  8. you should remove the table. Tables are meant to format tabular data. while you could put them to different uses from their original intention, browsers may not display them as you'd want them to. Now continuing from my previous post, I'll write the code for just a single slot: function slot(element,symbols){ if(!(this instanceof slot)) return new slot(element,symbols); //variables you see with a "_" prefix are intended to be used // internally. you could use them publicly but you shouldn't // need to... this.slot = element; this._intervalID = null; this._rollspeed = 75; this._rollDuration = 50;//20 frames/second; this.rolling = false; this.current = null; this.slot.innerHTML = ""; var sym = symbols.slice();//copy symbols array //populate the slot while(sym.length>0){ this.slot.appendChild(document.createElement("div")); this.slot.lastElementChild.className = sym.splice(Math.round(Math.random()*(sym.length-1)),1) } this._slotHeight = parseInt(getComputedStyle(this.slot) .getPropertyValue("height")); this._symbolHeight = parseInt(getComputedStyle(this.slot.firstElementChild) .getPropertyValue("height")); this._origin = Math.floor((this._slotHeight-this._symbolHeight)/2); //the origin is where the "current" element will start and stop at, // this is so the slots will properly line up in the end for(var i = this.slot.firstElementChild; i!=null; i = i.nextElementSibling){ i.style.top =(i.previousElementSibling == null) ? this._origin - this._symbolHeight+"px" :parseInt(i.previousElementSibling.style.top) + this._symbolHeight + "px"; if (i.style.top ==this._origin) this.current = i; } };slot.prototype.roll = function roll(){ var rollControl = function(self){ var iter = self.slot.firstElementChild; while(iter!=null){ iter.style.top = (parseInt(iter.style.top) + self._rollspeed + self._symbolHeight) %(self.slot.children.length*self._symbolHeight) - self._symbolHeight + "px"; iter = iter.nextElementSibling; } }; this._intervalID = setInterval(rollControl,this._rollDuration,this); this.rolling = true; }slot.prototype.stop= function stop(){ //if the slot isn't rolling do nothing. if(!this.rolling) return; var currentSpeed = this._rollspeed; var finalSpeed = false; var slowroll = function slowroll(self){ if(!self.rolling){ clearInterval(self._intervalID); self._intervalID = null; return; } var iter = self.slot.firstElementChild; while(iter!=null){ var pos = parseInt(iter.style.top) finalSpeed |= currentSpeed<=10 && pos>self._origin-self._symbolHeight/5 && pos<self._origin; iter.style.top = (pos + currentSpeed +self._symbolHeight) %(self.slot.children.length*self._symbolHeight) - self._symbolHeight + "px"; self.rolling &= parseInt(iter.style.top) != self._origin || !finalSpeed; if( !self.rolling && parseInt(iter.style.top) == self._origin){ this.current = iter; } iter = iter.nextElementSibling; } //the current speed will slow down, on each pass, to 5. // when a symbol nears the origin on the final pass, it will // decellerate faster down to a speed of 1. currentSpeed = finalSpeed ?Math.max(1,Math.floor(currentSpeed*.5)) :Math.max(4,Math.floor(self._symbolHeight/20), Math.floor(currentSpeed*.95)); } //change the linear rolling animation to a roll that slows to a stop. var changeroll = function changeroll(self){ clearInterval(self._intervalID); self._intervalID = setInterval(slowroll,self._rollDuration,self) } // add a short random delay between .75 and 1.25 seconds on when // the slowdown should begin setTimeout(changeroll,Math.floor(Math.random()*500)+750,this); } this is code for just a single slot. once this is hammered down, adding slots to the slot machine won't be hard... now to give this a test run I'm gonna go back to the html I wrote before and change it slightly like so: <div id="slot" class="slot"></div><button onclick="sl.roll()">roll</button><button onclick="sl.stop()">stop</button> the buttons here are temporary to demonstrate the example. the id is also temporary for this demonstration and will not be needed in the final product. the css is still the same, however. Now to initialize this slot we need to run this line onload var sl;window.onload = function(){sl = new slot(document.getElmentById("slot"),["red","green","blue"]);} this code is also stub code and won't be used in the final product. Notice that the slot constructor will automatically randomize the positions of the symbols inside the slot. And now when you click the buttons you should see the slot roll and stop as expected. I also added some extra code in the stopping animation so that it really appears to slow down instead of abruptly stopping. now that the code for a single slot has been cooked up, we finally need to work on the code that will handle multiple slots in a slot machine all together. that which I'll post soon.
  9. while its important to build a proper interaction matrix, you don't necessarily need to code to every possibility. Conway's game of life is a great example to this. it only has a couple extremely simple rules but the complexity of the patterns it makes is so advanced and beautiful. you don't need to code to 12 possibilities, just make a check that the 3 selected symbols match at the end of the roll. for now I'm going to split this up into multiple posts cause I want to take this a step at a time. The javascript portion will be a lot of code regardless how you'll plan to code it, so I'll be writing in OOP style, which info itself inherently requires more code and isn't as lightweight, but will be more stable and extendible. but 1st, lets start with the html and css. I'll show the example html for just one slot and then we can extrapolate from that later. <div class="slot"> <div class="red" style="top:-160px;"></div> <div class="green" style="top:0px;"></div> <div class="blue" style="top:180px;"></div></div> css: .slot{ position: relative; height: 200px; width: 200px; overflow:hidden;}.slot>div{ position: absolute; height: 180px; width: 200px;}.red{background-color:red;}.green{background-color:green;}.blue{background-color:blue;} so now what we made is a simple slot with the colors representing the future symbols. when we're ready to put those images in don't put them in as img tags but as background-images for those .red/.green/.blue divs this way the browser will only preload the image once for all future images and not per tag (will also save tons of bandwidth). In my next post I'll go into the javascript for just a single slot and how it will be animated.
  10. jQuery itself doesn't use window.onload (at least not directly) but he does have a window.onload line there near the bottom of his html code snippet. my assumption as to why the css style, display:none isn't working is because there is already a $(document).ready() in place that runs a .show() or a .fadeIn() or something similar on the objects which makes jQuery overwrite those styles
  11. try... window.onload=closeProjects; instead of.. window.onload=closeProjects(); likely whats happening is that its closing immediately right there on the line and not when the page finishes loading. then… your pk.js runs it's $(document).ready() which I assume builds up the project and then in the process shows it again (I didn't dig deep into the code so I'm not certain). So its likely trying to close the project before its even created on the page. then when the page fully loads the project is then created and opened, AFTER closeProjects was called (which ran immediately and not when window.onload was supposed to fire). a better option would be to have closeProjects() run at the end of the $(document).ready() inside the pk.js so that its kept more encapsulated with the external script, that is if you want every page to automatically close the project when the page loads.
  12. do you want the english and french paragraphs to be shown and hidden independently from each other (as in if you hide the english, french is unaffected, and when you show english again, french is still unaffected?) well what you can do create event handlers by css class and not just by element ID. with id, only one element will be used for all the event handling, but if you create event handles by classes, then you can have individual elements handle events relative to the elements around them. I might've not explained that as well as I could. so let me show by example. first lets group each button with the paragraph tag that it will be in charge of hiding, like so: HTML: <div> <p> this is my english paragraph. blah blah blah </p> <button class="collapsible">hide</button></div><div> <p> this is my french paragraph. Aren't you impressed at how fluent I am? </p> <button class="collapsible">hide</button></div> notice that the button and the paragraph it'll hide are direct siblings. plus there is only ONE paragraph in each div tag. next lets add in some special CSS rules to apply only when certain classes are added. CSS: .hidden>p {display:none;} what that means is that any paragraph element whose direct parent just so happens to have a class "hidden" then that paragraph must hide itself. what this grants us is the ability to independently hide each paragraph separately. so if one div has class="hidden", it only hides the paragraph thats directly inside it and won't affect any other paragraph. now, lets go ahead and add in the jQuery to make sure hidden gets added and removed like you want: jQuery: $(document).ready(function(){ $(".collapsible").click(function(){ var button = $(this); //goes to the buttons parent (the div) and // adds the hidden class if its not there // otherwise it removes the hidden class so // that the paragraph will reshow button.parent().toggle("hidden"); //if the paragraph is hidden, change button // text to "show". Otherwise paragraph is // visible, change button text to "hide" button.parent().hasClass("hidden") ?button.text("show") :button.text("hide"); });}); what this does is that it looks for all elements that have the "collapsible" class (those will be the buttons) and attaches on click even handlers so that when the user clicks them jQuery will add/remove the hidden class from the div tags which are holding a paragraph, and at the same time the text in the button should update correctly as well. so to walk you through what is happening, when you click on a button, it's on click even will trigger, starting its unique function. this function will look at the button that was clicked and move up to the element thats containing the button (the div tag). It will then either add OR remove the class "hidden" to/from the tag, depending if it was already there. then makes sure the button updates with the correct text. afterwards CSS will kick in and notice that the styling on this one element has changed. Thus the browser will automatically update and cascade all the styles that have to do with it, which results in the child paragraph's display being changed to none/default.
  13. here is an expandable script which calculates a variable amount of numbers you providehowever , I don't think this is quite the answer you might be looking for (not sure if you even had a question; you weren't exactly clear). <!DOCTYPE html><html> <head> <script> var list,avg; window.onload = function (){ list = document.getElementById("list"); avg = document.getElementById("average"); //start with 10 default blanks for (var i=0;i<10;i++) add(); } //allows you to set as many numbers as you want. //builds a textfield and a remove button to go with it function add(){ var input, div = document.createElement("div"); list.appendChild(div); input = document.createElement("input"); input.type = "text"; input.onkeyup = calc; div.appendChild(input); input.focus(); input = document.createElement("input"); input.type = "button"; input.value="Remove" input.onclick = function(){ this.parentElement.remove(); return calc(); }; div.appendChild(input); return calc(); } //removes all numbers function reset(){ while(list.firstElementChild != null) list.firstElementChild.remove(); return calc(); } //finds the average of only the numbers it can parse function calc(){ var iter = list.firstElementChild; var sum = 0; var count = 0; while(iter !=null){ var val = parseFloat(iter.firstElementChild.value) if(!isNaN(val)){ sum += val; count++; } iter = iter.nextElementSibling; } avg.innerHTML = isNaN(sum/count) ?"" :sum/count; } </script> </head> <body> <div id="list"></div> <input type="button" value="add" onclick="add()"> <input type="button" value="reset" onclick="reset()"> <div>Average:<span id="average"></span></div> </body></html>
  14. The problem is that console.log(imgWidth); is not inside the load call, so its running instantly and the load call will run later when the image loads. so right now, imgWidth is still undefined when that console is running. javascript doesn't run a function as soon as it's spotted. it looks at all the functons in the scope first (which weren't defined literally) and makes sure its closed correctly then it starts at the top and moves down. Javascript only goes back to that function actually look and runs whats inside it when something tells it to (in this case thats the img onload event). so at the highest level it'll see var imgWidth;$(blah blah) it sees no function definition so it works from top down, declaring imgWidth and then running the jQuery function. So inside this $() function it first looks for function declarations then starts top down. At this scope level that's just the anonymous function (){blah blah} so it makes note of it at this scope and then $() will force it to run immediately so Javascript now moves inside this anonymous function: $("img").load(function (){blah blah));console.log(imgWidth); in this scope it 1st checks for all functions not defined literally (the load function wasn't defined literally, but its defined inside another scope so javascript doesn't see it yet) and finds nothing so it works top down again. on the first line it finds theres is an onload function that was defined. right now it just remembers that there is a function there but doesn't actually worry about it until someone needs to use it (when the img loads) so then it moves on the console.log(). Well at this point the onload function hasn't run yet so when it runs the console.log imgWidth is still undefined. then some time later (however short it is) that image finishes loading and then fires the onload event for that img. then javascript will actually look inside that load function to do whats inside of it.
  15. they aren't using css :hover to provide that effect (or at least not exclusively), that is most likely javascript performing animations on those elements with an onmouseenter event.
  16. I've recently used a formula to calculate in log base 10, and you do need to be wary of rounding errors when diving one log by another. for example: log2(100) / log2(10) == log10 (100) == 2 however in javascript Math.log(100) / Math.log(10) will equal something like 1.99999999...due to those floating-point rounding errors. something to be mindful of
  17. force of habit. I like to make sure when I want a number I append a +0 in case the passed in value could be a non-number, so that javascript casts the variable to a number. if the value is already a number nothing really happens. if its a boolean true becomes 1 and false 0. undefined and nulls become 0. and objects should run their valueOf() method automatically. while strings that don't appear as numbers will become NaN (as far as javascript is concerned, NaN or Not-a-Number, is a number... just a special type). sometimes javascript can be confused as to whether a primitive should be a string or number, as it all depends on the context of the value being used. The Math object should provide the right context, though, and often times you needn't worry. This is just a simple enforcement of the type-casting. this habit of mine mostly originated from writing out formulas in Excel, when I wanted something to be either X or 1, or either X or 0, based on a true/false data validation field you would have to do either X^boolean or X*boolean to get that.
  18. sin, cos, and tan are property methods of the Math object, and you're just passing sin cos and tan. Javascript has no idea what those are. include the entire Math.sin, Math.cos, and Math.tan into the function calls. <input type="button" value="sin" onClick="trig('gets',Math.sin);" class="its" ><input type="button" value="tan" onClick="trig('gets',Math.tan);" class="its" ><input type="button" value="cos" onClick="trig('gets',Math.cos);" class="its" > the trig function has the entire function reference this way so the it doesn't even need to know that it's using the Math object or it's trig methods function trig(el,oprtr){ var m=document.getElementById(el); m.value=oprtr((m.value+0));}
  19. you can't prevent people from saving a video thats streaming onto their PC. Just like you can't read my post and then not be allowed to remember it. You can make it harder for the user to save the video. but anyone who can see the video can work hard enough to save it. be it by either viewing the browser resources to see the actual video file the server is letting the browser 'borrow', by fishing the video out of the browser cache, or by performing actual video capture with some program like camtasia.
  20. setTimeout doesn't stop the flow of the code. the code still runs on even after you call setTimeout. its a "do this at a later time" method, not a "hold off everything until after this function is called" method. if it did... then there'd be no point of functions like clearTimeout or clearInterval as the code could never reach it.use this show function function show(el){ var m=document.getElementById(el).style; var delayHide = funtion delayHide (){ m.display = "none"; } m.display="block"; return setTimeout(delayHide,1000);}
  21. no, local storage is better than cookies in every way. it can store more information than cookies can ever dream to, its far more secure as websites can't access other websites local storage, and consumes far less bandwith/overhead (local storage starts and ends on the client's browser, it never goes to the server. and it is only accessed when needed, cookies are always parsed even if you're not gonna use them). your jsfiddle didn't include the jQuery library, so its not even getting to anything inside that $(document).ready. you also forgot to check if local storage is supported on the browser. older browsers do not have this support and will simply error cause it doesn't know what localstorage is. you also need to enforce html5 doctype (which your jsfiddle is doing)
  22. if you want to follow that example you posted at the top, I think we can manage to pull that off with far less code. first take a look at your example and look for the patterns. every week these three people (I'll call $workers) rotate their jobs (I'll call $shifts) using modulus and arrays, its not hard to change each worker's shift every week. also PHP has it's own Date class that handles ALLLL that code you have in figuring out the date, just for you. While you are using Date here and there, you're not really harnessing its potential and just "re-inventing the wheel". <?php$workers = array("Dan","Mike","Les");$shifts = array("Puller","Ground","Loco");$date = new DateTime();//set the date to what the webpage requests hereif(isset($__POST['year'])&& isset($__POST['month'])) $date->setDate($__POST['year'],$__POST['month'],1); //sets date to whats been requested, defaults to today's date$shownMonth = $date->format('m');//if sunday isn't the 1st day in the the month, prepends empty table cells // so if the first day in the month is wednesday then 3 blank cells are made// for sunday, monday, and tuesdayif($date->format('w')!=0)echo '<tr>';for($i=0;$i<$date->format('w');$i++){ ?><td></td><?php}while($date->format('m')==$shownMonth){ if($date->format('w')==0)echo '<tr>';?> <td> <span class="text_16_white"> <?=$date->format('j');?> </span> <?php for($i=0;$i<count($shifts);$i++) echo '<br />'.$shifts[i].":".$workers[(i+intval($date->format('W'))%count($workers)); ?> </td> <?php if($date->format('w')==6)echo '</tr>'; $date->modify('+1 day');//iterates to the next day}//this fills out the last week if the last day in the month isn't saturdayfor($i=6;$i>$date->format('w');$i++){?><td></td><?php }if($date->format('w')!=6)echo '</tr>';?> now... place that inside the table html like so.. <html> <head></head> <body> <table> PHP STUFF IN PREVIOUS CODE BLOCK GOES HERE </table> </body></html> now the code provided isn't everything you have on your page, for example I haven't added the "if day in calender is today, use this style" you have nor the "print this month's name" but really all you need to do for each is: $date->format('F'); //returns a string of that date's month name... Or it'll print the current month's name ("December") by default//if $date is today$today = new DateTime();if($date->format("o m d")==$today->format("o m d")) I will be honest... its been quite a while since I actually programmed in PHP so I can't say the code is bug-proof. but the spirit should be there in full.
  23. var obj = {key:value};//is just shorthand forvar obj = new Object();obj.key = value;//just like...var arr = [1,2,3,4,5];//is just shorthand forvar arr = new Array(1,2,3,4,5); While Function is-a Object (Function extends/inherits Object), using curly bracs directly wouldn't create a function with properties but just an object. The closest,that I know of, you could possibly get to that shorthand is: var func1 = Object.create(function myfunc(){/*my statements*/},{key:value});alert(typeof func1)//prints: "function"alert(func1.key) // prints the value, whatever it isalert(func1())// runs the function, and if it has something to return, it'll print it
  24. you could use function memoization where the function redefines its own self after performing an execution once. you can also give the function an extra property as if its an object (because in javascript it IS an object) function show(){ //1st call, javascript will start running code from here //this is memoization, redefing the function inside itself // after the first time show runs, only whats defined inside HERE will run. // the code after this definition runs only once. show = function show(){ //2nd and later calls, javascript will start running code from here //do your regular everyday stuff in here. //2nd and later calls will stop here } //this code runs only once, the first time it's called show.hasRun = true; return show(); //calls show a second time //1st call stops here}//hasRun will be undefined (which evals to false) if show() wasn't called, otherwise is will be true)if(show.hasRun){/*do this*/} With memoization. The entire function code can change "states" each time it is called, or simply just the first time its called (like in this example). Its usually used as a performance optimization where expensive calculations (that either take a lot of time to compute, or is just redundant to run again) only need to be run once, actually run only once. however if the if statment is just inside a script tag and not in it's own function, I'm not sure its the best way to check if show(), a function that runs in a onclick event, would ever work, I assume its not though.
  25. Hadien

    a simple game

    well you have the the 2d array thats one thing. with each block tracking 1 of 3 states (" ", "X", and "O"). you then need to track the current player's turn which isn't difficult, and make sure they can only add their symbol in empty blocks. and after the block is change check it's matches in the 4 directions. (I'm just stating the obvious here, but it helps when you try to code something to declare the requirements first) var Player = ["X","O"];var Board = [ [" "," "," "], [" "," "," "], [" "," "," "]];var gameover = false;var turn = 0;function ticTacToe(y,x){ var value = Board[y][x]; //these 3 functions will be run through the Array.every function // though I don't use the arguments properly, it will perform // expected behavior and see if all elements in any of the 4 lines // (horizontal, vertical, or 2 diagonals) match the added symbol var horz = function (e, i, a) {return (value == a[y][i]);}; var vert = function (e, i, a) {return (value == a[i][x]);}; var diag = function (e, i, a) {return (y+x)%2!=1 && value == a[y==x ?i :2-i][i];}; //check for any matches // if no matches here then theres no TicTacToe // again, not using .every() "exactly" as it was intended // but the code this way is very minimalistic return Board.every(horz) || Board.every(vert) || Board.every(diag);}function mark(el, y,x){ //if the game is over, // or if the players haven't had enough turns to possibly win, // or if the tile selected already has a X/O // then do nothing and save on unnecessary checking. if(gameover || turn<4 || Board[y][x]!= " ") return; //set currentPlayer's symbol into block, and update Board[y][x] = Player[turn%2]; el.innerHTML = Board[y][x]; //check for ticTacToe if(ticTacToe(y,x)){ alert(Player[turn%2]+ " wins!"); gameover = true; } // otherwise go to next player's turn turn++;} and your table should look like this, no ID needed <table> <tr > <td onClick="mark(this,0,0);"></td> <td onClick="mark(this,0,1);"></td> <td onClick="mark(this,0,2);"></td> </tr> <tr > <td onClick="mark(this,1,0);"></td> <td onClick="mark(this,1,1);"></td> <td onClick="mark(this,1,2);"></td> </tr> <tr > <td onClick="mark(this,2,0);"></td> <td onClick="mark(this,2,1);"></td> <td onClick="mark(this,2,2);"></td> </tr></table>
×
×
  • Create New...