A little background: as a way to learn multinode trees in C++, I decided to generate all possible TicTacToe boards and store them in a tree such that the branch beginning at a n
The "naive" way to do this (for an arbitrary game where two players take turns doing a move) is to try each possible move recursively until you end up with a board where one is the winner, then back-track upwards in the tree marking the nodes as "O wins", "X wins" or "draw".
Each time you step up (one such step is usually called a ply), depending on who's move it is, assume the player chooses the move that is best for him/her. Since you are moving from the leaves and upwards, you will always know the optimum possible results for each child node.
When counting the number of possible winning or losing boards in a subtree, you are essentially assuming that each player will always make a random move. As you noted, this will not be very effective if you play against a smart player. The scheme I outlined above instead assumes that the opponent always makes a perfect move, trying to win.