Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 96 additions & 22 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { useState } from 'react';
import './App.css';
import React, { useState } from "react";
import "./App.css";

import Board from './components/Board';
import Board from "./components/Board";

const PLAYER_1 = 'X';
const PLAYER_2 = 'O';
const PLAYER_1 = "X";
const PLAYER_2 = "O";

const generateSquares = () => {
const squares = [];
Expand All @@ -16,46 +16,120 @@ const generateSquares = () => {
for (let col = 0; col < 3; col += 1) {
squares[row].push({
id: currentId,
value: '',
value: "",
});
currentId += 1;
}
}

return squares;
}
};

const App = () => {

const [player, setPlayer] = useState("player_1");
const [squares, setSquares] = useState(generateSquares());
const [winner, setWinner] = useState(null);

// Wave 2
// You will need to create a method to change the square
// When it is clicked on.
// Then pass it into the squares as a callback
// wave 2
// changes the square when it is clicked on.
// Then pass it into the squares as a callback
const onClickCallback = (squareId) => {
console.log('clicked');
console.log (winner);
if (winner !== null) {
return;
}
console.log("no winner");

let gameValue = "";
if (player === "player_1") {
gameValue = PLAYER_1;
} else if (player === "player_2") {
gameValue = PLAYER_2;
}

const checkForWinner = () => {
// Complete in Wave 3
const newSquares = [];
squares.forEach((row) => {
const newRow = [];
row.forEach((square) => {
if (square.id === squareId) {
//updates the square
const newSquare = {
id: square.id,
value: gameValue,
};
newRow.push(newSquare);
} else {
newRow.push(square);
}
});
newSquares.push(newRow);
});

}
checkForWinner(newSquares);
setSquares(newSquares);

let nextPlayer = "";
if (player === "player_1") {
nextPlayer = "player_2";
} else if (player === "player_2") {
nextPlayer = "player_1";
}
setPlayer(nextPlayer);
};

// wave 3
const checkForWinner = (squares) => {
const winningRows = [

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clever!

[squares[0][0], squares[0][1], squares[0][2]],
[squares[1][0], squares[1][1], squares[1][2]],
[squares[2][0], squares[2][1], squares[2][2]],
[squares[0][0], squares[1][0], squares[2][0]],
[squares[0][1], squares[1][1], squares[2][1]],
[squares[0][2], squares[1][2], squares[2][2]],
[squares[0][0], squares[1][1], squares[2][2]],
[squares[0][2], squares[1][1], squares[2][0]],
];

for (let i = 0; i < winningRows.length; i++) {
const [a, b, c] = winningRows[i];
console.log(a.value);
if (a.value && a.value === b.value && a.value === c.value) {
//return a.value;
if (a.value === PLAYER_1) {
setWinner("player_1");

} else if (a.value === PLAYER_2) {
setWinner("Player_2");
// if (a.value === "o") setWinner("Player_2");
}
}
} // otherwise
return null;
};

// wave 4
const resetGame = () => {
// Complete in Wave 4
}
setPlayer("player_1");
setSquares(generateSquares());
setWinner(null);
};

return (
<div className="App">
<header className="App-header">
<h1>React Tic Tac Toe</h1>
<h2>The winner is ... -- Fill in for wave 3 </h2>
<button>Reset Game</button>
<h2>The winner is {winner} </h2>
<button onClick={resetGame}>Reset Game</button>
</header>
<main>
<Board squares={squares} />
<Board
squares={squares}
onClickCallback={onClickCallback}
player={player}
/>
</main>
</div>
);
}
};

export default App;
27 changes: 21 additions & 6 deletions src/components/Board.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,28 @@ import Square from './Square';
import PropTypes from 'prop-types';


const generateSquareComponents = (squares, onClickCallback) => {
// Complete this for Wave 1
const generateSquareComponents = (squares, onClickCallback, player) => {

const squareComponents = squares.map((row) => {
return row.map(({id, value}) => {
return (
<Square
id={id}
value={value}
onClickCallback={onClickCallback}
player={player}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a big issue but I wanted to point out that player is being passed as a prop but isn't ever used by the Square component. Its good practice to remove any props that you end up not using (with the exception of key).
This is similar to the advice we'd give about arguments in functions.

key={id}
/>

);
});
});
return squareComponents;
}

const Board = ({ squares, onClickCallback }) => {
const squareList = generateSquareComponents(squares, onClickCallback);
console.log(squareList);
const Board = ({ squares, onClickCallback, player }) => {
const squareList = generateSquareComponents(squares, onClickCallback, player);

return <div className="grid" >
{squareList}
</div>
Expand All @@ -22,11 +36,12 @@ Board.propTypes = {
PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number.isRequired,
value: PropTypes.string.isRequired
value: PropTypes.string.isRequired,
})
)
),
onClickCallback: PropTypes.func.isRequired,
player: PropTypes.string.isRequired
};

export default Board;
2 changes: 2 additions & 0 deletions src/components/Square.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ const Square = (props) => {
// For Wave 1 enable this
// Component to alert a parent
// component when it's clicked on.


return <button
className="square"
onClick={() => props.onClickCallback(props.id)}
>
{props.value}
</button>
Expand Down