<pedrocorreia.net ⁄>
corner
<mySearch ⁄> <mySearch ⁄>

corner
 
corner
<mySnippets order="rand" ⁄> <mySnippets order="rand" ⁄>

corner
 
corner
<myContacts ⁄> <myContacts ⁄>

<email ⁄>


pc@pedrocorreia.net

<windows live messenger ⁄>


pedrojacorreia@hotmail.com

<myCurriculum type="pdf" ⁄>


Download
corner
 
corner
<myBlog show="last" ⁄> <myBlog show="last" ⁄>

corner
 
corner
<myNews show="rand" ⁄> <myNews show="rand" ⁄>

corner
 
corner
<myNews type="cat" ⁄> <myNews type="cat" ⁄>

corner
 
corner
<myQuote order="random" ⁄> <myQuote order="random" ⁄>

corner
 
corner
<myPhoto order="random" ⁄> <myPhoto order="random" ⁄>

<pedrocorreia.net ⁄>
corner
 
corner
<myAdSense ⁄> <myAdSense ⁄>

corner
 
corner
<myVisitorsMap ⁄> <myVisitorsMap ⁄>

corner
 
 

<Javascript Tic Tac Toe ⁄ >




clicks: 17517 17517 2009-02-24 2009-02-24 goto mySnippets mySnippets javascript  Download  Bookmark This Bookmark This



Here's a game that, I think, almost everyone knows about, Tic-Tac-Toe, who never played this one?
I’ll try to give a full working example, well, almost full, I won’t implement a Human vs Computer, only Human Vs Human, later on a future snippet I'll try to do it.
If you still can’t figure it out, what Tic-Tac-Toe means, please check this link in wikipedia

The algorithm will be a rather basic one, I'll just make a brute force to check if the last player has a winning path, this is, we'll have an object that keeps all valid moves to win a game, and at each player move, will check it.

We'll have 9 squares, each one will have an internal number (0 until 8), starting at upper left corner, like the following picture:





style.css
  1. *{padding: 0; margin: 0;}
  2.  
  3.  
  4. body{
  5. font-family: Verdana, Tahoma, Arial, sans-serif;font-size: 62.5%;
  6. color: #000;background-color: #fff;text-align: center;
  7. }
  8.  
  9.  
  10. div#board_title{
  11. margin: 0 auto; text-align: center; font-weight: 900;color: #cc0000;
  12. font-size: 3em;width: 27.4em; margin-bottom: .5em;
  13. }
  14.  
  15.  
  16. div#board{margin: 0 auto;width: 27.4em;height: 27.4em;}
  17. div#board div{
  18. float: left;border: solid 0.2em #ce5c00;cursor: pointer;
  19. width: 8.6em;height: 8.6em; line-height: 8.6em;
  20. }
  21. div#board div#square0,div#board div#square1,
  22. div#board div#square3,div#board div#square4,
  23. div#board div#square6,div#board div#square7{border-left: 0; border-top: 0;}
  24. div#board div#square2,div#board div#square5,
  25. div#board div#square8{border-right: 0; border-top: 0; border-left: 0;}
  26. div#board div#square6,div#board div#square7,
  27. div#board div#square8{border-bottom: 0;}
  28. div#board div.player1,
  29. div#info div#board_info div.player1{background: url("player1.gif") no-repeat center center; color: #fff;}
  30. div#board div.player2,
  31. div#info div#board_info div.player2{background: url("player2.gif") no-repeat center center;}
  32. div#board div.win{background-color: #ffff99;}
  33. div#board div.clear{background: none;}
  34.  
  35.  
  36. div#info{margin: 0 auto; width: 46em;}
  37.  
  38. div#info div#board_console{
  39. float: left;
  40. width: 26.5em;
  41. border: dashed .2em #cc0000;
  42. padding: .4em;line-height: 2em;
  43. }
  44. div#info div#board_console span{
  45. color: #fff;font-weight: 700;padding: .1em;
  46. }
  47. div#info div#board_console span.player1{background-color: #204a87;}
  48. div#info div#board_console span.player2{background-color: #4e9a06;}
  49. div#info div#board_console span.draw{background-color: #cc0000;}
  50.  
  51. div#info div#board_control, div#info div#board_info{
  52. float: right;
  53. border: solid .5em #ce5C00;
  54. line-height: 1.8em;
  55. padding: .2em;width: 16.5em;
  56. }
  57. div#info div#board_control input{
  58. background-color: #ffffd4; border: solid .1em #e9b96e;
  59. font-size: 1em; font-weight: 700; padding: .4em;
  60. }
  61. div#info div#board_control label.player{font-weight: 700; font-size: 2em;float: right;}
  62. div#info div#board_control label.one{color: #204a87;}
  63. div#info div#board_control label.two{color: #4e9a06;}
  64. div#info div#board_control label.draw{color: #cc0000;}
  65. div#info div#board_control span{float: left;}
  66.  
  67. div#info div#board_info{margin-top: .4em; clear: right; height: 8em;color: #000;}
  68. div#info div#board_info div{height: 5.8em;background-position: center top;}



