Transforming the typical Tic Tac Toe game from the React tutorial, with an added one-player feature. Oddly, button alignment shifts out of place once a value is inserted; causing the button to drop by about 50px until the row is filled with values, after which they realign back into formation on the board. I'm puzzled as to why this occurs and would appreciate any assistance in maintaining consistent button alignment.
There's also unpredictability in the computer's logic when selecting a diagonal move; it seems simple to trap the computer into choosing either 0
or 2
, where it then resorts to random selection to fill those squares. As per my understanding, the program "should..." recognize the necessity to choose these squares based on the given logic;
else if (squares[b] === 'X' && squares[b] === squares[c] && squares[a] === null){
console.log("need O in ", a);
return a;
I've maintained the console.log
statements within the program to demonstrate how and where I faced issues while troubleshooting this problem. Any insights offered would be immensely valued. Thank you for taking the time to assist.
The alignment glitch can be viewed on JS Bin
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tic Tac Toe</title>
<script src="https://unpkg.com/react@latest/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="640605060108491710050a0005080b0a0124524a55514a54">[email protected]</a>/babel.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id='root'></div>
<script type='text/babel' >
var numberXs = 0;
var lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
];
function Square(props){
return(
<button className="square" onClick={() => props.onClick()}>{props.value}</button>
);
}
class Board extends React.Component{
renderSquare(i){
return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />
}
render(){
return(
<div className="board" key={this.props.key}>
<div className="row">
{this.renderSquare(0)}
{this.renderSquare(1)}
{this.renderSquare(2)}
</div>
<div className="row">
{this.renderSquare(3)}
{this.renderSquare(4)}
{this.renderSquare(5)}
</div>
<div className="row">
{this.renderSquare(6)}
{this.renderSquare(7)}
{this.renderSquare(8)}
</div>
</div>
);
}
}
class Game extends React.Component{
defaultState = {
onePlayerGame: true,
squares: Array(9).fill(null),
xIsNext: true
};
constructor(props){
super(props);
this.onePlayer = this.onePlayer.bind(this);
this.twoPlayer = this.twoPlayer.bind(this);
this.handleMove = this.handleMove.bind(this);
this.gameOver = this.gameOver.bind(this);
this.state = this.defaultState;
}
onePlayer(){
this.setState({onePlayerGame: true});
return(
document.getElementById('onePlayer').style.color = "red",
document.getElementById('twoPlayer').style.color = "black"
);
}
twoPlayer(){
this.setState({ onePlayerGame: false});
return(
document.getElementById('onePlayer').style.color= "black",
document.getElementById('twoPlayer').style.color = "red"
);
}
handleMove(i){
var HALturn = true,
HALmove;
const squares = this.state.squares.slice();
if (checkWinner(squares) || squares[i]){
return;
}
if (this.state.onePlayerGame){
squares[i] = 'X';
numberXs += 1;
this.setState({squares:squares});
if (numberXs >= 5){
return;
}
if (HALbest(squares)){
HALmove = HALbest(squares);
squares[HALmove] = 'O';
this.setState({squares: squares});
return;
} else {
while (HALturn) {
HALmove = Math.floor(Math.random() * squares.length);
if (squares[HALmove] === null){
squares[HALmove] = 'O';
this.setState({
squares: squares
});
return;
HALturn = false;
} else {
console.log("Additional random selection");
}
}
}
}
else {
squares[i] = this.state.xIsNext ? 'X':'O';
this.setState({
squares: squares,
xIsNext: !this.state.xIsNext
});
}
}
gameOver(){
this.setState({...this.defaultState});
numberXs = 0;
}
render(){
var winner = checkWinner(this.state.squares);
let status, endGame;
if (winner) {
status = "Winner is " + winner;
} else if (!winner && numberXs === 5){
status = "No Winner. Reset to play again.";
} else {
status = "Next Move: " + (this.state.xIsNext ? 'X': 'O');
}
return(
<div id="main">
<div>
<button className="gameSelect" id="onePlayer" value={this.state.onePlayerGame} onClick={() => this.onePlayer()} >One Player</button>
<button className="gameSelect" id="twoPlayer"value={this.state.onePlayerGame} onClick={() => this.twoPlayer()} >Two Players</button>
</div>
<Board
squares={this.state.squares}
onClick={(i) => this.handleMove(i)} />
<div id="status">{status}</div>
<button className="gameSelect" id="resetButton" onClick={() => this.gameOver()}>Reset Game</button>
</div>
);
}
}
function checkWinner(squares){
for (var i = 0; i < lines.length; i++){
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]){
return squares[a];
}
}
return null;
}
function HALbest(squares){
for (var i = 0; i < lines.length; i++){
const [a, b, c] = lines[i];
if (squares[a] === 'X' && squares[a] === squares[c] && squares[b] === null){
console.log("need O in ", b);
return b;
} else if (squares[b] === 'X' && squares[b] === squares[c] && squares[a] === null){
console.log("need O in ", a);
return a;
} else if ( squares[a] === 'X' && squares[a] === squares[b] && squares[c] === null ){
console.log("need O in ", c);
return c;
}
}
return null;
}
ReactDOM.render(
<Game />,
document.getElementById('root')
)
</script>
</body>
</html>
Aspect Ratio issues persisted despite utilizing this CSS adaptation;
#main {
width: 80%;
margin: auto;
color: blue;
text-align: center;
}
.gameSelect {
width: 30%;
text-align: center;
background-color: white;
border: 1px solid transparent;
margin: 5px 0 5px 0;
}
.board {
display: inline;
}
#onePlayer {
color: red;
}
#status {
margin: 25px 0 5px 0;
}
.row {
margin: auto;
height: 100px;
}
.square {
width: 100px;
height: 100px;
background-color: white;
font-size: 20px;
margin: 0;
display: inline;
}
Your continued support is greatly appreciated.