Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                
<html lang="en">

<head>
  <meta charset="utf-8">
 

  <link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,700' rel='stylesheet' type='text/css'>
  <link href='https://fonts.googleapis.com/css?family=Lato:100,300italic,700,900' rel='stylesheet' type='text/css'>


  <!--Import Google Icon Font-->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <link href='https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900' rel='stylesheet' type='text/css'>

 
  





  <title>Tic-Tac-Toe</title>
</head>

<body>

  <nav>
    <div class="nav-wrapper z-depth-2">
      <a href="#" class="brand-logo center">Tic-Tac-Toe</a>
      <a href="#" data-activates="mobile-menu" class="button-collapse"><i class="material-icons">menu</i></a>
      <ul class="right hide-on-med-and-down">
        <li><a href="mailto:2am.ninja@outlook.com"><i class="icon-color fa fa-envelope"></i></a></li>
        <li><a href="https://www.linkedin.com/in/brucewilliamyoung" target="_blank"><i class="icon-color fa fa-linkedin"></i></a></li>
        <li><a href="https://twitter.com/mutantspore" target="_blank"><i class="icon-color fa fa-twitter"></i></a></li>
        <li><a href="https://codepen.io/MutantSpore/" target="_blank"><i class="icon-color fa fa-codepen"></i></a></li>
      </ul>
            <div class="black side-nav" id="mobile-menu">
                <div class="container middle person">
                    <img class="portrait" src="http://2am.ninja/img/bruce_contact3.jpg">
                    <span>Bruce Young</span>
                </div>
                <ul class="contact">
                    <li><a href="mailto:2am.ninja@outlook.com"><i class="fa fa-envelope"></i></a></li>
                    <li><a href="https://www.linkedin.com/in/brucewilliamyoung" target="_blank"><i class="fa fa-linkedin"></i></a></li>
                    <li><a href="https://twitter.com/mutantspore" target="_blank"><i class="fa fa-twitter"></i></a></li>
                    <li><a href="https://codepen.io/MutantSpore/" target="_blank"><i class="fa fa-codepen"></i></a></li>
                </ul>


            </div>
    </div>
  </nav>





<div class="container">

  <!-- Game Board -->
  <div id="board" class="container">
    <div class="row top valign-wrapper">
      <div class="square left col s4 valign waves-effect waves-light flow-text" id="0"></div>
      <div class="square middle col s4 valign waves-effect waves-light flow-text" id="1"></div>
      <div class="square right col s4 valign waves-effect waves-light flow-text" id="2"></div>
    </div>
    <div class="row middle valign-wrapper">
      <div class="square left col s4 valign waves-effect waves-light flow-text" id="3"></div>
      <div class="square middle col s4 valign waves-effect waves-light flow-text" id="4"></div>
      <div class="square right col s4 valign waves-effect waves-light flow-text" id="5"></div>
    </div>
    <div class="row bottom valign-wrapper">
      <div class="square left col s4 valign waves-effect waves-light flow-text" id="6"></div>
      <div class="square middle col s4 valign waves-effect waves-light flow-text" id="7"></div>
      <div class="square right col s4 valign waves-effect waves-light flow-text" id="8"></div>
    </div>
  </div>

</div>


  <!-- Score Board -->
  <div id="score-board" class="container">
    <div class="row">
      <div class="col s12">
        <div class="card-panel transparent">
          <span class="bluetext">
            <div class="row center-align">
              <div class="col s3">
                <span class="flow-text center-align">
                  <span><i class="fa fa-2x fa-user"></i></span>
                  <span id="score0" class="score">0</span>
                </span>
              </div>
              <div class="col s3">
                <span class="flow-text center-align">
                  <i class="fa fa-2x fa-ban"></i>
                  <span id="score1" class="score">0</span>
                </span>
              </div>
              <div class="col s3">
                <span class="flow-text center-align">
                  <i class="fa fa-2x fa-laptop"></i>
                  <span id="score2" class="score">0</span>
                </span>
              </div>
              <div class="col s3">
                <a id="new-game" class="btn-floating btn-large waves-effect waves-light amber darken-4"><i class="medium material-icons">replay</i></a>
              </div>
            </div>
          </span>
        </div>
      </div>
    </div>
  </div>





  <!-- Get Player Token Modal -->
  <div id="chooseModal" class="modal amber darken-4">
    <div class="modal-content">
      <div class="row">
        <div class="choose col s6 waves-effect waves-light" id="X"><i class='fa fa-times'></i></div>
        <div class="choose col s6 waves-effect waves-light" id="O"><i class='fa fa-circle-o'></i></div>
      </div>
    </div>
  </div>




  