Events.js, this file's responsible for events management, that is, our page has elements and those elements will react to events/ triggers, with this class we'll be able to add or remove events, such as onchange, onload, etc, etc.
  1. /**
  2. * Static Class
  3. * Manage Events
  4. */
  5. Events = function(){}
  6.  
  7. /**
  8. * Add Event
  9. *
  10. * Source and full credits to:
  11. * http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
  12. *
  13. * @param Object
  14. * @param Object
  15. * @param Object
  16. */
  17. Events.AddEvent = function(obj, type, fn){
  18. if(!obj) return;
  19.  
  20. this.RemoveEvent(obj, type, fn);
  21. if (obj.addEventListener) {obj.addEventListener(type, fn, false);}
  22. else {
  23. if (obj.attachEvent) {
  24. obj["e" + type + fn] = fn;
  25. obj[type + fn] = function(){
  26. obj["e" + type + fn](window.event);
  27. }
  28. obj.attachEvent("on" + type, obj[type + fn]);
  29. }
  30. }
  31. }
  32.  
  33. /**
  34. * Remove Event
  35. *
  36. * Source and full credits to:
  37. * http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
  38. *
  39. * @param Object
  40. * @param Object
  41. * @param Object
  42. */
  43. Events.RemoveEvent = function(obj, type, fn){
  44. if (obj.removeEventListener) {
  45. try{obj.removeEventListener(type, fn, false);}catch(e){}
  46. }
  47. else{
  48. if (obj.detachEvent) {
  49. obj.detachEvent("on" + type, fn);
  50. obj[type + fn] = null;
  51. obj["e" + type + fn] = null;
  52. }
  53. }
  54. }



Dom.js, responsible for the DOM operations
  1. /**
  2. * Static Class
  3. *
  4. * A few basic DOM manipulations
  5. *
  6. * @author: pedrocorreia.net
  7. */
  8. Dom = function(){}
  9.  
  10. /**
  11. * Get Html Object reference
  12. *
  13. * @param String Id Object
  14. */
  15. $=function(id){return document.getElementById(id);}
  16.  
  17. /**
  18. * Get, set or append html object css class
  19. *
  20. * @param Object Html Object
  21. * @param Optional String Class Name
  22. * @param Optional Int Append Class?
  23. */
  24. $class=function(obj /**, css_class**/ /**, append*/){
  25. if(arguments[1] && arguments[2]){$(obj).className+=" "+arguments[1];}
  26. else if(arguments[1]){$(obj).className=arguments[1];}
  27. else{return $(obj).className;}
  28. }



Messages.js, all game messages
  1. /**
  2. * Static Class
  3. *
  4. * Language file
  5. *
  6. * @author: pedrocorreia.net
  7. */
  8. Messages = function(){}
  9.  
  10. /**
  11. * Where game's already finished
  12. *
  13. * @param String Player Name
  14. * @param Int Who won the game
  15. */
  16. Messages.AlreadyFinished = function (name, number){
  17. var str="";
  18. switch (number){
  19. case 0:
  20. str="Draw.";
  21. break;
  22. default:
  23. str=name+" "+number+"'s the winner!";
  24. break;
  25.  
  26. }
  27. return "Game already finished. "+str+"\n\Please press \"New Game\"";
  28. }
  29.  
  30. /**
  31. * Square already filled
  32. */
  33. Messages.SquareFilled = function(){
  34. return "Square already filled!";
  35. }
  36.  
  37. /**
  38. * Who won the game
  39. */
  40. Messages.Winner = function(clss, name, number, path){
  41. return "<span class='"+clss+"'>"+name+": "+number+", won the game<span> | Squares: "+path;
  42. }
  43.  
  44. /**
  45. * Draw message
  46. */
  47. Messages.Draw = function(clss){
  48. return "<span class='"+clss+"'>The game finished tied up!</span>"
  49. }
  50.  
  51. /**
  52. * Trace move
  53. *
  54. * @param String Player Name
  55. * @param Int Player Id
  56. * @param Int Square filled
  57. */
  58. Messages.TraceMove = function(name, number, square){
  59. return "<b>"+name+":</b> "+number+" | <b>Square:</b> "+square;
  60. }








