diff --git a/package.json b/package.json index 3a7852f0..4664ea65 100644 --- a/package.json +++ b/package.json @@ -10,14 +10,12 @@ "react-dom": "^17.0.1", "react-scripts": "4.0.3" }, - "homepage": "http://adagold.github.io/react-tic-tac-toe", + "homepage": "https://weishan-tic-tac-toe.herokuapp.com/", "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject", - "predeploy": "npm run build", - "deploy": "gh-pages -d build" + "eject": "react-scripts eject" }, "eslintConfig": { "extends": "react-app" diff --git a/src/App.js b/src/App.js index 6005602b..27e3cb8e 100644 --- a/src/App.js +++ b/src/App.js @@ -3,8 +3,8 @@ import './App.css'; 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 = []; @@ -30,39 +30,76 @@ const App = () => { // This starts state off as a 2D array of JS objects with // empty value and unique ids. const [squares, setSquares] = useState(generateSquares()); + const [winner, setWinner] = useState(''); + const [activePlayer, switchActivePlayer] = useState(PLAYER_1); + const [usedSquare, updateUsedSquare] = useState(0); // 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 + const updateBoard = (id) => { + const newBoard = [].concat(...squares); + if (winner) return + for (let square of newBoard) { + if (square.id === id){ + if (square.value !== '') return + square.value = activePlayer + if (activePlayer === 'x') { + switchActivePlayer('o') + } else {switchActivePlayer('x')} + } + } + updateUsedSquare(usedSquare + 1); + setSquares(squares) + setWinner(checkForWinner()) + } const checkForWinner = () => { - // Complete in Wave 3 - // You will need to: - // 1. Go accross each row to see if - // 3 squares in the same row match - // i.e. same value - // 2. Go down each column to see if - // 3 squares in each column match - // 3. Go across each diagonal to see if - // all three squares have the same value. + if (checkBoard('x')) { + return 'x' + } else if (checkBoard('o')) { + return 'o' + } else { + return '' + } + } + const checkBoard = (player) => { + let i = 0; + while (i < 3) { + if (squares[i][0].value === squares[i][1].value && squares[i][1].value === squares[i][2].value && squares[i][0].value === player) { + return true + } else if (squares[0][i].value === squares[1][i].value && squares[1][i].value === squares[2][i].value && squares[2][i].value === squares[0][i].value && squares[0][i].value === player) { + return true + } + i += 1 + } + if (squares[0][0].value === squares[1][1].value && squares[1][1].value === squares[2][2].value && squares[2][2].value === squares[0][0].value && squares[0][0].value === player) { + return true; + } else if (squares[0][2].value === squares[1][1].value && squares[1][1].value === squares[2][0].value && squares[2][0].value === squares[0][2].value && squares[0][2].value === player) { + return true; + }; + return false; } const resetGame = () => { - // Complete in Wave 4 + setSquares(generateSquares()) + setWinner('') + updateUsedSquare(0) } return (

React Tic Tac Toe

-

The winner is ... -- Fill in for wave 3

- +

{winner === '' ? `Current player is ${activePlayer}` : `Winner is ${winner}`}

+

{(winner === '' && usedSquare === 9) ? `It is a tie!` : `🥰 🥰 🥰 🥰 🥰 🥰`}

+
- +
); diff --git a/src/App.test.js b/src/App.test.js index cc4c4490..b0686705 100644 --- a/src/App.test.js +++ b/src/App.test.js @@ -14,7 +14,7 @@ describe('App', () => { expect(buttons[buttonIndex].innerHTML).toEqual(expectedResult); } - describe.skip('Wave 2: clicking on squares and rendering App', () => { + describe('Wave 2: clicking on squares and rendering App', () => { test('App renders with a board of 9 empty buttons', () => { // Arrange-Act - Render the app @@ -85,7 +85,7 @@ describe('App', () => { }); - describe.skip('Wave 3: Winner tests', () => { + describe('Wave 3: Winner tests', () => { describe('Prints "Winner is x" when x wins', () => { test('that a winner will be identified when 3 Xs get in a row across the top', () => { // Arrange @@ -364,7 +364,7 @@ describe('App', () => { }); }); - describe.skip('Wave 4: reset game button', () => { + describe('Wave 4: reset game button', () => { test('App has a "Reset Game" button', () => { // Arrange-Act render(); diff --git a/src/components/Board.js b/src/components/Board.js index 3add7e88..4928a4f7 100644 --- a/src/components/Board.js +++ b/src/components/Board.js @@ -9,15 +9,19 @@ const generateSquareComponents = (squares, onClickCallback) => { // squares is a 2D Array, but // you need to return a 1D array // of square components - + const squaresArray = [].concat(...squares); + const newSquares = [] + for (const square of squaresArray) { + newSquares.push() + } + return newSquares } const Board = ({ squares, onClickCallback }) => { - const squareList = generateSquareComponents(squares, onClickCallback); - console.log(squareList); - return
+ const squareList = generateSquareComponents(squares, onClickCallback); + return
{squareList} -
+
} Board.propTypes = { diff --git a/src/components/Board.test.js b/src/components/Board.test.js index 93571b2d..5a06bf8f 100644 --- a/src/components/Board.test.js +++ b/src/components/Board.test.js @@ -84,7 +84,7 @@ describe('Wave 1: Board', () => { }); describe('Wave 2: Board', () => { describe('button click callbacks', () => { - test.skip('that the callback is called for the 1st button', () => { + test('that the callback is called for the 1st button', () => { // Arrange const callback = jest.fn(); const { container } = render(); @@ -97,7 +97,7 @@ describe('Wave 2: Board', () => { expect(callback).toHaveBeenCalled(); }); - test.skip('that the callback is called for the last button', () => { + test('that the callback is called for the last button', () => { // Arrange const callback = jest.fn(); const { container } = render(); diff --git a/src/components/Square.js b/src/components/Square.js index d0ebce48..2a881ed0 100644 --- a/src/components/Square.js +++ b/src/components/Square.js @@ -4,15 +4,16 @@ import PropTypes from 'prop-types'; import './Square.css' const Square = (props) => { + const squareClick = () => { + props.onClickCallback(props.id); + }; // For Wave 1 enable this // Component to alert a parent // component when it's clicked on. - return + return } Square.propTypes = { diff --git a/src/components/Square.test.js b/src/components/Square.test.js index 0945c3fd..1e507528 100644 --- a/src/components/Square.test.js +++ b/src/components/Square.test.js @@ -23,7 +23,7 @@ describe('Wave 1: Square', () => { }); describe('Wave 2: Square', () => { - test.skip('when clicked on it calls the callback function', async () => { + test('when clicked on it calls the callback function', async () => { const callback = jest.fn(); render();