Labels

game (1) javascript (1) jQuery (1) JS (1) tic-tac-toe (1)

Wednesday, April 6, 2011

Tic-Tac-Toe with jQuery

A little while ago I got this idea in my head to make games in jQuery and so to see how easy or hard it would be I wanted to first make a simple Tic-Tac-Toe game, and then go from there. And as it turns out it is VERY simple :-) lol. I am at work on an adventure game, but am getting really caught up in the graphics lol, so until that is done i thought i would share my Tic-Tac-Toe game.

I first concentrated on the basics of the game, what would it require? I needed to map out the cycle of the game and all possible outcomes. I wanted to just focus on the game play, and not the starting or stopping of it, or the players logic.

player clicks space -> need to check if space is already marked -> if no mark : mark for player -- else : do nothing or alert to pick different space

if player marks space -> need to validate board to check for winner -> if winner : alert winner/game ends -- if no more space : alert tie/game ends -- else next player turn

if End Game -> need to reset board 

Since it was looking like the whole game would be progressed by each players 'onClick()' of the game board, so i made a function called playerMove() which would take the current element (the space that was clicked) and used that as the point of reference. When the player clicked on a space, if the space has not been marked, mark it for that player and validate the board.

        <table>
            <tbody>
                <tr>

                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                </tr>
                <tr>
                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                </tr>
                <tr>
                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                    <td onclick="playerMove(this);"></td>
                </tr>
            </tbody>
        </table>

function playerMove(t){
    if(!($(t).hasClass(pClassOne())) && !($(t).hasClass(pClassTwo())) && $('#mainWrap').hasClass('started')){
        $(t).addClass(pClass());
        if(validateBoard()){
            $('#mainWrap').removeClass('started');
            $('#GameButton').removeClass('hideMe');
        }else{
            nextTurn();
        }
    }
}

The validation was simple as well, there is only 8 possible combinations for a win in tic-tac-toe so i made one method that checks them all, of course this could be broken up to smaller methods but thats up to you. But if the board validates i pass the winning indexes to the showWinner() function so that it can highlight those spaces and show how the player won.


function checkIfFull(){
    var booleanCheck = true;
    $('table').find('td').each(function(){
        if(!$(this).hasClass(pClassOne()) && !$(this).hasClass(pClassTwo())){
            booleanCheck =  false;
        }  
    });
    if(booleanCheck){
        return true;
    }else{
        return false;
    }
}


function validateBoard(){
    if($('td:eq(0)').hasClass(pClass()) && $('td:eq(1)').hasClass(pClass()) && $('td:eq(2)').hasClass(pClass())){
        showWinner(0,1,2);
        return true;
    }else if($('td:eq(3)').hasClass(pClass()) && $('td:eq(4)').hasClass(pClass()) && $('td:eq(5)').hasClass(pClass())){
        showWinner(3,4,5);
        return true;
    }else if($('td:eq(6)').hasClass(pClass()) && $('td:eq(7)').hasClass(pClass()) && $('td:eq(8)').hasClass(pClass())){
        showWinner(6,7,8);
        return true;
    }else if($('td:eq(0)').hasClass(pClass()) && $('td:eq(3)').hasClass(pClass()) && $('td:eq(6)').hasClass(pClass())){
        showWinner(0,3,6);
        return true;
    }else if($('td:eq(1)').hasClass(pClass()) && $('td:eq(4)').hasClass(pClass()) && $('td:eq(7)').hasClass(pClass())){
        showWinner(1,4,7);
        return true;
    }else if($('td:eq(2)').hasClass(pClass()) && $('td:eq(5)').hasClass(pClass()) && $('td:eq(8)').hasClass(pClass())){
        showWinner(2,5,8);
        return true;
    }else if($('td:eq(0)').hasClass(pClass()) && $('td:eq(4)').hasClass(pClass()) && $('td:eq(8)').hasClass(pClass())){
        showWinner(0,4,8);
        return true;
    }else if($('td:eq(2)').hasClass(pClass()) && $('td:eq(4)').hasClass(pClass()) && $('td:eq(6)').hasClass(pClass())){
        showWinner(2,4,6);
        return true;
    }else{
        if(checkIfFull()){
            showTie();
            return true;
        }else{
            return false;
        }
    }
}

function showWinner(numOne,numTwo,numThree){
    $('td:eq('+numOne+'),td:eq('+ numTwo +'),td:eq('+ numThree +')').addClass('flash');
    $('#messageBox').text(player()+ ' WINS!!');
}

Once I got the main game going, it was time to add the players, and the logic around them. To start, i wanted the players to have the ability to create custom names, but with that I would also need to ensure that the names where not the same otherwise the validation would fail. I would also add a start and end buttons, and if the game is left untouched i wanted it to reset itself, so i added player cookies to track session and current player. 

 function startGame(){
    if((pOne() != null && pOne() != '')&&(pTwo() != null && pTwo() != '')){
        if(pOne() != pTwo()){
            $('.startWrap').addClass('hideMe');
            $('#GameButton').addClass('hideMe').find('.btn').attr('onCLick','endGame();').find('#buttonText').text('End');
            $('#mainWrap').addClass('started');
            $.cookie('player', pOne());
            $.cookie(pOne(), 'one');
            $.cookie(pTwo(), 'two');
            $('#messageBox').text(player()+' go!');
        }else{
            $('#messageBox').text('Each player must have a unique name');
        }
    }else{
        $('#messageBox').text('We need two players to start the game... DUH');
    }
}

function nextTurn(){
    if(player() == pOne()){
        $.cookie('player', pTwo());
    }else{
        $.cookie('player', pOne());
    }
    $('#messageBox').text(player()+ ' go!');
}

function endGame(){
    $('td').each(function(){
        $(this).removeClass(pClassOne()).removeClass(pClassTwo()).removeClass('flash');
    });
    $('input:text').val('');
    $('#GameButton').removeClass('hideMe').find('.btn').attr('onCLick','endGame();').find('#buttonText').text('End');
    $('.startWrap').removeClass('hideMe');
    $('#messageBox').text('');
}

To see it in action or to see the complete jQuery file, just download the files below and then just launch the page and play!
for a complete zip of all the files:http://ge.tt/3aXFzJ5

Questions?
Twitter: @jQueryGirl

2 comments:

  1. I think (I'm just starting to learn this myself) if you use something like

    $('td').click(function() {
    playerMove(this);
    )}

    in your document ready function you can remove the behavior from your markup.

    Then if you get a "designer type" to work on your markup, you don't have to worry about them messing up any of your code.

    ReplyDelete
  2. Yup :-) and, I could also turn it into a plug-in so it would look like this:

    $('tbody td').ticTacToe();

    but i use the one you referenced all the time, and actually i really don't know why i did it that way... hummm :-/

    ReplyDelete