http://www.perlmonks.org?node_id=361817

I've been obsessing with Tic Tac Toe recently, with my post of a bot that plays best-defense against a human player. Along the way I bumped into this thread from 4 years ago, which shows a somewhat golfed and obfuscated script that plays two humans.

I posted my own entry, but wasn't satisfied with it. After some more tinkering and an epiphany or two, I came up with this, measuring in at 159 characters:

$_="123 456 789 147,258,369,159,357";$p=X;sub d{/.{12}/s;print$&.$p;die$_ for@_} n:d;$m=<>until$m=~/\d/&&s/$&/$p/g;/$p{3}/?d$p:!/\d/?d"Tie":$p=~y/XO/OX +/;goto n
The challenge: Create a script that follows the rules below, in as few characters as possible.

Rules:

  • Standard Tic Tac Toe rules must be followed (e.g., the board is 3x3, each square can be played only once, X and O alternate turns.)
  • A representation of the current game state (the board) must be displayed after each turn. This can take any form that is understandable. (Mine is the squares being numbered 1 through 9 and displayed on a 3x3 console grid)
  • An indicator of who's (X or O) turn it is must be displayed before each turn.
  • A mechanism to accept and validate input must be provided (e.g., it's X's turn until he picks a legal square).
  • A winning move must exit the game and display who won.
  • A "cat" game (tie) must exit and display "Tie" or "Cat" after the last square has been played.
  • Replies are listed 'Best First'.
    Re: (Golf) Tic Tac Toe
    by ambrus (Abbot) on Jun 06, 2004 at 22:08 UTC

      Just an idea. This may or may not help in the golf, but is good to know anyway.

      If you take this magic square:

      2 9 4 7 5 3 6 1 8
      and play tic-tac-toe on it, you have three in a row iff you have three different cells so that the sum of their three numbers is 15.

      Source of the idea:

      Csákány Béla, Diszkrét matematikai játékok.
      1998, Polygon, Szeged
      pp. 100-101

      Update: changed 1 in 1st row to 2. Thanks to jdhawke and also QM for noticing the typo.

      Update: this one does not check for valid moves so it's easy to cheat. Also, it does not detect ties yet.

      s;;294 753 618 ;;$f=(OX)x9;{print$_,$u=chop$f;$n=<>-Q;s;$n;$u;e;$$u&1<<15-$n&&die$u.$ +/;$$u|=$$u[0]<<$n;$$u[0]|=1<<$n;redo}
        should that square be:
        2 9 4 7 5 3 6 1 8
        Otherwise the first column and row only sums to 14. --JDHawke
        You have a typo I think:
        1 9 4 7 5 3 6 1 8
        1st column and major diagonal do not add to 15.

        -QM
        --
        Quantum Mechanics: The dreams stuff is made of

          Run this with an odd argument (like 3) to get a magic square :-)
          print"@{$_=++$_%@F+$p--%@F*@F+1for@F,$p;F} "for@F=0..~-pop
    Re: (Golf) Tic Tac Toe
    by belg4mit (Prior) on Jun 07, 2004 at 04:22 UTC
      If you relax some of the requirements the code below comes in at 147
      $_="123 456 789 147,258,369,159,357"; sub d{/.{12}/s;print$&.($p= $p?0:X);die$_ for@_}d; while(<>=~/\d/&&s/$&/$p/g){ /$p{3}/?d$p:!/\d/ ?d"Tie":d }
      The relaxation's are you automatically lose if you try to cheat :-P i.e; given invalid input UPDATE: this can be remdedied with a goto but that brings it up to 153. The output is a little jury-rigged. I use 0 instead of O to allow for some shaving. Also, instead of where you die $p, the loser dies in this game.

      UPDATE 2: 144

      $_="123 456 789 147,258,369,159,357"; sub d{/.{12}/s;print$&.( $p=$p?0:X);@_&&die@_}d; while(<>=~/\d/&&s/$&/$p/g){ /$p{3}/?d$p:!/\d/?d"Tie":d }

      I should mention, I really like the way you use $_. It takes a double-take or two to figure out what's going on but it's rather elegant.

      --
      I'm not belgian but I play one on TV.

    Re: (Golf) Tic Tac Toe
    by Anonymous Monk on Jun 07, 2004 at 16:05 UTC
      Before starting to think, let's just rewrite it to 139:
      s//123 456 789 z147,258,369,159,357/;$p=X;sub d{/z/;print$`.$p;@_&&die@_} {d;1until<>=~/\d/&&s/$&/$p/g;/$p{3}/?d$p:/\d/?$p^=v23:d Tie;redo}
        (parent node was me too, just forgot to log in)

        The sub isn't useful either. 124:

        s//123 456 789 z147,258,369,159,357/;$p=O;{/$p{3}/?die$p:/\d/?$p^=O^X:die Tie;/z/;pri +nt$`.$p;1until<>=~/\d/&&s/$&/$p/g;redo}
        update (shortcircuiting the self reply chain) Currently at 119:
        s//123 456 789 z147,258,369,159,357/;$p=O;{/z/;print$`,$p^=O^X;/(.)\1\1/?die$1:/\d/|| +die Tie;$?=<>until s/$?/$p/g;redo}
        And 118:
        s//123 456 789 z147,258,369,159,357/;{/z/;print$`,$p=$p^h?X:O;/(.)\1\1/?die$1:/\d/||d +ie Tie;$?=<>until s/$?/$p/g;redo}
        Followed by 113:
        s//123 456 789 z147,258,369,159,3570/;$?=/(.)\1\1/?die$1:/\d/?<>:die(Tie)while!s/$?/$ +p/g||print$`x/z/,$p=$p^h?X:O
        Sneakily add a space in the output to get 111:
        s//123 456 7890147,258,369,159,357/;$?=/(.)\1\1/?die$1:/\d/?<>:die(Tie)while!s/$? +/$:/g||print$`x/-/,$:=$:^h?X:O
          Forgot to do the final situation print in that 124, but now it prints the person whose turn is WAS.
          s//123 456 789 z147,258,369,159,357/;$p=O;{/z/;print$`.$p;/$p{3}/?die$p:/\d/?$p^=O^X: +die Tie;1until<>=~/\d/&&s/$&/$p/g;redo}
            Re^5:
            by Jasper (Chaplain) on Jun 17, 2004 at 16:22 UTC
          Great Hera!

          That's a work of art. Nice job.