├── TIC TAC TOE - PART 1 ├── game.js ├── options.js ├── index.html ├── img │ ├── O.png │ ├── X.png │ └── tie.png ├── font │ └── jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 └── style.css ├── TIC TAC TOE - PART 2 ├── img │ ├── O.png │ ├── X.png │ └── tie.png ├── font │ └── jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 ├── index.html ├── options.js ├── style.css └── game.js ├── TIC TAC TOE - FINAL CODE ├── img │ ├── O.png │ ├── X.png │ └── tie.png ├── font │ └── jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 ├── index.html ├── options.js ├── style.css └── game.js └── README.md /TIC TAC TOE - PART 1/game.js: -------------------------------------------------------------------------------- 1 | // GAME CODE -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/options.js: -------------------------------------------------------------------------------- 1 | // OPTIONS CODE -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/img/O.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 1/img/O.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/img/X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 1/img/X.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/img/O.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 2/img/O.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/img/X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 2/img/X.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/img/tie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 1/img/tie.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/img/tie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 2/img/tie.png -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/img/O.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - FINAL CODE/img/O.png -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/img/X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - FINAL CODE/img/X.png -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/img/tie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - FINAL CODE/img/tie.png -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 1/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - PART 2/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CodeExplainedRepo/Tic-Tac-Toe-JavaScript/HEAD/TIC TAC TOE - FINAL CODE/font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2 -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tic Tac Toe - JavaScript 8 | 9 | 10 | 11 |
12 | 13 |
14 |

Tic Tac Toe

15 | 16 |

Play Versus

17 |
COMPUTER
18 |
FRIEND
19 | 20 |

Symbol

21 |
X
22 |
O
23 | 24 |
PLAY
25 |
26 |
27 |
28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tic Tac Toe - JavaScript 8 | 9 | 10 | 11 |
12 | 13 | 14 |
15 |

Tic Tac Toe

16 | 17 |

Play Versus

18 |
COMPUTER
19 |
FRIEND
20 | 21 |

Symbol

