Quando eu fiz isto pela primeira vez foi na calculadora. O programa ficou tão grande que só me sobravam uns 30 ou 40 bytes na memória, o que não dava para as variáveis todas... Tive de tirar o código para o computador jogar e ficou para dois jogadores...
Depois, no 11º ano, acho eu, tive de fazer isso em VB. Já foi para aí há 5 anos, por isso não me lembro bem de todos os pormenores, mas aqui ficam algumas conclusões que tirei na altura.
A estratégia de (o programador) calcular todas as jogadas possíveis previamente não é tão difícil como parece. E não dá uma catrefada de ifs. Pelo menos pela minha definição de catrefada. E dá para fazer com switch, o que simplifica as coisas.
No fundo, quando a "inteligência" estiver toda implementada, só existem quatro ou cinco jogos diferentes possíveis.
Não precisas de código para verificar se o jogador ganha. Esse código nunca vai ser executado
. Para verificar um empate é simples: se ao fim das 9 jogadas ninguém ganhar, é empate. Para verificar se o programa ganhou... lê a seguir...
Deves começar por escrever código para não deixar o jogador terminar uma linha (ou para o programa ganhar...), ou seja, quando duas casas adjacentes têm o mesmo símbolo, jogar na casa que evita a linha (ou faz). Se as duas casas adjacentes tinham o símbolo do programa, ganhou. Senão safou-se de perder.
Depois de escrever código para fechar linhas, falta o código para as primeiras duas ou três jogadas, que são tudo o que define o jogo. Na altura passei uma tarde inteira a jogar contra mim próprio (no meu programa, a dois jogadores) para verificar todas as possibilidades.
Depois há que reduzir os padrões das primeiras jogadas àqueles que são "seguros", isto é, que não deixam o jogador fazer uma jogada que o leva a ganhar o jogo.
Por exemplo, só há três tipos de 1ª jogadas: num canto, no centro, ou numa das outras quatro casas (eu chamei-lhes lados). Qualquer uma é segura, apesar de os lados apresentarem muito menos chances de vitória, excepto contra um jogador estúpido. Sendo o computador a começar, uma casa aleatória, com preferência pelo centro e pelos cantos. Eu dei ainda mais preferência aos cantos, de modo a apanhar desprevenidos alguns jogadores que estão habituados a começar sempre pelo centro. Se for o jogador a começar e jogar num dos lados, jogar no centro. Outras jogadas levam invariavelmente a uma derrota. Se ocorrer o oposto (programa -> lado), mas o jogador não joga no centro, já da para ganhar.
Espero que esta pequena análise de algumas situações iniciais sirva de alguma ajuda.