Question

I'm creating a simple memory matching game and I want to compare the text-value of each clicked cell to see if a match is made. The click event handler at the bottom is my attempt to do so but I'm not sure how to save which cell was clicked. How do I save the text-value of each cell and compare them, while also saving which cell I'm comparing so I can hide it if the two cells that were clicked are not equal? Text-indent is set to 100%, and overflow is hidden by default.

var createTable = function (col, row) {
    $('table').empty();
    for (var i = 1; i <= row; i++) {
        $('table').append($('<tr>'));
    }
    for (var j = 1; j <= col; j++) {
        $('tr').append($('<td>'));
    }
    countCells = row * col;
};
createTable(4, 1);

var arr = [1, 2, 1, 2];
var pushNum = function () {
    var len = arr.length;
    for (var i = 0; i <= len; i++) {
        var ran = Math.ceil(Math.random() * arr.length) - 1;
        $('td').eq(i).append(arr[ran]);
        arr.splice(ran, 1);
    }
};
pushNum();

var match1;
$('td').click(function () {
    $(this).css('text-indent', 0);
    match1 = $(this).eq();
    if (match1.val() === "1") {
        alert("GOOD");
    }
});
Was it helpful?

Solution

Personally, I think I would create a couple of functions to handle two things:

1) an onclick function on each cell that would simply toggle some kind of "clicked" class (using toggleClass()), when a cell is clicked. It could have a visual indicator as well (e.g., change text or background color or something like that).

2) an independent function that would get called by the "onclick" in #1, after the toggle was complete, to check to see if exactly 2 cells had been clicked. you could use a jQuery selector to get all of the cells with the "clicked" class and, if the length of the return set equals 2, then use the first() and last() functions to get the values of the clicked cells so that you can compare them. This is the function where you would integrate your existing "do they match" JS code from above.

That way, you wouldn't actually have to store the value, you just wouldn't ever check unless you know that you had two selections made and then you would check them real-time.

OTHER TIPS

Found it interesting so I made my attempt to implement it with simple jQuery

jQuery memory game

var $mainTable = $('#mainTable'),
    myWords = [],
    valA, valB, col=4, row=3, start;

//    function to create the table
var createTable = function (col, row) {
    var $table = $('<table>'), i;

    // construct our table internally
    for(var i=0; i<row; i++){
        var $tr = $('<tr data-row="'+i+'">'); // make row

        for(var j=0; j<col; j++){
            $tr.append($('<td data-col="'+j+'">')); // make cell
        }
        $table.append($tr);
    }

    $mainTable.html($table.html());
};

//    generate an array random words from a dictionary
var giveWords = function(pairsRequested){
    var dictionary = ['now','this','is','only','a','test','I','think'],
        ar = dictionary.slice(0,pairsRequested);

    ar = ar.concat(ar);
    // taken from @ http://jsfromhell.com/array/shuffle [v1.0]
    for(var j, x, i = ar.length; i; j = parseInt(Math.random() * i), x = ar[--i], ar[i] = ar[j], ar[j] = x);
    return ar;
}

// initialize
createTable(col,row);
myWords = giveWords(6); // our words array

// listen
$mainTable.on('click', 'td' ,function(){
    var $that = $(this),
        thisCol = $that.data('col'),
        thisRow = $that.closest('tr').data('row');

    if(!valB && !$that.hasClass('clicked')){
        var itemNum = (thisRow*(col))+thisCol;

        if(!valA){   // first item clicked
            valA = myWords[itemNum];
            $that.addClass('clicked')
                 .text(valA);

        } else {    // we already have a clicked one
            valB = myWords[itemNum];

            if(valA === valB){ // if they match...
                $mainTable.find('.clicked')
                          .add($that)
                          .removeClass('clicked')
                          .addClass('revealed')
                          .text(valA);

                //    check how many open remaining
                var open = $mainTable.find('td')
                                     .not('.revealed')
                                     .length;

                if(open===0){    //    if 0, game over!
                    var elapsed = Date.now()-start;
                    alert('Congratulations! cleared the table in '+elapsed/1000+' seconds.');
                }

                valA = valB = undefined;
            } else {
                $that.addClass('clicked')
                     .text(valB);

                setTimeout(function(){ // leave the value visible for a while
                    $mainTable.find('.clicked')
                              .removeClass('clicked')
                              .text('');
                    valA = valB = undefined;
                },700);
            }
        }
    }

    if(!start){     // keep time of game completion
        start=Date.now(); 
    }
});

Used data-num attribute for table cell values instead of using classes. There were some problems to be fixed, like double clicking on the same cell or clicking on already revealed cell, but all in all, now it works!

var countCells;

var createTable = function (col, row) {
    var str = '';
    for (var i = 1; i <= row; i++) {
        str += '<tr>';
        for (var j = 1; j <= col; j++) {
            str += '<td>';
        }
        str += '</tr>';
    }
    $('table').html(str);
    countCells = row * col;
};
createTable(6, 3);

function shuffle(o) {
    for (var j, x, i = o.length; i; j = parseInt(Math.random() * i, 10), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
}
// http://stackoverflow.com/questions/6274339/how-can-i-shuffle-an-array-in-javascript

var arr = [];
for (var i = 0; i < countCells / 2; i++) {
    arr[i] = arr[i + countCells / 2] = i + 1;
}
shuffle(arr);
//console.log(arr);

var tds = $('table td');
tds.each(function (i) {
    this.setAttribute('data-num', arr[i]);
});

var attempts = 0;
var match1 = null;
var info = $('#info');
var wait = false;
$('td').click(function () {
    if (wait) {
        return;
    } // wait until setTimeout executes
    var num = this.getAttribute('data-num');
    if (match1 === null && num != 'X') { //1st click on unmatched cell
        match1 = this;
        this.innerHTML = num;
        attempts++;
        info.text('Attempts: ' + attempts);
        return;
    } else { //2nd click
        var num1 = match1.getAttribute('data-num'); //1st num
        if (match1 === this) {
            // clicked twice this cell
            return;
        } else if (num == 'X') {
            // clicked on already revealed cell
            return;
        } else if (num == num1) {
            // both cells match
            info.text('Bingo! Attempts: ' + attempts);
            this.innerHTML = match1.innerHTML = num1;
            this.setAttribute('data-num', 'X');
            match1.setAttribute('data-num', 'X');
            match1 = null;
        } else {
            // cells not match
            info.text('Try again. Attempts: ' + attempts);
            this.innerHTML = num;
            var self = this;
            wait = true;
            window.setTimeout(function () {
                self.innerHTML = match1.innerHTML = '';
                match1 = null;
                wait = false;
            }, 1000);
        }
    }
});

jsfiddle

enjoy! :-)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top