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\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.