</body>

</html>

              
            
!

CSS

              
                body {
  background-color: #6795C2;
}

.nav-wrapper {
  background-color: #083968;
}

#board {
  width: 90vw;
  height: 90vw;
  min-width: 300px;
  min-height: 300px;
  max-width: 600px;
  max-height: 600px;
  background-color: rgba(64, 116, 167,1);
  box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.32), 0 3px 12px 0 rgba(0, 0, 0, 0.24);
  text-align: center;
  margin-top: 50px;
}

#score-board {
  min-width: 300px;
  max-width: 600px;
  margin-top: 30px;
}

.score {
  font-size: 1.7em;
  color: #bbdefb;
}

.bluetext {
  color: rgba(64, 116, 167,1);
}

.icon-color{
  color: rgba(64, 116, 167,1);
}

.portrait {
  width: 200%;
  height: auto;
}

.person {
  font-size: 1.5em;
  color: white;
  text-align: center;
  width: 100%;
  line-height: 1.5em;
}

.contact {
  text-align: center;
}

.square {
  display: inline-block;
  margin: 0px;
  padding: 0px;
  border: 0px;
  width: calc(100%/3);
  height: 100%;
  background-color: rgba(0,0,0,0.0);
  border-style: none;
  cursor: pointer;
  text-align: center;
}

.who {
    color: #bbdefb;
    font-size: 5.5em;
    margin: 0px;
    border: 0px;
    padding: 0px;
}

.row.top,
.row.middle {
  border-bottom: dotted 2px #6795C2;
}

.square.left,
.square.middle {
  border-right: dotted 2px #6795C2;
}


#board > .row {
  height: calc(100%/3);
  margin: 0px;
  padding: 0px;
}


.choose {
  text-align: center;
  font-size: 8em;
  cursor: pointer;
  background-color: #eee;
  color: #555;
}

.choose:hover {
  background-color: rgba(0,0,0,0.0);
  color: #000;
}

.modal .modal-content {
    padding: 0px;
    margin: 0px;
}

.row {
  padding: 0px;
  margin: 0px;
}

#mobile-menu {
  padding: 0px;
  margin: 0px;
}

              
            
!