TicTacToe.js, our main file, will manage all the game
  1. /**
  2. * This class implements the popular game Tic-Tac-Toe
  3. *
  4. * @author: pedrocorreia.net
  5. */
  6. TicTacToe = function (){
  7.  
  8. //needed to allow private functions to call public methods
  9. var self=this;
  10.  
  11. //saves all board moves
  12. var _board_moves;
  13.  
  14. //all possible winning moves
  15. var _win_moves = {
  16. 1: {pos1: 0, pos2: 1, pos3: 2},
  17. 2: {pos1: 3, pos2: 4, pos3: 5},
  18. 3: {pos1: 6, pos2: 7, pos3: 8},
  19. 4: {pos1: 2, pos2: 4, pos3: 6},
  20. 5: {pos1: 0, pos2: 3, pos3: 6},
  21. 6: {pos1: 1, pos2: 4, pos3: 7},
  22. 7: {pos1: 2, pos2: 5, pos3: 8},
  23. 8: {pos1: 0, pos2: 4, pos3: 8}
  24. }
  25.  
  26. //game settings
  27. var _settings = {
  28. num_squares: 9,
  29. min_plays_check: 5,
  30. player: "Player",//generic player name
  31. prefix_square: "square",
  32. class_player1: "player1",
  33. class_player2: "player2",
  34. lbl_points_player1: "lbl_player1",
  35. lbl_points_player2: "lbl_player2",
  36. lbl_points_draw: "lbl_draw",
  37. class_winning: "win",
  38. class_draw: "draw",
  39. console: "board_console"
  40. }
  41.  
  42. //game statistics
  43. var _stats = {
  44. current_player: 1,
  45. num_plays: 1,
  46. winning_player: -1,
  47. points_player1: 0,
  48. points_player2: 0,
  49. points_draw: 0
  50. }
  51.  
  52. /**
  53. * Next move
  54. */
  55. var _NextPlayer = function(){
  56. _stats.current_player=(_stats.current_player==1)?2:1;
  57. _stats.num_plays++;
  58. $class("next_player",_CurPlayerClass());
  59. }
  60.  
  61. /**
  62. * Get current player css class
  63. */
  64. var _CurPlayerClass = function(){
  65. return (_stats.current_player==1)?_settings.class_player1:_settings.class_player2;
  66. }
  67.  
  68. /**
  69. * Add Events
  70. */
  71. var _EventHandlers = function(){
  72. var fn;
  73. for (var i=0;i<_settings.num_squares;i++){
  74. fn=(function(i){return function(){ _Select (i);}})(i);
  75. Events.AddEvent($(_settings.prefix_square+i),"click",fn);
  76. }
  77.  
  78. Events.AddEvent($("bt_new_game"),"click",self.NewGame);
  79. Events.AddEvent($("bt_reset"),"click",_Reset);
  80. }
  81.  
  82. /**
  83. * Check if the selected square is filled or not and check if the
  84. * current player has a winning path.
  85. *
  86. * @param Int Número da Casa
  87. */
  88. var _Select = function(i){
  89.  
  90. //check if the game ended, having or not a winner
  91. if(_stats.winning_player>-1 || _stats.num_plays>_settings.num_squares){
  92. alert(Messages.AlreadyFinished(_settings.player,_stats.winning_player));
  93. return;
  94. }
  95.  
  96. if(_IsSquareEmpty(i)){ //check id the selected square is already filled
  97. $class(_settings.prefix_square+i,_CurPlayerClass());
  98. _MarkSquare(i,_stats.current_player);
  99. _TraceValidMove(i);
  100. _CheckBoard(_stats.current_player);
  101. _NextPlayer(); //next move
  102. }
  103. else{
  104. alert(Messages.SquareFilled()); //square already filled
  105. }
  106. }
  107.  
  108. /**
  109. * Check if the selected square is available
  110. *
  111. * @param Int Square number
  112. * @return Bool
  113. */
  114. var _IsSquareEmpty = function(pos){return (_board_moves[pos]==0);}
  115.  
  116. /**
  117. * Fill the squre, making it unavailable.
  118. *
  119. * @param Int Square number
  120. * @param Int Player number
  121. */
  122. var _MarkSquare = function(pos, player){_board_moves[pos]=player;}
  123.  
  124. /**
  125. * Log move
  126. *
  127. * @param Int Square number
  128. */
  129. var _TraceValidMove = function(square){
  130. var str=Messages.TraceMove(_settings.player,_stats.current_player,square+1);
  131. $(_settings.console).innerHTML+=str+"<br/>";
  132. }
  133.  
  134. /**
  135. * Check if in the current move, the player has a winning path
  136. *
  137. * @param Int Player number
  138. */
  139. var _CheckBoard = function(player){
  140. if(_stats.num_plays<_settings.min_plays_check){return;}
  141.  
  142. var count=0;
  143. var square="";
  144.  
  145. for (var move in _win_moves){
  146. for (var i=1;i<=3;i++){
  147. square=_board_moves[_win_moves[move]["pos"+i]];
  148. if(square==player){count++;}
  149. }
  150.  
  151. if (count==3){
  152. var path="";
  153. for (var i=1;i<=3;i++){
  154. square=_settings.prefix_square+_win_moves[move]["pos"+i];
  155. $class(square,_settings.class_winning,1);
  156. path+=(_win_moves[move]["pos"+i]+1)+";";
  157. }
  158.  
  159. _stats.winning_player = player;
  160. $(_settings.console).innerHTML+=Messages.Winner(_CurPlayerClass(),_settings.player,player,path);
  161.  
  162. _stats["points_player"+player]++;
  163. $(_settings["lbl_points_player"+player]).innerHTML=_stats["points_player"+player];
  164. return;
  165. }
  166.  
  167. count=0;
  168. }
  169.  
  170. if(_stats.num_plays==_settings.num_squares){
  171. _stats.points_draw++;
  172. _stats.winning_player = 0;
  173. $(_settings.lbl_points_draw).innerHTML=_stats.points_draw;
  174. $(_settings.console).innerHTML+=Messages.Draw(_settings.class_draw);
  175. }
  176. }
  177.  
  178. /**
  179. * Reset
  180. */
  181. var _Reset = function(){
  182. _stats.points_player1=0;
  183. _stats.points_player2=0;
  184. _stats.points_draw=0;
  185. $(_settings.lbl_points_player1).innerHTML=_stats.points_player1;
  186. $(_settings.lbl_points_player2).innerHTML=_stats.points_player2;
  187. $(_settings.lbl_points_draw).innerHTML=_stats.points_draw;
  188.  
  189. self.NewGame();
  190. }
  191.  
  192. /**
  193. * Start a new Game
  194. */
  195. this.NewGame = function(){
  196. for (var i=0;i<_settings.num_squares;i++){
  197. $class(_settings.prefix_square+i,"clear");
  198. $(_settings.prefix_square+i).innerHTML=(i+1);
  199. }
  200.  
  201. _stats.num_plays=1;
  202. _stats.current_player=1;
  203. _stats.winning_player=-1;
  204. _board_moves = new Array(0,0,0,0,0,0,0,0,0);
  205. $(_settings.console).innerHTML="";
  206. $class("next_player",_settings.class_player1);
  207. }
  208.  
  209. //EventHandlers
  210. _EventHandlers();
  211. }



