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
73 changes: 51 additions & 22 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';
import './App.css';

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

const PLAYER_1 = 'X';
const PLAYER_2 = 'O';
Comment on lines 7 to 8

Choose a reason for hiding this comment

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

It seems like you aren't using these 2 variables anywhere in your project. You could probably leave them out?

Expand All @@ -27,42 +28,70 @@ const generateSquares = () => {

const App = () => {

// This starts state off as a 2D array of JS objects with
// empty value and unique ids.
const [squares, setSquares] = useState(generateSquares());

// 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 [currentPlayerX, setCurrentPlayerX] = useState(true);

Choose a reason for hiding this comment

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

Good use of state to keep track of the current player.


const updateGameState = (id) => {

const game = squares.map((row) => {
return row.map((square) => {
if(id === square.id) {
if(square.value === '' && !checkForWinner(squares)){
if(currentPlayerX){
square.value = 'x';
} else{
square.value = 'o';
}
setCurrentPlayerX(!currentPlayerX);
}
}
return square;
} );

});
setSquares(game);
};

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.

const checkForWinner = (squares) => {
// diagonals
if(squares[0][0].value && squares[0][0].value===squares[1][1].value && squares[0][0].value===squares[2][2].value){
return squares[0][0].value;

}
if(squares[0][2].value && squares[0][2].value===squares[1][1].value && squares[0][2].value===squares[2][0].value){
return squares[0][2].value;
}
// vertical
for(let i=0; i<3; i+=1){
if(squares[0][i].value && squares[0][i].value===squares[1][i].value && squares[0][i].value===squares[2][i].value){
return squares[0][i].value;
}
}
//horizontal
for(let i of squares) {
if(i[0].value && i[0].value===i[1].value && i[0].value===i[2].value){
return i[0].value;
}
}
return null;
}

Choose a reason for hiding this comment

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

There's something in the game logic here that is failing a test. Remind me to go over that with you during our next 1:1.

Choose a reason for hiding this comment

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

You're not checking for empty values in any of these combinations so I wonder if that's what is making one of the tests fail.


const resetGame = () => {
// Complete in Wave 4
}

return (
<div className="App">
<header className="App-header">
<h1>React Tic Tac Toe</h1>
<h2>The winner is ... -- Fill in for wave 3 </h2>
<h2>Winner is {checkForWinner(squares)}</h2>
<button>Reset Game</button>

Choose a reason for hiding this comment

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

The reset button isn't quite working but here is a hint to get it to work:

  1. Add an onclick event to this button that will call a function
  2. The function will reset the squares state so that it is freshly generated and the winner is empty.

</header>
<main>
<Board squares={squares} />
<Board
squares={squares}
onClickCallback ={updateGameState}
/>

</main>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion src/App.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 14 additions & 5 deletions src/components/Board.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,29 @@ import Square from './Square';
import PropTypes from 'prop-types';


const generateSquareComponents = (squares, onClickCallback) => {
const generateSquareComponents = (squares) => {
// Complete this for Wave 1
// squares is a 2D Array, but
// you need to return a 1D array
// of square components
let oneDArray = [];
for(let i=0; i<squares.length; i+= 1) {
oneDArray = oneDArray.concat(squares[i]);
}
return oneDArray;

}

const Board = ({ squares, onClickCallback }) => {
const squareList = generateSquareComponents(squares, onClickCallback);

const squareList = generateSquareComponents(squares);
console.log(squareList);
return <div className="grid" >
{squareList}
</div>
const squareComponents = squareList.map(square => {
console.log(square)
return (<Square key={square.id}id={square.id} value={square.value} onClickCallback={onClickCallback}></Square>)
});

return <div className="grid">{squareComponents}</div>
}

Board.propTypes = {
Expand Down
93 changes: 47 additions & 46 deletions src/components/Board.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,53 +3,54 @@ import '@testing-library/jest-dom/extend-expect';
import Board from './Board';
import { render, screen, fireEvent} from '@testing-library/react'

const SAMPLE_BOARD = [
[
{
value: 'X',
id: 0,
},
{
value: 'X',
id: 1,
},
{
value: 'O',
id: 2,
},
],
[
{
value: 'X',
id: 3,
},
{
value: 'X',
id: 4,
},
{
value: 'O',
id: 5,
},
],
[
{
value: 'O',
id: 6,
},
{
value: 'O',
id: 7,
},
{
value: 'X',
id: 8,
},
],
];

describe('Wave 1: Board', () => {
// Sample input to the Board component
const SAMPLE_BOARD = [
[
{
value: 'X',
id: 0,
},
{
value: 'X',
id: 1,
},
{
value: 'O',
id: 2,
},
],
[
{
value: 'X',
id: 3,
},
{
value: 'X',
id: 4,
},
{
value: 'O',
id: 5,
},
],
[
{
value: 'O',
id: 6,
},
{
value: 'O',
id: 7,
},
{
value: 'X',
id: 8,
},
],
];


test('that board will render with the proper number of Xs and Os', () => {
// Act
Expand Down Expand Up @@ -84,7 +85,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(<Board squares={SAMPLE_BOARD} onClickCallback={callback} />);
Expand All @@ -97,7 +98,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(<Board squares={SAMPLE_BOARD} onClickCallback={callback} />);
Expand Down
2 changes: 2 additions & 0 deletions src/components/Square.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@
justify-content: center;
align-items: center;
margin: 2px;
width: 100%;
height: 100%;
}
9 changes: 3 additions & 6 deletions src/components/Square.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ import PropTypes from 'prop-types';

import './Square.css'

const Square = (props) => {
const Square = ({id, value, onClickCallback}) => {
// For Wave 1 enable this
// Component to alert a parent
// component when it's clicked on.


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

Square.propTypes = {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Square.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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(<Square value="X" id={1} onClickCallback={callback} />);
Expand Down
5 changes: 5 additions & 0 deletions src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@

/* * {
box-sizing: border-box;
} */

body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
Expand Down