3
\$\begingroup\$

This is a project that grew out of the React Tutorial and is one of my first efforts at solving React problems on my own. There is a lot of code here and I am sure that there are more concise ways to have completed aspects of this project. Any suggestions, insights or positive comments would be greatly appreciated.

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" id={props.id} onClick={() => props.onClick()}>{props.value}</button>    
    );
}

class Board extends React.Component{
  renderSquare(i, j){
    return <Square id={j}  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, "squareOne")}
        {this.renderSquare(1, "squareTwo")}
        {this.renderSquare(2, "squareThree")}
    </div>
    <div className="row">
        {this.renderSquare(3, "squareFour")}
        {this.renderSquare(4, "squareFive")}
        {this.renderSquare(5, "squareSix")}
    </div>
    <div className="row">
        {this.renderSquare(6, "squareSeven")}
        {this.renderSquare(7, "squareEight")}
        {this.renderSquare(8, "squareNine")}
    </div>
    </div>
    );
  }
}

class Game extends React.Component{

   defaultState = {
      playerOneIcon: 'X',
      playerTwoIcon: 'O',
      easy: false,
      onePlayerGame: true,
      squares: Array(9).fill(null),
      OneIsNext: 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 = "white",
    document.getElementById('twoPlayer').style.color = "black"
    );
  }


  twoPlayer(){
    this.setState({ onePlayerGame: false});
    return(
    document.getElementById('onePlayer').style.color= "black",
    document.getElementById('twoPlayer').style.color =  "white"
    );
  }

  playerOneSelectX(){
    document.getElementById('playerOneX').style.color = "white";
    document.getElementById('playerOneO').style.color = "black";
  }

  playerOneSelectO(){
    document.getElementById('playerOneX').style.color = "black";
    document.getElementById('playerOneO').style.color = "white";
    this.setState({
      playerOneIcon: 'O',
      playerTwoIcon: 'X',
      }, () => {this.state});
  }


  handleMove(i){
    var HALturn = true,
        HALmove;
    const squares = this.state.squares.slice();
    const playerOneIcon = this.state.playerOneIcon;
    const playerTwoIcon = this.state.playerTwoIcon;

    if (checkWinner(squares) || squares[i]){
      return;
    }

    if (this.state.onePlayerGame){
      squares[i] = playerOneIcon;
      numberXs += 1;
      this.setState({squares:squares});
      if (numberXs >= 5){
        return;
      }

      if (!squares[4] && !this.state.easy){
        squares[4] = playerTwoIcon;
        this.setState({squares: squares});
        return;
      }
      if (HALbest(squares, playerOneIcon) !== null){
        HALmove = HALbest(squares, playerOneIcon);
        squares[HALmove] = playerTwoIcon;
        this.setState({squares: squares});
        return;


      } else {
      while (HALturn) {
        HALmove = Math.floor(Math.random() * squares.length);
        if (squares[HALmove] === null){
          squares[HALmove] = playerTwoIcon;
          this.setState({
            squares: squares
          });
          return;
          HALturn = false;
        } else {
          console.log("Additional Random Selection");
        }
      }
      }
    }

    else {
      squares[i] = this.state.OneIsNext ? playerOneIcon: playerTwoIcon;
      this.setState({
        squares: squares,
        OneIsNext: !this.state.OneIsNext
      });
    } 
  }

  easyDay(){
    var easy = this.state.easy;
    var newEasy = !easy;
    this.setState({easy: newEasy}, () => {this.state});
    console.log("after change ", this.state.easy);
    if (newEasy){
      document.getElementById('easyMe').style.backgroundColor = 'green';
      document.getElementById('easyMe').innerHTML = "Harder";
    } else {
      document.getElementById('easyMe').style.backgroundColor = 'red';
      document.getElementById('easyMe').innerHTML = "Easy";
    }
    console.log("after function ", this.state.easy);
  }

  gameOver(){
    this.setState({...this.defaultState});
    numberXs = 0;
    console.log(this.state.easy);
    document.getElementById('onePlayer').style.color = "white",
    document.getElementById('twoPlayer').style.color = "black"
    document.getElementById('easyMe').style.backgroundColor = 'red';
    document.getElementById('easyMe').innerHTML = "Easy";
    document.getElementById('playerOneX').style.color = "white";
    document.getElementById('playerOneO').style.color = "black";
  }

  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.OneIsNext ? this.state.playerOneIcon: this.state.playerTwoIcon);
    }


    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>
      <div>
      <h3>Player One is:
        <button className="iconSelect" id="playerOneX" value={this.state.playerOneIcon} onClick={() => this.playerOneSelectX()}  >X</button>
        <button className="iconSelect" id="playerOneO" value={this.state.playerOneIcon} onClick={() => this.playerOneSelectO()}  >O</button></h3>
      </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>
        <button className="easyButton" id='easyMe' onClick={() => this.easyDay()}>Easy</button>
      </div>
    </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, icon){
  for (var i = 0; i < lines.length; i++){
    const [a, b, c] = lines[i];
    if (squares[a] === icon && squares[a] === squares[c] && squares[b] === null){
      console.log("need O in ", b);
      return b;
    } else if (squares[b] === icon && squares[b] === squares[c] && squares[a] === null){
      console.log("need O in ", a);
      return a;
    } else if ( squares[a] === icon &&  squares[a] === squares[b] && squares[c] === null  ){
      console.log("need O in ", c);
      return c;
    } 
  } 
  return null;
}


ReactDOM.render(
  <Game />,
  document.getElementById('root')
)
#body {
  background-color: #678e40;
}

#main {
  width: 60%;
  margin: auto;
  color: black;
  text-align: center;
}

.gameSelect {
  width: 30%;
  text-align: center;
  background-color: #5d6002;
  border: 1px solid transparent;
  border-radius: 3px;
  margin: 5px 0 5px 0;
}

.iconSelect {
  margin: 3px;
  background-color: #5d6002;
  border-radius: 3px;
  border: 1px solid transparent;
}

.board {
  display: inline;
}

#onePlayer {
  color: white;
  margin: 15px 15px 15px 0;
}

#twoPlayer {
  margin: 15px 0 15px 15px;;
}

#easyMe {
  margin-top: 15px;
  width: 75px;
  height: 75px;
  background-color: red;
  color: white;
  border: 2px solid white;
  border-radius: 50px;
}

#status {
  margin: 25px 0 5px 0;
}

.row {
  margin: auto;
  height: 100px;
}

.square {
  vertical-align: top;
  width: 100px;
  height: 100px;
  background-color: #bdc14b;
  font-size: 20px;
  margin: 0;
  display: inline;
  border: 1px solid black;
}

#squareOne {
  border-right: 1px solid #5d6002;
  border-bottom: 1px solid #5d6002;
  border-radius: 5px 0 0 0;
}

#squareThree {
  border-left: 1px solid #5d6002;
  border-bottom: 1px solid #5d6002;
  border-radius: 0 5px 0 0;
}
#squareFive {
  border: 1px solid #5d6002;
}

#squareNine {
  border-left: 1px solid #5d6002;
  border-top: 1px solid #5d6002;
  border-radius: 0 0 5px 0;
}

#squareSeven {
  border-right: 1px solid #5d6002;
  border-top: 1px solid #5d6002;
  border-radius: 0 0 0 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='root'></div>

Here it is on CodePen.

\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.