8

I know this has been asked a lot and I've searched other code but most of what I've seen doesn't seem flawless (never loses) and simple, elegant and efficient. And I'm unable to decide which type of solution would fit that description.

The solutions I've seen are:

(1) Using minimax with alpha-beta pruning. This seems complicated to me and possibly unnecessary for such a simple game? Is it probably too complicated? If not, would I need to do a lot of hard coding or am I misunderstanding the algorithm?

(2) Write your code using the pseudocode strategy from Wikipedia... I'm not exactly sure how to implement this. For example, it just says "check for forks". Would most of these checks be done by having an array of winningLines and checking if they'd be filled in or something like that? If not, can someone give me hints on what data structures or any basic tips on how to implement the checks posed in the pseudocode here: http://en.wikipedia.org/wiki/Tic-tac-toe#Strategy . I've also seen algorithms that give a numerical value to an 'X' square and an 'O' square and then use the sum to decide the winner but I don't see why this is particularly useful.

Any other reasonable solutions?

user1136342
  • 4,731
  • 10
  • 30
  • 40
  • 1
    For such a small game tree, just brute-force it. It would take no time at all to simulate every possible game. – Dave Apr 01 '13 at 23:22
  • 2
    doesn't seem flawless (always wins) = seems normal. i always win at tic tac toe. or at worst tie. any intelligent person will have this same result. that is why no one plays tic tac toe after the age of 10. it's no fun when no one wins. – nathan hayfield Apr 01 '13 at 23:23
  • Also yeah, "always win" isn't a valid requirement (ever). Just imagine your algorithm playing against itself. – Dave Apr 01 '13 at 23:23
  • Then you should probably edit your question. – Nick Mitchinson Apr 01 '13 at 23:29
  • Minimax does not have to be complicated, and pruning isn't really necessary for such a small game. See for example [this implementation](https://stackoverflow.com/questions/64882717/solving-tictactoe-with-minimax-algorithm-in-javascript/65417503#65417503) – trincot Dec 23 '20 at 00:31

2 Answers2

9

To be honest, when dealing with AI and heuristics, the most simple tasks can become complicated very quickly. The minimax approach is going to give you the best results and it shouldn't be too difficult considering the fact that you are implementing AI. It is an established standard with 2 player turn based gaming logic.

Check out this website... it gives some good insight into tic-tac-toe AI and the minimax implementation.

http://www.ntu.edu.sg/home/ehchua/programming/java/JavaGame_TicTacToe_AI.html

Edit:

Noticing that someone wrote "Brute Force"... this is going to end up being an inefficient way of the implementation of the heuristics involved in minimax. Iteration through every possible move based on the other players last move is just another way to implement a heuristic.. except it seems to be, in my opinion, more work. Minimax implementation will be simple and effective.

Edit2:

"Simpler implementation" is somewhat relative. Minimax is the standard and as I said in the comment you can manipulate the heuristic to suit the cases you are looking for...

I wish I could tell you the simplest way but there are so many variables dependent on the implantation of your game in code.

Take the suggestions, look at you game implementation, and then see what suits you best!

What is simple to one person might be complicated to another. I'm just trying to give you options and minimax is pretty solid. Maybe try adjusting it to fit your needs.

Edit3:

Let me know if you need more direction. I'm happy to help.

AnxGotta
  • 1,006
  • 7
  • 28
  • To be clear, are you saying that minimax actually ends up being *simpler* than checking all of the cases from the wikipedia entry, or are you saying that it's not much more complicated while also allowing for more efficient and elegant code? – user1136342 Apr 02 '13 at 00:47
  • I'm saying if you want dynamic play, use minimax. In the case of tic-tac-toe using the cases from the wiki you could hard code those options and follow them in a "brute force" way if you want. It would work fine and guarantee winning in certain cases. I was saying if you want a general heuristic to handle cases you could implement the minimax with your specific heuristic. You could include those "definite win" cases in the heuristic to insure they are covered and then fall back on more general selections if needed. I think a hybrid heuristic including both will serve you best. – AnxGotta Apr 02 '13 at 01:05
  • What do you mean by "guarantee winning in certain cases". Wouldn't it guarantee winning in all cases? – user1136342 Apr 02 '13 at 02:31
  • Yes. Sorry if I'm not being completely clear. Semantics... – AnxGotta Apr 02 '13 at 03:36
3

Use the format of your choice to "encode" this image into a set of moves. The AI will always win or tie.

For example, you could encode it as follows:

var turns = {
  "mefirst":{
    "move":0,
    "next":[
      null,
      {
        "move":4,
        "next":[
          null,
          null,
          {"move":8}, // win
          {"move":8}, // win
          null,
          {"move":8}, // win
          {"move":8}, // win
          {"move":8}, // win
          {
            "move":6,
            "next":[
              null,
              null,
       /* AND SO ON... */
    ]
  }
};

Then you can start with:

if( ai_goes_first) {
    game = turns.mefirst;
    makeMove(game.move);
}
else game = turns.themfirst;
playerTurn();

Where playerTurn is something like:

function playerTurn() {
    when player clicks a valid squeare {
        game = game.next[chosenSquare];
        makeMove(game.move);
        if( game.next) playerTurn();
    }
}
Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592