JS

              
                $(document).ready(function() {

    var squares = [0, 1, 2, 3, 4, 5, 6, 7, 8];
    var used = [0, 0, 0, 0, 0, 0, 0, 0, 0];
    var X_token = "<i class='fa fa-times'></i>";
    var O_token = "<i class='fa fa-circle-o'></i>";
    var humanPlayer = X_token;
    var aiPlayer = O_token;
    var empty = 0;
    var human = 1;
    var ai = 2;
    var hasMoved = false;
    var gameOver = false;
    var how = [];
    var score = [0, 0, 0];
    var delay;
    var move = {};
    var moveCounter = 0;
    var score_TIE = 1;
    var score_HUMAN = 0;
    var score_AI = 2;
    var outcome = null;


    var board = [
        [0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]
    ];

    var win = [
        [0, 1, 2],
        [3, 4, 5],
        [6, 7, 8],
        [0, 3, 6],
        [1, 4, 7],
        [2, 5, 8],
        [0, 4, 8],
        [2, 4, 6]
    ];



    var humanSound = new Audio('audio/water_droplet_3.mp3');
    var aiSound = new Audio('audio/water_droplet.mp3');



    function setNewGame() {
        squares.forEach(function(v) {
            $('#' + v).empty();
            $('#' + v).css('background-color', 'rgba(0,0,0,0.0)');
        });

        board = [
            [0, 0, 0],
            [0, 0, 0],
            [0, 0, 0]
        ];
        hasMoved = false;
        outcome = null;
        moveCounter = 0;
        gameOver = false;
        how = [];
        move = {};
    }


    function playSound(sound) {
        sound.play();
    }


    function moveHUMAN(here) {
        if (!(board[here.x][here.y])) {
            board[here.x][here.y] = human;
            // playSound(humanSound);
            drawMove(here, humanPlayer, 100);
            hasMoved = true;
        }
    }


    function moveAI_Rnd() {
        var min = Math.min.apply(null, board.reduce(function(a, b) {
            return a.concat(b);
        }, []));

        var whereMove = {};

        if (min === 0) {
            while (!(hasMoved)) {
                whereMove.x = Math.floor(Math.random() * 3);
                whereMove.y = Math.floor(Math.random() * 3);
                if (!(board[whereMove.x][whereMove.y])) {
                    board[whereMove.x][whereMove.y] = ai;
                    drawMove(whereMove, aiPlayer, 300);
                  //   playSound(aiSound);
                    hasMoved = true;
                }
            }
        }
    }




    function moveAI_Wiki() {

        // transfer board to used
        used = [0, 0, 0, 0, 0, 0, 0, 0, 0];
        var corner = [0, 2, 6, 8];
        var side = [1, 3, 5, 7];
        var count = 0;
        var theMove = null;
        for (var row = 0; row <= 2; row++) {
            for (var col = 0; col <= 2; col++) {
                used[count] = board[row][col];
                count++;
            }
        }

        function move() {
            var whereMove = {};
            whereMove.x = parseInt(theMove / 3);
            whereMove.y = theMove % 3;
            board[whereMove.x][whereMove.y] = ai;
            drawMove(whereMove, aiPlayer, 300);
            hasMoved = true;
            moveCounter++;
        }


        // opening move
        function opening() {
            if (theMove === null && (used[1] === human || used[3] === human)) {
                theMove = 0;
                move();
            }

            if (theMove === null && (used[5] === human || used[7] === human)) {
                theMove = 8;
                move();
            }

            if (used[4] === human && theMove === null) {
                emptyCorner();
                return;
            }

            if (used[4] === empty && theMove === null && moveCounter === 0 && aiPlayer === X_token) {
                theMove = corner[Math.floor(Math.random() * 4)];
                move();
            }

            if (used[4] === empty && theMove === null) {
                playCenter();
                return;
            }
        }


        // look for a win
        function aWin() {
            win.forEach(function(solution) {
                if ((used[solution[0]] === ai && used[solution[1]] === ai && used[solution[2]] == empty) ||
                    (used[solution[0]] === ai && used[solution[1]] === empty && used[solution[2]] == ai) ||
                    (used[solution[0]] === empty && used[solution[1]] === ai && used[solution[2]] == ai)) {

                    solution.forEach(function(pos) {
                        if (used[pos] === empty && theMove === null) {
                            theMove = pos;
                        }
                    });
                    move();
                }
            });
        }


        // look for a block
        function block() {
            if (used[4] === empty && theMove === null) {
                playCenter();
                return;
            }

            win.forEach(function(solution) {
                if ((used[solution[0]] === human && used[solution[1]] === human && used[solution[2]] == empty) ||
                    (used[solution[0]] === human && used[solution[1]] === empty && used[solution[2]] == human) ||
                    (used[solution[0]] === empty && used[solution[1]] === human && used[solution[2]] == human)) {

                    solution.forEach(function(pos) {
                        if (used[pos] === empty && theMove === null) {
                            theMove = pos;
                        }
                    });
                    move();
                }
            });
        }


        // make fork
        function fork() {
            win.forEach(function(solution) {
                if ((used[solution[0]] === ai && used[solution[1]] === empty && used[solution[2]] == empty) ||
                    (used[solution[0]] === empty && used[solution[1]] === empty && used[solution[2]] == ai) ||
                    (used[solution[0]] === empty && used[solution[1]] === ai && used[solution[2]] == empty)) {

                    if (used[4] === ai &&
                        (([used[0] === human] && used[8] === human) || ([used[2] === human] && used[6] === human))) {
                        side.forEach(function(pos) {
                            if (used[pos] === empty && theMove === null) {
                                theMove = pos;
                            }
                        });
                    } else {
                        corner.forEach(function(pos) {
                            if (used[pos] === empty && theMove === null) {
                                theMove = pos;
                            }
                        });
                    }
                    move();
                }
            });
        }


        // block fork
        function blockFork() {
            if (moveCounter > 1 && used[4] !== empty && theMove === null) {
                emptySide();
                return;
            }

            win.forEach(function(solution) {
                if ((used[solution[0]] === human && used[solution[1]] === empty && used[solution[2]] == empty) ||
                    (used[solution[0]] === empty && used[solution[1]] === empty && used[solution[2]] == human) ||
                    (used[solution[0]] === empty && used[solution[1]] === human && used[solution[2]] == empty)) {

                    side.forEach(function(pos) {
                        if (used[pos] === empty && theMove === null) {
                            theMove = pos;
                        }
                    });
                    move();
                }
            });
        }


        // play center
        function playCenter() {
            if (used[4] === empty && theMove === null) {
                theMove = 4;
                move();
            }
        }


        // opposite corner
        function oppositeCorner() {
            if (used[0] === human && used[8] === empty && theMove === null) {
                theMove = 8;
                move();
            } else if (used[0] === empty && used[8] === human && theMove === null) {
                theMove = 0;
                move();
            } else if (used[2] === human && used[6] === empty && theMove === null) {
                theMove = 6;
                move();
            } else if (used[2] === empty && used[6] === human && theMove === null) {
                theMove = 2;
                move();
            }
        }


        // empty corner
        function emptyCorner() {
            corner.forEach(function(pos) {
                if (used[pos] === empty && theMove === null) {
                    theMove = pos;
                    move();
                }
            });
        }


        //empty side
        function emptySide() {
            side.forEach(function(pos) {
                if (used[pos] === empty && theMove === null) {
                    theMove = pos;
                    move();
                }
            });
        }


        //based on wikipedia solution
        // https://en.wikipedia.org/wiki/Tic-tac-toe

        //0. opening move
        if (theMove === null && moveCounter === 0) {
            opening();
        }

        //1. Win
        if (theMove === null) {
            aWin();
        }

        //2. Block
        if (theMove === null) {
            block();
        }

        //3. Fork
        if (theMove === null) {
            fork();
        }

        //4. Block Fork
        if (theMove === null) {
            blockFork();
        }

        //5. Center
        if (theMove === null) {
            playCenter();
        }

        //6. Opposite corner
        if (theMove === null) {
            oppositeCorner();
        }

        //7. Empty corner
        if (theMove === null) {
            emptyCorner();
        }

        //8. Empty side
        if (theMove === null) {
            emptySide();
        }
    }



    function drawMove(location, who, delay) {
        setTimeout(function() {
            $('#' + (location.x * 3 + location.y)).html("<span class='who valign center-align animated fadeIn'>" + who + "</span>");
        }, delay);
    }


    function checkStatus() {

        var min = Math.min.apply(null, board.reduce(function(a, b) {
            return a.concat(b);
        }, []));

        [ai, human].forEach(function(player) {
            win.forEach(function(solution) {
                var check = 0;
                solution.forEach(function(pos) {
                    if (board[parseInt(pos / 3)][pos % 3] === player) {
                        check++;
                    }
                });
                if (check === 3) {
                    if (player === ai) {
                        outcome = score_AI;
                        gameOver = true;
                        how = solution;
                        score[score_AI]++;
                    } else {
                        outcome = score_HUMAN;
                        gameOver = true;
                        how = solution;
                        score[score_HUMAN]++;
                    }
                }
            });
        });

        // if no moves left to make it's a draw
        if (min !== 0 && !gameOver) {
            hasMoved = true;
            gameOver = true;
            outcome = score_TIE;
            score[score_TIE]++;
            return;
        }
    }



    function showWin() {
        console.log(gameOver, outcome, how);
        how.forEach(function(v) {
            $('#' + v).css('background-color', 'rgba(0,0,0,0.2)');
        });
    }


    function updateScore() {
        score.forEach(function(count, i) {
            $('#score' + i).text(count);
        });

        $('#score' + outcome).addClass('animated flash');
        $('#score' + outcome).one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function() {
            $('#score' + outcome).removeClass('animated flash');
        });
    }


    function control() {

        if (aiPlayer === X_token && moveCounter === 0) {
            hasMoved = false;
            moveAI_Wiki();
            checkStatus();
        }

        $('#board').on('click', '.square', (function() {

            hasMoved = false;

            if (!hasMoved && !gameOver) {
                move.x = parseInt($(this).attr('id') / 3);
                move.y = $(this).attr('id') % 3;
                moveHUMAN(move);
                checkStatus();
            }

            if (hasMoved && !gameOver) {
                hasMoved = false;
                //moveAI_Rnd();
                moveAI_Wiki();
                checkStatus();
            }

            if (hasMoved && gameOver) {
                showWin();
                updateScore();
            }
        }));

    }



    $('#X').click(function() {
        humanPlayer = X_token;
        aiPlayer = O_token;
        $('#chooseModal').closeModal();
        control();
    });

    $('#O').click(function() {
        humanPlayer = O_token;
        aiPlayer = X_token;
        $('#chooseModal').closeModal();
        control();
    });

    $('#new-game').click(function() {
        setNewGame();
        control();
    });


    $(".button-collapse").sideNav();

    setNewGame();
    $('#chooseModal').openModal();


});

              
            
!
999px

Console