Init.js, this is where initially events will be triggered.
  1. /**
  2. * Init function
  3. *
  4. * @author pedrocorreia.net
  5. */
  6. Init = function(){
  7. var tic_tac_toe=new TicTacToe();
  8. tic_tac_toe.NewGame();
  9. }
  10.  
  11. Events.AddEvent(window,"load",Init);



index.htm,
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  3. <html xmlns="http://www.w3.org/1999/xhtml" >
  4. <head>
  5. <title>Tic-Tac-Toe</title>
  6. <link rel="stylesheet" href="style.css" />
  7. <script type="text/javascript" src="Events.js"></script>
  8. <script type="text/javascript" src="Dom.js"></script>
  9. <script type="text/javascript" src="Messages.js"></script>
  10. <script type="text/javascript" src="TicTacToe.js"></script>
  11. <script type="text/javascript" src="Init.js"></script>
  12. </head>
  13.  
  14. <body>
  15. <div id="board_title">Tic-Tac-Toe</div>
  16.  
  17. <div id="board">
  18. <div id="square0"></div>
  19. <div id="square1"></div>
  20. <div id="square2"></div>
  21. <div id="square3"></div>
  22. <div id="square4"></div>
  23. <div id="square5"></div>
  24. <div id="square6"></div>
  25. <div id="square7"></div>
  26. <div id="square8"></div>
  27. </div>
  28.  
  29. <div id="info">
  30.  
  31. <div id="board_console"></div>
  32.  
  33. <div id="board_control">
  34. <span>Stats Player 1:</span> <label id="lbl_player1" class="player one">0</label>
  35. <br />
  36. <span>Stats Player 2:</span> <label id="lbl_player2" class="player two">0</label>
  37. <br />
  38. <span>Draws:</span> <label id="lbl_draw" class="player draw">0</label>
  39. <br /><br />
  40. <input type="button" value="New Game" id="bt_new_game" />
  41. <input type="button" value="Reset" id="bt_reset" />
  42. </div>
  43.  
  44. <div id="board_info">Next move<div id="next_player"></div></div>
  45.  
  46. </div>
  47. </body>
  48.  
  49. </html>




Here's a full working example of this snippet, convince a friend to Play with you ^_^''




If you have any doubt or found any error, please drop me an email.









clicks: 17517 17517 2009-02-24 2009-02-24 goto mySnippets mySnippets javascript  Download  Bookmark This Bookmark This