├── 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 |
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}1>
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}1>
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 |
--------------------------------------------------------------------------------