22 |
X
23 |
O
24 | 25 |
Play
26 |
27 | 28 |
29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/options.js: -------------------------------------------------------------------------------- 1 | // SELECT START ELEMENT 2 | const options = document.querySelector(".options"); 3 | 4 | // SELECT BUTTONS 5 | const computerBtn = document.querySelector(".computer"); 6 | const friendBtn = document.querySelector(".friend"); 7 | const xBtn = document.querySelector(".x"); 8 | const oBtn = document.querySelector(".o"); 9 | const playBtn = document.querySelector(".play"); 10 | 11 | // GAME OVER ELEMENT 12 | const gameOverElement = document.querySelector(".gameover"); 13 | 14 | const player = new Object; 15 | let OPPONENT; 16 | 17 | oBtn.addEventListener("click", function(){ 18 | player.man = "O"; 19 | player.computer = "X"; 20 | player.friend = "X"; 21 | 22 | switchActive(xBtn, oBtn); 23 | }); 24 | 25 | xBtn.addEventListener("click", function(){ 26 | player.man = "X"; 27 | player.computer = "O"; 28 | player.friend = "O"; 29 | 30 | switchActive(oBtn, xBtn); 31 | }); 32 | 33 | computerBtn.addEventListener("click", function(){ 34 | OPPONENT = "computer"; 35 | switchActive(friendBtn, computerBtn); 36 | }); 37 | 38 | friendBtn.addEventListener("click", function(){ 39 | OPPONENT = "friend"; 40 | switchActive(computerBtn, friendBtn); 41 | }); 42 | 43 | playBtn.addEventListener("click", function(){ 44 | if( !OPPONENT){ 45 | computerBtn.style.backgroundColor = "red"; 46 | friendBtn.style.backgroundColor = "red"; 47 | return; 48 | } 49 | 50 | if( !player.man ){ 51 | oBtn.style.backgroundColor = "red"; 52 | xBtn.style.backgroundColor = "red"; 53 | return; 54 | } 55 | 56 | init(player, OPPONENT); 57 | options.classList.add("hide"); 58 | }); 59 | 60 | function switchActive(off, on){ 61 | off.classList.remove("active"); 62 | on.classList.add("active"); 63 | } -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/options.js: -------------------------------------------------------------------------------- 1 | // SELECT ELEMENTS 2 | const options = document.querySelector(".options"); 3 | const gameOverElement = document.querySelector(".gameover"); 4 | 5 | // SELECT BUTTONS 6 | const computerBtn = options.querySelector(".computer"); 7 | const friendBtn = options.querySelector(".friend"); 8 | const xBtn = options.querySelector(".x"); 9 | const oBtn = options.querySelector(".o"); 10 | const playBtn = options.querySelector(".play"); 11 | 12 | // SOME VARIABLES TO STORE USER'S OPTIONS 13 | let OPPONENT; 14 | const player = new Object; 15 | 16 | // ADD AND EVENT LISTENER TO EVERY BUTTON 17 | computerBtn.addEventListener("click", function(){ 18 | OPPONENT = "computer"; 19 | 20 | switchActive(friendBtn, computerBtn); 21 | }); 22 | 23 | friendBtn.addEventListener("click", function(){ 24 | OPPONENT = "friend"; 25 | 26 | switchActive(computerBtn, friendBtn); 27 | }); 28 | 29 | xBtn.addEventListener("click", function(){ 30 | player.man = "X"; 31 | player.computer = "O"; 32 | player.friend = "O"; 33 | 34 | switchActive(oBtn, xBtn); 35 | }); 36 | 37 | oBtn.addEventListener("click", function(){ 38 | player.man = "O"; 39 | player.computer = "X"; 40 | player.friend = "X"; 41 | 42 | switchActive(xBtn, oBtn); 43 | }); 44 | 45 | playBtn.addEventListener("click", function(){ 46 | // CHECK IF THE USER CHOSE AN OPPONENT 47 | if( !OPPONENT){ 48 | computerBtn.style.backgroundColor = "#f00"; 49 | friendBtn.style.backgroundColor = "#f00"; 50 | 51 | return; 52 | } 53 | 54 | // CHECK IF THE USER CHOSE A SYMBOL 55 | if( !player.man ){ 56 | xBtn.style.backgroundColor = "#f00"; 57 | oBtn.style.backgroundColor = "#f00"; 58 | 59 | return; 60 | } 61 | 62 | // RUN THE GAME 63 | init(player, OPPONENT); 64 | options.classList.add("hide"); 65 | }); 66 | 67 | // SWITCH ACTIVE CLASS BETWEEN TWO ELEMENTS 68 | function switchActive(off, on){ 69 | off.classList.remove("active"); 70 | on.classList.add("active"); 71 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tic-Tac-Toe-JavaScript 2 | Build Tic Tac Toe Game With JavaScript 3 | 4 | Tic-tac-toe for American English, noughts and crosses for British English, or Xs and Os is a paper-and-pencil game for two players, X and O, who take turns filling the spaces in a 3×3 grid (2D Array in JavaScript). The player who succeeds in placing three of their symbols in a horizontal, vertical, or diagonal row is the winner. 5 | 6 | For the tutorial and like always, I'm going to start with the logic part, and after we understand that, then I will open the text editor and try the build the game from scratch. 7 | 8 | This JavaScript Project may seems easy to build, but trust me there a lot of things to learn though. 9 | 10 | Anyone with JavaScript Basics (For loops, variables, functions, Arrays, if statements ... etc) can build this game. 11 | 12 | I will start the tutorial with a preview of the Tic Tac Toe game, and then talk a little bit about the canvas, how to draw on the canvas, and what does the method getContext() do. 13 | Then we will talk about the HTML elements we're going to need for our game. 14 | 15 | For JavaScript, we will need to files options.js and game.js they are self explanatory. 16 | OPTIONS.JS is where the code that handles the player's options lives, like what is the opponent and symbol it has chosen. 17 | GAME.JS is where our game code lives. 18 | 19 | This is Just the first part of tutorial, there still is a second part where we're going to discuss the AI. 20 | You can find the second part here: "Sorry not uploaded yet :(" 21 | 22 | In general in our game.js all what we need to do, is: 23 | 24 | 1. A 1D Array called "gameData" to store the players moves. 25 | 2. Draw the board on the canvas. 26 | 3. add Event listener to the CANVAS. 27 | 4. Determine which SPACE on THE BOARD the player has clicked on. 28 | 5. Update the gameData array. (if the space clicked by the player is empty) 29 | 6. Draw the player's move on the board (canvas). 30 | 7. check if this player wins. if wins we show the game over message. and stop the game. 31 | 8. If it doesn't win, we check for a tie game, if it's a tie we show the game over message. and stop the game. 32 | 9. If there is no winner and it's not a tie game, we give the turn to other player. 33 | 34 | To watch the tutorial on Youtube, follow this link: https://youtu.be/TiozoT6o_8E 35 | 36 | ************************************************************** 37 | 38 | I guess you'll be interested in this tutorials too: 39 | 40 | Create a To Do List App Using JavaScript. 41 | https://www.youtube.com/watch?v=b8sUhU_eq3g 42 | 43 | Ping Pong Game Using JavaScript 44 | https://youtu.be/nl0KXCa5pJk 45 | 46 | Create a Multiple Choice Quiz Using JavaScript 47 | https://youtu.be/49pYIMygIcU 48 | 49 | Tetris Game Using JavaScript 50 | https://youtu.be/HEsAr2Yt2do 51 | 52 | Snake Game Using JavaScript 53 | https://youtu.be/9TcU2C1AACw 54 | 55 | Flappy Bird Game Using JavaScript 56 | https://youtu.be/L07i4g-zhDA 57 | 58 | ************************************************************** 59 | 60 | Social Media 61 | 62 | Facebook: https://web.facebook.com/codeexplainedorg 63 | Twitter: https://twitter.com/code_explained 64 | -------------------------------------------------------------------------------- /TIC TAC TOE - PART 1/style.css: -------------------------------------------------------------------------------- 1 | /* latin */ 2 | @font-face { 3 | font-family: 'Fascinate Inline'; 4 | font-style: normal; 5 | font-weight: 400; 6 | font-display: swap; 7 | src: local('Fascinate Inline'), local('FascinateInline-Regular'), url(font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2) format('woff2'); 8 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 9 | } 10 | 11 | .container{ 12 | width: 450px; 13 | height: 450px; 14 | display: block; 15 | margin: 25px auto; 16 | position: relative; 17 | } 18 | 19 | #cvs{ 20 | position: absolute; 21 | border: 1px solid #000; 22 | } 23 | 24 | .options{ 25 | position: absolute; 26 | width: 450px; 27 | height: 450px; 28 | } 29 | 30 | .options h1{ 31 | text-align: center; 32 | font-size: 65px; 33 | font-family: 'Fascinate Inline', cursive; 34 | color: #f00; 35 | margin: 30px 0 20px 0; 36 | } 37 | 38 | .options h2{ 39 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 40 | text-align: center; 41 | font-weight: bold; 42 | } 43 | 44 | .options div{ 45 | display: inline-block; 46 | } 47 | 48 | .options .computer, .x{ 49 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 50 | padding: 5px; 51 | background-color: #FFF; 52 | color: #000; 53 | font-size: 1.5em; 54 | border-radius: 5px; 55 | margin-left: 70px; 56 | width: 150px; 57 | text-align: center; 58 | cursor: pointer; 59 | border: 1px solid #000; 60 | } 61 | 62 | .options .friend, .o{ 63 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 64 | padding: 5px; 65 | background-color: #FFF; 66 | color: #000; 67 | font-size: 1.5em; 68 | border-radius: 5px; 69 | margin-left: 10px; 70 | width: 150px; 71 | text-align: center; 72 | cursor: pointer; 73 | border: 1px solid #000; 74 | } 75 | 76 | .options .friend:hover, .computer:hover, .x:hover, .o:hover{ 77 | background-color: #011627; 78 | color: #FFF; 79 | } 80 | 81 | .options .play{ 82 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 83 | font-size: 1.5em; 84 | width: 70px; 85 | display: block; 86 | margin: 25px auto; 87 | border-radius: 5px; 88 | border: 1px solid #011627; 89 | text-align: center; 90 | padding: 10px; 91 | background-color: #011627; 92 | color: #FFF; 93 | cursor: pointer; 94 | transition: 100ms width ease-in; 95 | } 96 | .options .play:hover{ 97 | width: 110px; 98 | } 99 | 100 | .active{ 101 | background-color: #011627 !important; 102 | color: #FFF !important; 103 | } 104 | 105 | .hide{ 106 | display: none; 107 | } 108 | 109 | .gameover{ 110 | position: absolute; 111 | width: 450px; 112 | height: 450px; 113 | background-color: rgba(0, 0, 0, 0.95); 114 | } 115 | .gameover h1{ 116 | text-align: center; 117 | font-size: 50px; 118 | font-family: 'Fascinate Inline', cursive; 119 | color: #fff; 120 | margin: 40px 0 20px 0; 121 | } 122 | 123 | .gameover .winner-img{ 124 | display: block; 125 | margin: 20px auto; 126 | } 127 | 128 | .gameover .play{ 129 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 130 | font-size: 1.5em; 131 | width: 150px; 132 | display: block; 133 | margin: 25px auto; 134 | border-radius: 5px; 135 | border: 1px solid #fff; 136 | text-align: center; 137 | padding: 10px; 138 | background-color: #fff; 139 | color: #000; 140 | cursor: pointer; 141 | transition: 100ms width ease-in; 142 | } 143 | .gameover .play:hover{ 144 | width: 200px; 145 | } -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/style.css: -------------------------------------------------------------------------------- 1 | /* latin */ 2 | @font-face { 3 | font-family: 'Fascinate Inline'; 4 | font-style: normal; 5 | font-weight: 400; 6 | font-display: swap; 7 | src: local('Fascinate Inline'), local('FascinateInline-Regular'), url(font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2) format('woff2'); 8 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 9 | } 10 | 11 | .container{ 12 | width: 450px; 13 | height: 450px; 14 | display: block; 15 | margin: 25px auto; 16 | position: relative; 17 | } 18 | 19 | #cvs{ 20 | position: absolute; 21 | border: 1px solid #000; 22 | } 23 | 24 | .options{ 25 | position: absolute; 26 | width: 450px; 27 | height: 450px; 28 | } 29 | 30 | .options h1{ 31 | text-align: center; 32 | font-size: 65px; 33 | font-family: 'Fascinate Inline', cursive; 34 | color: #f00; 35 | margin: 30px 0 20px 0; 36 | } 37 | 38 | .options h2{ 39 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 40 | text-align: center; 41 | font-weight: bold; 42 | } 43 | 44 | .options div{ 45 | display: inline-block; 46 | } 47 | 48 | .options .computer, .x{ 49 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 50 | padding: 5px; 51 | background-color: #FFF; 52 | color: #000; 53 | font-size: 1.5em; 54 | border-radius: 5px; 55 | margin-left: 70px; 56 | width: 150px; 57 | text-align: center; 58 | cursor: pointer; 59 | border: 1px solid #000; 60 | } 61 | 62 | .options .friend, .o{ 63 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 64 | padding: 5px; 65 | background-color: #FFF; 66 | color: #000; 67 | font-size: 1.5em; 68 | border-radius: 5px; 69 | margin-left: 10px; 70 | width: 150px; 71 | text-align: center; 72 | cursor: pointer; 73 | border: 1px solid #000; 74 | } 75 | 76 | .options .friend:hover, .computer:hover, .x:hover, .o:hover{ 77 | background-color: #011627; 78 | color: #FFF; 79 | } 80 | 81 | .options .play{ 82 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 83 | font-size: 1.5em; 84 | width: 70px; 85 | display: block; 86 | margin: 25px auto; 87 | border-radius: 5px; 88 | border: 1px solid #011627; 89 | text-align: center; 90 | padding: 10px; 91 | background-color: #011627; 92 | color: #FFF; 93 | cursor: pointer; 94 | transition: 100ms width ease-in; 95 | } 96 | .options .play:hover{ 97 | width: 110px; 98 | } 99 | 100 | .active{ 101 | background-color: #011627 !important; 102 | color: #FFF !important; 103 | } 104 | 105 | .hide{ 106 | display: none; 107 | } 108 | 109 | .gameover{ 110 | position: absolute; 111 | width: 450px; 112 | height: 450px; 113 | background-color: rgba(0, 0, 0, 0.95); 114 | } 115 | .gameover h1{ 116 | text-align: center; 117 | font-size: 50px; 118 | font-family: 'Fascinate Inline', cursive; 119 | color: #fff; 120 | margin: 40px 0 20px 0; 121 | } 122 | 123 | .gameover .winner-img{ 124 | display: block; 125 | margin: 20px auto; 126 | } 127 | 128 | .gameover .play{ 129 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 130 | width: 150px; 131 | font-size: 0.5em; 132 | display: block; 133 | margin: 25px auto; 134 | border-radius: 5px; 135 | border: 1px solid #fff; 136 | text-align: center; 137 | padding: 10px; 138 | background-color: #fff; 139 | color: #000; 140 | cursor: pointer; 141 | transition: 100ms width ease-in; 142 | } 143 | .gameover .play:hover{ 144 | width: 200px; 145 | } -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/style.css: -------------------------------------------------------------------------------- 1 | /* latin */ 2 | @font-face { 3 | font-family: 'Fascinate Inline'; 4 | font-style: normal; 5 | font-weight: 400; 6 | font-display: swap; 7 | src: local('Fascinate Inline'), local('FascinateInline-Regular'), url(font/jVyR7mzzB3zc-jp6QCAu60poNqIy5grIfA.woff2) format('woff2'); 8 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 9 | } 10 | 11 | .container{ 12 | width: 450px; 13 | height: 450px; 14 | display: block; 15 | margin: 25px auto; 16 | position: relative; 17 | } 18 | 19 | #cvs{ 20 | position: absolute; 21 | border: 1px solid #000; 22 | } 23 | 24 | .options{ 25 | position: absolute; 26 | width: 450px; 27 | height: 450px; 28 | } 29 | 30 | .options h1{ 31 | text-align: center; 32 | font-size: 65px; 33 | font-family: 'Fascinate Inline', cursive; 34 | color: #f00; 35 | margin: 30px 0 20px 0; 36 | } 37 | 38 | .options h2{ 39 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 40 | text-align: center; 41 | font-weight: bold; 42 | } 43 | 44 | .options div{ 45 | display: inline-block; 46 | } 47 | 48 | .options .computer, .x{ 49 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 50 | padding: 5px; 51 | background-color: #FFF; 52 | color: #000; 53 | font-size: 1.5em; 54 | border-radius: 5px; 55 | margin-left: 70px; 56 | width: 150px; 57 | text-align: center; 58 | cursor: pointer; 59 | border: 1px solid #000; 60 | } 61 | 62 | .options .friend, .o{ 63 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 64 | padding: 5px; 65 | background-color: #FFF; 66 | color: #000; 67 | font-size: 1.5em; 68 | border-radius: 5px; 69 | margin-left: 10px; 70 | width: 150px; 71 | text-align: center; 72 | cursor: pointer; 73 | border: 1px solid #000; 74 | } 75 | 76 | .options .friend:hover, .computer:hover, .x:hover, .o:hover{ 77 | background-color: #011627; 78 | color: #FFF; 79 | } 80 | 81 | .options .play{ 82 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 83 | font-size: 1.5em; 84 | width: 70px; 85 | display: block; 86 | margin: 25px auto; 87 | border-radius: 5px; 88 | border: 1px solid #011627; 89 | text-align: center; 90 | padding: 10px; 91 | background-color: #011627; 92 | color: #FFF; 93 | cursor: pointer; 94 | transition: 100ms width ease-in; 95 | } 96 | .options .play:hover{ 97 | width: 110px; 98 | } 99 | 100 | .active{ 101 | background-color: #011627 !important; 102 | color: #FFF !important; 103 | } 104 | 105 | .hide{ 106 | display: none; 107 | } 108 | 109 | .gameover{ 110 | position: absolute; 111 | width: 450px; 112 | height: 450px; 113 | background-color: rgba(0, 0, 0, 0.95); 114 | } 115 | .gameover h1{ 116 | text-align: center; 117 | font-size: 50px; 118 | font-family: 'Fascinate Inline', cursive; 119 | color: #fff; 120 | margin: 40px 0 20px 0; 121 | } 122 | 123 | .gameover .winner-img{ 124 | display: block; 125 | margin: 20px auto; 126 | } 127 | 128 | .gameover .play{ 129 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 130 | font-size: 1.5em; 131 | width: 150px; 132 | display: block; 133 | margin: 25px auto; 134 | border-radius: 5px; 135 | border: 1px solid #fff; 136 | text-align: center; 137 | padding: 10px; 138 | background-color: #fff; 139 | color: #000; 140 | cursor: pointer; 141 | transition: 100ms width ease-in; 142 | } 143 | .gameover .play:hover{ 144 | width: 200px; 145 | } -------------------------------------------------------------------------------- /TIC TAC TOE - PART 2/game.js: -------------------------------------------------------------------------------- 1 | function init(player, OPPONENT){ 2 | // SELECT CANAVS 3 | const canvas = document.getElementById("cvs"); 4 | const ctx = canvas.getContext("2d"); 5 | 6 | // BOARD VARIABLES 7 | let board = []; 8 | const COLUMN = 3; 9 | const ROW = 3; 10 | const SPACE_SIZE = 150; 11 | 12 | // STORE PLAYER'S MOVES 13 | let gameData = new Array(9); 14 | 15 | // By default the first player to play is the human 16 | let currentPlayer = player.man; 17 | 18 | // load X & O images 19 | const xImage = new Image(); 20 | xImage.src = "img/X.png"; 21 | 22 | const oImage = new Image(); 23 | oImage.src = "img/O.png"; 24 | 25 | // Win combinations 26 | const COMBOS = [ 27 | [0, 1, 2], 28 | [3, 4, 5], 29 | [6, 7, 8], 30 | [0, 3, 6], 31 | [1, 4, 7], 32 | [2, 5, 8], 33 | [0, 4, 8], 34 | [2, 4, 6] 35 | ]; 36 | 37 | // FOR GAME OVER CHECK 38 | let GAME_OVER = false; 39 | 40 | // DRAW THE BOARD 41 | function drawBoard(){ 42 | // WE give every space a unique id 43 | // So we know exactly where to put the player's move on the gameData Array 44 | let id = 0 45 | for(let i = 0; i < ROW; i++){ 46 | board[i] = []; 47 | for(let j = 0; j < COLUMN; j++){ 48 | board[i][j] = id; 49 | id++; 50 | 51 | // draw the spaces 52 | ctx.strokeStyle = "#000"; 53 | ctx.strokeRect(j * SPACE_SIZE, i * SPACE_SIZE, SPACE_SIZE, SPACE_SIZE); 54 | } 55 | } 56 | } 57 | drawBoard(); 58 | 59 | // ON PLAYER'S CLICK 60 | canvas.addEventListener("click", function(event){ 61 | 62 | // IF IT's A GAME OVER? EXIT 63 | if(GAME_OVER) return; 64 | 65 | // X & Y position of mouse click relative to the canvas 66 | let X = event.clientX - canvas.getBoundingClientRect().x; 67 | let Y = event.clientY - canvas.getBoundingClientRect().y; 68 | 69 | // WE CALCULATE i & j of the clicked SPACE 70 | let i = Math.floor(Y/SPACE_SIZE); 71 | let j = Math.floor(X/SPACE_SIZE); 72 | 73 | // Get the id of the space the player clicked on 74 | let id = board[i][j]; 75 | 76 | // Prevent the player to play the same space twice 77 | if(gameData[id]) return; 78 | 79 | // store the player's move to gameData 80 | gameData[id] = currentPlayer; 81 | 82 | // draw the move on board 83 | drawOnBoard(currentPlayer, i, j); 84 | 85 | // Check if the play wins 86 | if(isWinner(gameData, currentPlayer)){ 87 | showGameOver(currentPlayer); 88 | GAME_OVER = true; 89 | return; 90 | } 91 | 92 | // check if it's a tie game 93 | if(isTie(gameData)){ 94 | showGameOver("tie"); 95 | GAME_OVER = true; 96 | return; 97 | } 98 | 99 | // GIVE TURN TO THE OTHER PLAYER 100 | currentPlayer = currentPlayer == player.man ? player.friend : player.man; 101 | }); 102 | 103 | // check for a winner 104 | function isWinner(gameData, player){ 105 | for(let i = 0; i < COMBOS.length; i++){ 106 | let won = true; 107 | 108 | for(let j = 0; j < COMBOS[i].length; j++){ 109 | let id = COMBOS[i][j]; 110 | won = gameData[id] == player && won; 111 | } 112 | 113 | if(won){ 114 | return true; 115 | } 116 | } 117 | return false; 118 | } 119 | 120 | // Check for a tie game 121 | function isTie(gameData){ 122 | let isBoardFill = true; 123 | for(let i = 0; i < gameData.length; i++){ 124 | isBoardFill = gameData[i] && isBoardFill; 125 | } 126 | if(isBoardFill){ 127 | return true; 128 | } 129 | return false; 130 | } 131 | 132 | // SHOW GAME OVER 133 | function showGameOver(player){ 134 | let message = player == "tie" ? "Oops No Winner" : "The Winner is"; 135 | let imgSrc = `img/${player}.png`; 136 | 137 | gameOverElement.innerHTML = ` 138 |

