My first JS program - Tic Tac Toe game
up vote
2
down vote
favorite
I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.
The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...
So overall, how is this coded? is there a better way to code this?
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
javascript beginner css
New contributor
add a comment |
up vote
2
down vote
favorite
I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.
The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...
So overall, how is this coded? is there a better way to code this?
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
javascript beginner css
New contributor
add a comment |
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.
The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...
So overall, how is this coded? is there a better way to code this?
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
javascript beginner css
New contributor
I just completed some beginner web-dev courses (cs:50 and such) and wanted to try my skills.
The CSS centering - ugh I just gave up on that, I wanted to make it responsive and the letters centered perfectly, but whatever...
So overall, how is this coded? is there a better way to code this?
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
let turn = true;
let children;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
children = document.getElementsByClassName("child");
for (let i = 0; i < children.length; i++) {
children[i].addEventListener("click", function () {
clicked(i);
});
}
document.getElementById("clear").addEventListener("click", function () {
clearBoard();
}
);
updateTurn();
}
function clearBoard() {
for (let i = 0; i < children.length; i++) {
children[i].innerHTML = '';
children[i].classList.remove('animate');
}
turn = true;
winnerFound = false;
updateTurn();
}
//text at the top
function updateTurn() {
if (turn)
document.getElementById("turn").innerHTML = "X";
else
document.getElementById("turn").innerHTML = "O";
}
function clicked(i) {
if (winnerFound)
return;
if (children[i].childElementCount !== 0)
return;
const div = document.createElement('div');
if (turn) {
div.textContent = 'X';
}
else {
div.textContent = 'O';
}
children[i].appendChild(div);
children[i].classList.add('animate');
turn = !turn;
checkWinner();
updateTurn();
}
function checkWinner() {
//check rows
for (let x = 0; x < 9; x += 3) {
if (childContent(x) === childContent(x + 1) && childContent(x) === childContent(x + 2)) {
alert(childContent(x) + " won!");
winnerFound = true;
}
}
//check columns
for (let x = 0; x < 3; x += 1) {
if (childContent(x) === childContent(x + 3) && childContent(x) === childContent(x + 6)) {
alert(childContent(x)+ " won!");
winnerFound = true;
}
}
//check diagonals
if (childContent(0) === childContent(4) && childContent(0) === childContent(8)) {
alert(childContent(0)+ " won!");
winnerFound = true;
}
if (childContent(2) === childContent(4) && childContent(2) === childContent(6)) {
alert(childContent(2)+ " won!");
winnerFound = true;
}
}
function childContent(i) {
if (children[i].childElementCount === 0) {
return i;
}
return children[i].getElementsByTagName('div')[0].innerHTML;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.child:hover {
background-color: darkgrey;
}
.parent {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.child {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.animate {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turn"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
javascript beginner css
javascript beginner css
New contributor
New contributor
New contributor
asked 11 hours ago
John Mc
111
111
New contributor
New contributor
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
Review
Not bad for a beginner and welcome to the world of programing.
As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.
Naming
- Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.
- Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).
- Good naming does not name what something is, but what it represents in the current context of the code.
- Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)
Some specific name examples.
You have the variable children
. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?
, you know what that means, as opposed to What are the children in a game of Tic Tac Toe?
whaa! I have renamed children
to positions
You have done the same in the CSS and markup. The classes .child
, .parent
.animate
have no connection to the abstraction of Tic Tac Toe. Better name may be .child
is .position
, .parent
is .board
, .animate
is .playerMoved
Most of the function names are good with the exception of childContent
and clicked
. Better names could be childContent
as getPositonContent
(as you use this function a lot in checkWinner
a better name is getPos
so that the code is not cluttered with a long name) and clicked
as playerMove
Refactoring your code.
The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.
turnDisplay
created in load so you dont have to query the DOM each time.
playerMove
gets the position element rather than the index.- The listener for clear is passed the function directly rather than use the indirect call
addEventListener("click", function() { clearBoard() })
- Changed some
innerHTML
references totextContent
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
Review
Not bad for a beginner and welcome to the world of programing.
As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.
Naming
- Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.
- Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).
- Good naming does not name what something is, but what it represents in the current context of the code.
- Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)
Some specific name examples.
You have the variable children
. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?
, you know what that means, as opposed to What are the children in a game of Tic Tac Toe?
whaa! I have renamed children
to positions
You have done the same in the CSS and markup. The classes .child
, .parent
.animate
have no connection to the abstraction of Tic Tac Toe. Better name may be .child
is .position
, .parent
is .board
, .animate
is .playerMoved
Most of the function names are good with the exception of childContent
and clicked
. Better names could be childContent
as getPositonContent
(as you use this function a lot in checkWinner
a better name is getPos
so that the code is not cluttered with a long name) and clicked
as playerMove
Refactoring your code.
The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.
turnDisplay
created in load so you dont have to query the DOM each time.
playerMove
gets the position element rather than the index.- The listener for clear is passed the function directly rather than use the indirect call
addEventListener("click", function() { clearBoard() })
- Changed some
innerHTML
references totextContent
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.
add a comment |
up vote
0
down vote
Review
Not bad for a beginner and welcome to the world of programing.
As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.
Naming
- Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.
- Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).
- Good naming does not name what something is, but what it represents in the current context of the code.
- Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)
Some specific name examples.
You have the variable children
. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?
, you know what that means, as opposed to What are the children in a game of Tic Tac Toe?
whaa! I have renamed children
to positions
You have done the same in the CSS and markup. The classes .child
, .parent
.animate
have no connection to the abstraction of Tic Tac Toe. Better name may be .child
is .position
, .parent
is .board
, .animate
is .playerMoved
Most of the function names are good with the exception of childContent
and clicked
. Better names could be childContent
as getPositonContent
(as you use this function a lot in checkWinner
a better name is getPos
so that the code is not cluttered with a long name) and clicked
as playerMove
Refactoring your code.
The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.
turnDisplay
created in load so you dont have to query the DOM each time.
playerMove
gets the position element rather than the index.- The listener for clear is passed the function directly rather than use the indirect call
addEventListener("click", function() { clearBoard() })
- Changed some
innerHTML
references totextContent
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.
add a comment |
up vote
0
down vote
up vote
0
down vote
Review
Not bad for a beginner and welcome to the world of programing.
As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.
Naming
- Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.
- Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).
- Good naming does not name what something is, but what it represents in the current context of the code.
- Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)
Some specific name examples.
You have the variable children
. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?
, you know what that means, as opposed to What are the children in a game of Tic Tac Toe?
whaa! I have renamed children
to positions
You have done the same in the CSS and markup. The classes .child
, .parent
.animate
have no connection to the abstraction of Tic Tac Toe. Better name may be .child
is .position
, .parent
is .board
, .animate
is .playerMoved
Most of the function names are good with the exception of childContent
and clicked
. Better names could be childContent
as getPositonContent
(as you use this function a lot in checkWinner
a better name is getPos
so that the code is not cluttered with a long name) and clicked
as playerMove
Refactoring your code.
The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.
turnDisplay
created in load so you dont have to query the DOM each time.
playerMove
gets the position element rather than the index.- The listener for clear is passed the function directly rather than use the indirect call
addEventListener("click", function() { clearBoard() })
- Changed some
innerHTML
references totextContent
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.
Review
Not bad for a beginner and welcome to the world of programing.
As you are new to coding I will just focus on one aspect of your code. The naming (which is very poor). There are many other things that I had to resist changing, but did not want to overwhelm you with the technicalities of client side Javascript, CSS, DOM, and markup.
Naming
- Naming is very important, it gives meaning to code, data, and how it relates to the abstract concepts that make up a project. Bad naming will result in hard to read code, ambiguity and bugs.
- Good naming is not easy and takes time to learn by experience and example. (Read other peoples code and pay attention to how they name things).
- Good naming does not name what something is, but what it represents in the current context of the code.
- Good naming means you don't have to fill your code with comments to explain what can not be deduced from the code. Though you have done well in your comments :)
Some specific name examples.
You have the variable children
. Yes it is a list of children, that can be worked out by looking at how you declare its content, but in a bigger project there will be many children. The name does not represent what abstractly it holds, and that is board positions. If I ask What are the positions in a game of Tic Tac Toe?
, you know what that means, as opposed to What are the children in a game of Tic Tac Toe?
whaa! I have renamed children
to positions
You have done the same in the CSS and markup. The classes .child
, .parent
.animate
have no connection to the abstraction of Tic Tac Toe. Better name may be .child
is .position
, .parent
is .board
, .animate
is .playerMoved
Most of the function names are good with the exception of childContent
and clicked
. Better names could be childContent
as getPositonContent
(as you use this function a lot in checkWinner
a better name is getPos
so that the code is not cluttered with a long name) and clicked
as playerMove
Refactoring your code.
The rewrite is mostly just renaming the many poor names you used. There are also a few minor code changes. BTW the names I picked may not be what you would have used to represent the various abstracts, they are just examples.
turnDisplay
created in load so you dont have to query the DOM each time.
playerMove
gets the position element rather than the index.- The listener for clear is passed the function directly rather than use the indirect call
addEventListener("click", function() { clearBoard() })
- Changed some
innerHTML
references totextContent
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
Note: the above example is just concerned with naming, and does not represent an ideal code example. The idea was to keep as close to the OP's original code as possible.
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
let turn = true;
let positions, turnDisplay;
let winnerFound = false;
document.addEventListener('DOMContentLoaded', load);
function load() {
positions = document.getElementsByClassName("position");
turnDisplay = document.getElementById("turnDisplay");
for (let i = 0; i < positions.length; i++) {
positions[i].addEventListener("click", function() {
playerMove(positions[i])
});
}
document.getElementById("clear").addEventListener("click", clearBoard);
displayTurn();
}
function clearBoard() {
for (let i = 0; i < positions.length; i++) {
positions[i].innerHTML = '';
positions[i].classList.remove('playerMoved');
}
turn = true;
winnerFound = false;
displayTurn();
}
function displayTurn() {
if (turn) {
turnDisplay.textContent = "X";
} else {
turnDisplay.textContent = "O";
}
}
function playerMove(position) {
if (winnerFound) {
return
}
if (position.childElementCount !== 0) {
return
}
const mark = document.createElement('div');
if (turn) {
mark.textContent = 'X'
} else {
mark.textContent = 'O'
}
position.appendChild(mark);
position.classList.add('playerMoved');
turn = !turn;
checkWinner();
displayTurn();
}
function checkWinner() {
for (let x = 0; x < 9; x += 3) {
if (getPos(x) === getPos(x + 1) && getPos(x) === getPos(x + 2)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
for (let x = 0; x < 3; x += 1) {
if (getPos(x) === getPos(x + 3) && getPos(x) === getPos(x + 6)) {
alert(getPos(x) + " won!");
winnerFound = true;
}
}
if (getPos(0) === getPos(4) && getPos(0) === getPos(8)) {
alert(getPos(0) + " won!");
winnerFound = true;
}
if (getPos(2) === getPos(4) && getPos(2) === getPos(6)) {
alert(getPos(2) + " won!");
winnerFound = true;
}
}
function getPos(index) {
if (positions[index].childElementCount === 0) {
return index
}
return positions[index].textContent;
}
body {
background: lightgray;
text-align: center;
vertical-align: middle;
}
.position:hover {
background-color: darkgrey;
}
.board {
display: inline-flex;
flex-wrap: wrap;
width: 400px;
}
.position {
flex: 1 0 calc(33% - 10px);
margin: 5px;
height: 80px;
background-color: grey;
}
.playerMoved {
animation: changeColor 0.5s forwards;
}
@keyframes changeColor {
0% {
background-color: darkgrey;
}
100% {
background-color: khaki;
font-size: 60px;
}
}
<div>
<h1>Tic Tac Toe</h1>
<h2>It is now the turn of: <span id="turnDisplay"></span></h2>
<button id="clear">CLEAR</button>
</div>
<div class="board">
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
<div class="position"></div>
</div>
answered 3 hours ago
Blindman67
6,4041521
6,4041521
add a comment |
add a comment |
John Mc is a new contributor. Be nice, and check out our Code of Conduct.
John Mc is a new contributor. Be nice, and check out our Code of Conduct.
John Mc is a new contributor. Be nice, and check out our Code of Conduct.
John Mc is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f207842%2fmy-first-js-program-tic-tac-toe-game%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown