Checking for a win in Tic Tac Toe
public boolean hasWon(Seed theSeed) {



What is a Seed?  The way that you are using it, I'd expect a Player object.  


    for (int col = 0; col &lt; COLS; ++col) {               //check columns
        if (cells[currentRow][col].content == theSeed)
            count++;
        if (count == WIN_SIZE)
            return true;
    }



A more common format would be 

    //check squares in currentRow
    for (int col = 0; col &lt; COLS; ++col) {
        if (cells[currentRow][col].content == theSeed) {
            count++;
        } else {
            count = 0;
        }

        if (count == WIN_SIZE) {
            return true;
        }
    }


I added the else because I would expect a match to need to be consecutive.  As is, you would accept any row containing WIN_SIZE total matches.  Maybe that's what you want, but it's not what I would expect.  

You iterate over columns when you are checking a row.  The original comment was a bit confusing on that aspect.  

While there is a single statement form of control structures (if), it is often recommended not to use it.  It's less clear about what goes with what and it's easier to edit in a way that causes problems but is syntactically correct.  


    count = 0;

    int row = currentRow;

    for (int col = currentCol; col &gt;= 0; --col) {      //check forward diagonal
        if (cells[row][col].content == theSeed)
            count++;
        if (count == WIN_SIZE)
            return true;
        row--;
        if (row &lt; 0)
            break;
    }
    row = currentRow;
    count--;
    for (int col = currentCol; col &lt; COLS; ++col) {
        if (cells[row][col].content == theSeed)
            count++;
        if (count == WIN_SIZE)
            return true;
        row++;
        if (row == ROWS)
            break;
    }



This looks more complicated than it needs to be.  Consider 

    // check forward diagonal
    for (int col = currentCol, row = currentRow; col &gt;= 0 &amp;&amp; row &gt;= 0; --col, --row) {
        if (cells[row][col].content == theSeed)
            count++;
        if (count == WIN_SIZE)
            return true;
    }

    for (int col = currentCol + 1, row = currentRow + 1; col &lt; COLS &amp;&amp; row &lt; ROWS; ++col, ++row) {
        if (cells[row][col].content == theSeed)
            count++;
        if (count == WIN_SIZE)
            return true;
    }


Yes, you can use two variables in one for loop.  

Rather than decrementing the count, this skips the current square in the second loop.  

Or do the whole thing in one loop.  

    // check forward diagonal
    count = 0;
    int col = 0;
    int row = 0;
    if (currentCol &gt;= currentRow) {
        col = currentCol - currentRow;
    } else {
        row = currentRow - currentCol;
    }

    for (; col &lt; COLS &amp;&amp; row &lt; ROWS; ++col, ++row) {
        if (cells[row][col].content == theSeed) {
            count++;
        }

        if (count == WIN_SIZE) {
            return true;
        }
    }


More work up front to figure out the first square in the diagonal, but only a single loop.  

I left off the else case, as I'm not sure whether the current behavior is intentional or not.  The single loop version works with the else as before.  The double loop versions don't.