Initial commit

This commit is contained in:
2021-08-23 10:18:21 +07:00
parent 586ca9ff5b
commit b106042971
9 changed files with 273 additions and 0 deletions
+20
View File
@@ -0,0 +1,20 @@
{
"responsive-preview": {
"Mobile": [
320,
675
],
"Tablet": [
1024,
765
],
"Desktop": [
1400,
800
],
"Desktop HD": [
1920,
1080
]
}
}
+28
View File
@@ -0,0 +1,28 @@
{
"name": "tic-tac-toe",
"version": "1.0.0",
"description": "",
"keywords": [],
"main": "src/index.js",
"dependencies": {
"react": "17.0.2",
"react-dom": "17.0.2",
"react-scripts": "4.0.0"
},
"devDependencies": {
"@babel/runtime": "7.13.8",
"typescript": "4.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
+11
View File
@@ -0,0 +1,11 @@
import "./styles.css";
import Game from "./Game";
export default function App() {
return (
<div className="App">
<h1> Tic Tac Toe game </h1>
<Game />
</div>
);
}
+64
View File
@@ -0,0 +1,64 @@
import React from "react";
import Square from "./Square";
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
slot: true
};
this.clickHandler = this.clickHandler.bind(this);
this.handleClick = this.handleClick.bind(this);
}
clickHandler() {
console.log("Click");
this.setState({ value: "O" });
}
handleClick(props) {
let square = this.state.squares.slice();
console.log(square);
this.state.slot === true ? (square[props] = "X") : (square[props] = "O");
this.setState({
squares: square,
slot: !this.state.slot
});
}
renderSquare(props) {
return (
<Square
value={this.state.squares[props]}
onClick={() => this.handleClick(props)}
/>
);
}
render() {
const status = "Next player: X";
return (
<div>
<div className="status">{status}</div>
<div className="board-row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="board-row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="board-row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
export default Board;
+20
View File
@@ -0,0 +1,20 @@
import React from "react";
import Board from "./Board";
class Game extends React.Component {
render() {
return (
<div className="game">
<div className="game-board">
<Board />
</div>
<div className="game-info">
<div>{/* status */}</div>
<ol>{/* TODO */}</ol>
</div>
</div>
);
}
}
export default Game;
+20
View File
@@ -0,0 +1,20 @@
import React from "react";
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null
};
}
render() {
return (
<button className="square" onClick={() => this.props.onClick()}>
{this.props.value}
</button>
);
}
}
export default Square;
+12
View File
@@ -0,0 +1,12 @@
import { StrictMode } from "react";
import ReactDOM from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
rootElement
);
+55
View File
@@ -0,0 +1,55 @@
.App {
font-family: sans-serif;
text-align: center;
}
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.square {
background: #fff;
border: 1px solid black;
float: left;
font-size: 24px;
font-weight: bold;
line-height: 34px;
height: 34px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 34px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game {
display: flex;
flex-direction: row;
}
.game-info {
margin-left: 20px;
}