${message} 139 | 140 |
Play Again!
141 | `; 142 | 143 | gameOverElement.classList.remove("hide"); 144 | } 145 | 146 | // draw on board 147 | function drawOnBoard(player, i, j){ 148 | let img = player == "X" ? xImage : oImage; 149 | 150 | // the x,y positon of the image are the x,y of the clicked space 151 | ctx.drawImage(img, j * SPACE_SIZE, i * SPACE_SIZE); 152 | } 153 | } -------------------------------------------------------------------------------- /TIC TAC TOE - FINAL CODE/game.js: -------------------------------------------------------------------------------- 1 | function init(player, OPPONENT){ 2 | // SELECT CANAVS 3 | const canvas = document.getElementById("cvs"); 4 | const ctx = canvas.getContext("2d"); 5 | 6 | // BOARD VARIABLES 7 | let board = []; 8 | const COLUMN = 3; 9 | const ROW = 3; 10 | const SPACE_SIZE = 150; 11 | 12 | // STORE PLAYER'S MOVES 13 | let gameData = new Array(9); 14 | 15 | // By default the first player to play is the human 16 | let currentPlayer = player.man; 17 | 18 | // load X & O images 19 | const xImage = new Image(); 20 | xImage.src = "img/X.png"; 21 | 22 | const oImage = new Image(); 23 | oImage.src = "img/O.png"; 24 | 25 | // Win combinations 26 | const COMBOS = [ 27 | [0, 1, 2], 28 | [3, 4, 5], 29 | [6, 7, 8], 30 | [0, 3, 6], 31 | [1, 4, 7], 32 | [2, 5, 8], 33 | [0, 4, 8], 34 | [2, 4, 6] 35 | ]; 36 | 37 | // FOR GAME OVER CHECK 38 | let GAME_OVER = false; 39 | 40 | // DRAW THE BOARD 41 | function drawBoard(){ 42 | // WE give every space a unique id 43 | // So we know exactly where to put the player's move on the gameData Array 44 | let id = 0 45 | for(let i = 0; i < ROW; i++){ 46 | board[i] = []; 47 | for(let j = 0; j < COLUMN; j++){ 48 | board[i][j] = id; 49 | id++; 50 | 51 | // draw the spaces 52 | ctx.strokeStyle = "#000"; 53 | ctx.strokeRect(j * SPACE_SIZE, i * SPACE_SIZE, SPACE_SIZE, SPACE_SIZE); 54 | } 55 | } 56 | } 57 | drawBoard(); 58 | 59 | // ON PLAYER'S CLICK 60 | canvas.addEventListener("click", function(event){ 61 | 62 | // IF IT's A GAME OVER? EXIT 63 | if(GAME_OVER) return; 64 | 65 | // X & Y position of mouse click relative to the canvas 66 | let X = event.clientX - canvas.getBoundingClientRect().x; 67 | let Y = event.clientY - canvas.getBoundingClientRect().y; 68 | 69 | // WE CALCULATE i & j of the clicked SPACE 70 | let i = Math.floor(Y/SPACE_SIZE); 71 | let j = Math.floor(X/SPACE_SIZE); 72 | 73 | // Get the id of the space the player clicked on 74 | let id = board[i][j]; 75 | 76 | // Prevent the player to play the same space twice 77 | if(gameData[id]) return; 78 | 79 | // store the player's move to gameData 80 | gameData[id] = currentPlayer; 81 | 82 | // draw the move on board 83 | drawOnBoard(currentPlayer, i, j); 84 | 85 | // Check if the play wins 86 | if(isWinner(gameData, currentPlayer)){ 87 | showGameOver(currentPlayer); 88 | GAME_OVER = true; 89 | return; 90 | } 91 | 92 | // check if it's a tie game 93 | if(isTie(gameData)){ 94 | showGameOver("tie"); 95 | GAME_OVER = true; 96 | return; 97 | } 98 | 99 | if( OPPONENT == "computer"){ 100 | // get id of space using minimax algorithm 101 | let id = minimax( gameData, player.computer ).id; 102 | 103 | // store the player's move to gameData 104 | gameData[id] = player.computer; 105 | 106 | // get i and j of space 107 | let space = getIJ(id); 108 | 109 | // draw the move on board 110 | drawOnBoard(player.computer, space.i, space.j); 111 | 112 | // Check if the play wins 113 | if(isWinner(gameData, player.computer)){ 114 | showGameOver(player.computer); 115 | GAME_OVER = true; 116 | return; 117 | } 118 | 119 | // check if it's a tie game 120 | if(isTie(gameData)){ 121 | showGameOver("tie"); 122 | GAME_OVER = true; 123 | return; 124 | } 125 | }else{ 126 | // GIVE TURN TO THE OTHER PLAYER 127 | currentPlayer = currentPlayer == player.man ? player.friend : player.man; 128 | } 129 | 130 | }); 131 | 132 | // MINIMAX 133 | function minimax(gameData, PLAYER){ 134 | // BASE 135 | if( isWinner(gameData, player.computer) ) return { evaluation : +10 }; 136 | if( isWinner(gameData, player.man) ) return { evaluation : -10 }; 137 | if( isTie(gameData) ) return { evaluation : 0 }; 138 | 139 | // LOOK FOR EMTY SPACES 140 | let EMPTY_SPACES = getEmptySpaces(gameData); 141 | 142 | // SAVE ALL MOVES AND THEIR EVALUATIONS 143 | let moves = []; 144 | 145 | // LOOP OVER THE EMPTY SPACES TO EVALUATE THEM 146 | for( let i = 0; i < EMPTY_SPACES.length; i++){ 147 | // GET THE ID OF THE EMPTY SPACE 148 | let id = EMPTY_SPACES[i]; 149 | 150 | // BACK UP THE SPACE 151 | let backup = gameData[id]; 152 | 153 | // MAKE THE MOVE FOR THE PLAYER 154 | gameData[id] = PLAYER; 155 | 156 | // SAVE THE MOVE'S ID AND EVALUATION 157 | let move = {}; 158 | move.id = id; 159 | // THE MOVE EVALUATION 160 | if( PLAYER == player.computer){ 161 | move.evaluation = minimax(gameData, player.man).evaluation; 162 | }else{ 163 | move.evaluation = minimax(gameData, player.computer).evaluation; 164 | } 165 | 166 | // RESTORE SPACE 167 | gameData[id] = backup; 168 | 169 | // SAVE MOVE TO MOVES ARRAY 170 | moves.push(move); 171 | } 172 | 173 | // MINIMAX ALGORITHM 174 | let bestMove; 175 | 176 | if(PLAYER == player.computer){ 177 | // MAXIMIZER 178 | let bestEvaluation = -Infinity; 179 | for(let i = 0; i < moves.length; i++){ 180 | if( moves[i].evaluation > bestEvaluation ){ 181 | bestEvaluation = moves[i].evaluation; 182 | bestMove = moves[i]; 183 | } 184 | } 185 | }else{ 186 | // MINIMIZER 187 | let bestEvaluation = +Infinity; 188 | for(let i = 0; i < moves.length; i++){ 189 | if( moves[i].evaluation < bestEvaluation ){ 190 | bestEvaluation = moves[i].evaluation; 191 | bestMove = moves[i]; 192 | } 193 | } 194 | } 195 | 196 | return bestMove; 197 | } 198 | 199 | // GET EMPTY SPACES 200 | function getEmptySpaces(gameData){ 201 | let EMPTY = []; 202 | 203 | for( let id = 0; id < gameData.length; id++){ 204 | if(!gameData[id]) EMPTY.push(id); 205 | } 206 | 207 | return EMPTY; 208 | } 209 | 210 | // GET i AND j of a SPACE 211 | function getIJ(id){ 212 | for(let i = 0; i < board.length; i++){ 213 | for(let j = 0; j < board[i].length; j++){ 214 | if(board[i][j] == id) return { i : i, j : j} 215 | } 216 | } 217 | } 218 | 219 | // check for a winner 220 | function isWinner(gameData, player){ 221 | for(let i = 0; i < COMBOS.length; i++){ 222 | let won = true; 223 | 224 | for(let j = 0; j < COMBOS[i].length; j++){ 225 | let id = COMBOS[i][j]; 226 | won = gameData[id] == player && won; 227 | } 228 | 229 | if(won){ 230 | return true; 231 | } 232 | } 233 | return false; 234 | } 235 | 236 | // Check for a tie game 237 | function isTie(gameData){ 238 | let isBoardFill = true; 239 | for(let i = 0; i < gameData.length; i++){ 240 | isBoardFill = gameData[i] && isBoardFill; 241 | } 242 | if(isBoardFill){ 243 | return true; 244 | } 245 | return false; 246 | } 247 | 248 | // SHOW GAME OVER 249 | function showGameOver(player){ 250 | let message = player == "tie" ? "Oops No Winner" : "The Winner is"; 251 | let imgSrc = `img/${player}.png`; 252 | 253 | gameOverElement.innerHTML = ` 254 |

${message} 255 | 256 |
Play Again!
257 | `; 258 | 259 | gameOverElement.classList.remove("hide"); 260 | } 261 | 262 | // draw on board 263 | function drawOnBoard(player, i, j){ 264 | let img = player == "X" ? xImage : oImage; 265 | 266 | // the x,y positon of the image are the x,y of the clicked space 267 | ctx.drawImage(img, j * SPACE_SIZE, i * SPACE_SIZE); 268 | } 269 | } 270 | --------------------------------------------------------------------------------