#include <stdio.h>
#include <stdlib.h>

int b[3][3]; /* board. 0: blank; -1: computer; 1: human */

int check_winner()
{
	int i;
	for (i = 0; i < 3; i++) {
		if (b[i][0] && b[i][1] == b[i][0] && b[i][2] == b[i][0])
			return b[i][0];
		if (b[0][i] && b[1][i] == b[0][i] && b[2][i] == b[0][i])
			return b[0][i];
	}
	if (!b[1][1]) return 0;

	if (b[1][1] == b[0][0] && b[2][2] == b[0][0]) return b[0][0];
	if (b[1][1] == b[2][0] && b[0][2] == b[1][1]) return b[1][1];

	return 0;
}

void showboard()
{
	const char *t = "X O";
	int i, j;
	for (i = 0; i < 3; i++, putchar('\n'))
		for (j = 0; j < 3; j++)
			printf("%c ", t[ b[i][j] + 1 ]);
	printf("-----\n");
}

#define for_ij for (i = 0; i < 3; i++) for (j = 0; j < 3; j++)
int best_i, best_j;
int test_move(int val, int depth)
{
	int i, j, score;
	int best = -1, changed = 0;

	if ((score = check_winner())) return (score == val) ? 1 : -1;

	for_ij {
		if (b[i][j]) continue;

		changed = b[i][j] = val;
		score = -test_move(-val, depth + 1);
		b[i][j] = 0;

		if (score <= best) continue;
		if (!depth) {
			best_i = i;
			best_j = j;
		}
		best = score;
	}

	return changed ? best : 0;
}

const char* game(int user)
{
	int i, j, k, move, win = 0;
	for_ij b[i][j] = 0;

	printf("Board postions are numbered so:\n1 2 3\n4 5 6\n7 8 9\n");
	printf("You have O, I have X.\n\n");
	for (k = 0; k < 9; k++, user = !user) {
		while(user) {
			printf("your move: ");
			if (!scanf("%d", &move)) {
				scanf("%*s");
				continue;
			}
			if (--move < 0 || move >= 9) continue;
			if (b[i = move / 3][j = move % 3]) continue;

			b[i][j] = 1;
			break;
		}
		if (!user) {
			if (!k) { /* randomize if computer opens, less boring */
				best_i = rand() % 3;
				best_j = rand() % 3;
			} else
				test_move(-1, 0);

			b[best_i][best_j] = -1;
			printf("My move: %d\n", best_i * 3 + best_j + 1);
		}

		showboard();
		if ((win = check_winner()))
			return win == 1 ? "You win.\n\n": "I win.\n\n";
	}
	return "A draw.\n\n";
}

int main()
{
	int first = 0;
	while (1) printf("%s", game(first = !first));
	return 0;
}


# Project : Terminal control/Coloured text

load "consolecolors.ring"

forecolors = [CC_FG_BLACK,CC_FG_RED,CC_FG_GREEN,CC_FG_YELLOW,
                   CC_FG_BLUE,CC_FG_MAGENTA,CC_FG_CYAN,CC_FG_GRAY,CC_BG_WHITE]

for n = 1 to len(forecolors)
     forecolor = forecolors[n]
     cc_print(forecolor | CC_BG_WHITE, "Rosetta Code" + nl)
next


#!/usr/bin/ruby -w
require 'rubygems'
require 'colored'

print 'Colors are'.bold
print ' black'.black
print ' blue'.blue
print ' cyan'.cyan
print ' green'.green
print ' magenta'.magenta
print ' red'.red
print ' white '.white
print 'and'.underline, ' yellow'.yellow, "\n"
puts 'black on blue'.black_on_blue
puts 'black on cyan'.black_on_cyan
puts 'black on green'.black_on_green
puts 'black on magenta'.black_on_magenta
puts 'black on red'.black_on_red
puts 'white on black'.white_on_black
puts 'white on blue'.white_on_blue
puts 'white on cyan'.white_on_cyan
puts 'white on green'.white_on_green
puts 'white on magenta'.white_on_magenta
puts 'white on red'.white_on_red


object ColouredText extends App {
  val ESC = "\u001B"
  val (normal, bold, blink, black, white) =
    (ESC + "[0", ESC + "[1"
      , ESC + "[5" // not working on my machine
      , ESC + "[0;40m" // black background
      , ESC + "[0;37m" // normal white foreground
    )

  print(s"${ESC}c") // clear terminal first
  print(black) // set background color to black
  def foreColors = Map(
    ";31m" -> "red",
    ";32m" -> "green",
    ";33m" -> "yellow",
    ";34m" -> "blue",
    ";35m" -> "magenta",
    ";36m" -> "cyan",
    ";37m" -> "white")

  Seq(normal, bold, blink).flatMap(attr => foreColors.map(color => (attr, color)))
    .foreach { case (attr, (seq, text)) => println(s"$attr${seq}${text}") }
  println(white) // set foreground color to normal white
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RosettaTicTacToe
{
  class Program
  {

    /*================================================================
     *Pieces (players and board)
     *================================================================*/
    static string[][] Players = new string[][] {
      new string[] { "COMPUTER", "X" }, // computer player
      new string[] { "HUMAN", "O" }     // human player
    };

    const int Unplayed = -1;
    const int Computer = 0;
    const int Human = 1;

    // GameBoard holds index into Players[] (0 or 1) or Unplayed (-1) if location not yet taken
    static int[] GameBoard = new int[9];

    static int[] corners = new int[] { 0, 2, 6, 8 };

    static int[][] wins = new int[][] {
      new int[] { 0, 1, 2 }, new int[] { 3, 4, 5 }, new int[] { 6, 7, 8 },
      new int[] { 0, 3, 6 }, new int[] { 1, 4, 7 }, new int[] { 2, 5, 8 },
      new int[] { 0, 4, 8 }, new int[] { 2, 4, 6 } };

    /*================================================================
     *Main Game Loop (this is what runs/controls the game)
     *================================================================*/
    static void Main(string[] args)
    {
      while (true)
      {
        Console.Clear();
        Console.WriteLine("Welcome to Rosetta Code Tic-Tac-Toe for C#.");
        initializeGameBoard();
        displayGameBoard();
        int currentPlayer = rnd.Next(0, 2);  // current player represented by Players[] index of 0 or 1
        Console.WriteLine("The first move goes to {0} who is playing {1}s.\n", playerName(currentPlayer), playerToken(currentPlayer));
        while (true)
        {
          int thisMove = getMoveFor(currentPlayer);
          if (thisMove == Unplayed)
          {
            Console.WriteLine("{0}, you've quit the game ... am I that good?", playerName(currentPlayer));
            break;
          }
          playMove(thisMove, currentPlayer);
          displayGameBoard();
          if (isGameWon())
          {
            Console.WriteLine("{0} has won the game!", playerName(currentPlayer));
            break;
          }
          else if (isGameTied())
          {
            Console.WriteLine("Cat game ... we have a tie.");
            break;
          }
          currentPlayer = getNextPlayer(currentPlayer);
        }
        if (!playAgain())
          return;
      }
    }

    /*================================================================
     *Move Logic
     *================================================================*/
    static int getMoveFor(int player)
    {
      if (player == Human)
        return getManualMove(player);
      else
      {
        //int selectedMove = getManualMove(player);
        //int selectedMove = getRandomMove(player);
        int selectedMove = getSemiRandomMove(player);
        //int selectedMove = getBestMove(player);
        Console.WriteLine("{0} selects position {1}.", playerName(player), selectedMove + 1);
        return selectedMove;
      }
    }

    static int getManualMove(int player)
    {
      while (true)
      {
        Console.Write("{0}, enter you move (number): ", playerName(player));
        ConsoleKeyInfo keyInfo = Console.ReadKey();
        Console.WriteLine();  // keep the display pretty
        if (keyInfo.Key == ConsoleKey.Escape)
          return Unplayed;
        if (keyInfo.Key >= ConsoleKey.D1 && keyInfo.Key <= ConsoleKey.D9)
        {
          int move = keyInfo.KeyChar - '1';  // convert to between 0..8, a GameBoard index position.
          if (GameBoard[move] == Unplayed)
            return move;
          else
            Console.WriteLine("Spot {0} is already taken, please select again.", move + 1);
        }
        else
          Console.WriteLine("Illegal move, please select again.\n");
      }
    }

    static int getRandomMove(int player)
    {
      int movesLeft = GameBoard.Count(position => position == Unplayed);
      int x = rnd.Next(0, movesLeft);
      for (int i = 0; i < GameBoard.Length; i++)  // walk board ...
      {
        if (GameBoard[i] == Unplayed && x < 0)    // until we reach the unplayed move.
          return i;
        x--;
      }
      return Unplayed;
    }

    // plays random if no winning move or needed block.
    static int getSemiRandomMove(int player)
    {
      int posToPlay;
      if (checkForWinningMove(player, out posToPlay))
        return posToPlay;
      if (checkForBlockingMove(player, out posToPlay))
        return posToPlay;
      return getRandomMove(player);
    }

    // purposely not implemented (this is the thinking part).
    static int getBestMove(int player)
    {
      return -1;
    }

    static bool checkForWinningMove(int player, out int posToPlay)
    {
      posToPlay = Unplayed;
      foreach (var line in wins)
        if (twoOfThreeMatchPlayer(player, line, out posToPlay))
          return true;
      return false;
    }

    static bool checkForBlockingMove(int player, out int posToPlay)
    {
      posToPlay = Unplayed;
      foreach (var line in wins)
        if (twoOfThreeMatchPlayer(getNextPlayer(player), line, out posToPlay))
          return true;
      return false;
    }

    static bool twoOfThreeMatchPlayer(int player, int[] line, out int posToPlay)
    {
      int cnt = 0;
      posToPlay = int.MinValue;
      foreach (int pos in line)
      {
        if (GameBoard[pos] == player)
          cnt++;
        else if (GameBoard[pos] == Unplayed)
          posToPlay = pos;
      }
      return cnt == 2 && posToPlay >= 0;
    }

    static void playMove(int boardPosition, int player)
    {
      GameBoard[boardPosition] = player;
    }

    static bool isGameWon()
    {
      return wins.Any(line => takenBySamePlayer(line[0], line[1], line[2]));
    }

    static bool takenBySamePlayer(int a, int b, int c)
    {
      return GameBoard[a] != Unplayed && GameBoard[a] == GameBoard[b] && GameBoard[a] == GameBoard[c];
    }

    static bool isGameTied()
    {
      return !GameBoard.Any(spot => spot == Unplayed);
    }

    /*================================================================
     *Misc Methods
     *================================================================*/
    static Random rnd = new Random();

    static void initializeGameBoard()
    {
      for (int i = 0; i < GameBoard.Length; i++)
        GameBoard[i] = Unplayed;
    }

    static string playerName(int player)
    {
      return Players[player][0];
    }

    static string playerToken(int player)
    {
      return Players[player][1];
    }

    static int getNextPlayer(int player)
    {
      return (player + 1) % 2;
    }

    static void displayGameBoard()
    {
      Console.WriteLine(" {0} | {1} | {2}", pieceAt(0), pieceAt(1), pieceAt(2));
      Console.WriteLine("---|---|---");
      Console.WriteLine(" {0} | {1} | {2}", pieceAt(3), pieceAt(4), pieceAt(5));
      Console.WriteLine("---|---|---");
      Console.WriteLine(" {0} | {1} | {2}", pieceAt(6), pieceAt(7), pieceAt(8));
      Console.WriteLine();
    }

    static string pieceAt(int boardPosition)
    {
      if (GameBoard[boardPosition] == Unplayed)
        return (boardPosition + 1).ToString();  // display 1..9 on board rather than 0..8
      return playerToken(GameBoard[boardPosition]);
    }

    private static bool playAgain()
    {
      Console.WriteLine("\nDo you want to play again?");
      return Console.ReadKey(false).Key == ConsoleKey.Y;
    }
  }

}


var a = frequire('Term::ANSIColor');

say a.colored('RED ON WHITE', 'bold red on_white');
say a.colored('GREEN', 'bold green');
say a.colored('BLUE ON YELLOW', 'bold blue on_yellow');
say a.colored('MAGENTA', 'bold magenta');
say a.colored('CYAN ON RED', 'bold cyan on_red');
say a.colored('YELLOW', 'bold yellow');


# Utility interfaces to the low-level command
proc capability cap {expr {![catch {exec tput -S << $cap}]}}
proc colorterm {} {expr {[capability setaf] && [capability setab]}}
proc tput args {exec tput -S << $args >/dev/tty}
array set color {black 0 red 1 green 2 yellow 3 blue 4 magenta 5 cyan 6 white 7}
proc foreground x {exec tput -S << "setaf $::color($x)" > /dev/tty}
proc background x {exec tput -S << "setab $::color($x)" > /dev/tty}
proc reset {} {exec tput sgr0 > /dev/tty}

# Demonstration of use
if {[colorterm]} {
    foreground blue
    background yellow
    puts "Color output"
    reset
} else {
    puts "Monochrome only"
}

if {[capability blink]} {
    tput blink
    puts "Blinking output"
    reset
} else {
    puts "Steady only"
}


--color red
This is red
--color green
This is green
--color blue
This is blue
--color cyan
This is cyan
--color magenta
This is magenta
--color yellow
This is yellow


#include <windows.h>
#include <iostream>
#include <string>

//--------------------------------------------------------------------------------------------------
using namespace std;

//--------------------------------------------------------------------------------------------------
enum players { Computer, Human, Draw, None };
const int iWin[8][3] = { { 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }, { 0, 3, 6 }, { 1, 4, 7 }, { 2, 5, 8 }, { 0, 4, 8 }, { 2, 4, 6 } };

//--------------------------------------------------------------------------------------------------
class ttt
{
public:
    ttt() { _p = rand() % 2; reset(); }

    void play()
    {
	int res = Draw;
	while( true )
	{
	    drawGrid();
	    while( true )
	    {
		if( _p ) getHumanMove();
		else getComputerMove();

		drawGrid();

		res = checkVictory();
		if( res != None ) break;

		++_p %= 2;
	    }

	    if( res == Human ) cout << "CONGRATULATIONS HUMAN --- You won!";
	    else if( res == Computer ) cout << "NOT SO MUCH A SURPRISE --- I won!";
	    else cout << "It's a draw!";

	    cout << endl << endl;

	    string r;
	    cout << "Play again( Y / N )? "; cin >> r;
	    if( r != "Y" && r != "y" ) return;

	    ++_p %= 2;
	    reset();

	}
    }

private:
    void reset()
    {
	for( int x = 0; x < 9; x++ )
	    _field[x] = None;
    }

    void drawGrid()
    {
	system( "cls" );

        COORD c = { 0, 2 };
	SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );

	cout << " 1 | 2 | 3 " << endl;
	cout << "---+---+---" << endl;
	cout << " 4 | 5 | 6 " << endl;
	cout << "---+---+---" << endl;
	cout << " 7 | 8 | 9 " << endl << endl << endl;

	int f = 0;
	for( int y = 0; y < 5; y += 2 )
	    for( int x = 1; x < 11; x += 4 )
	    {
		if( _field[f] != None )
		{
		    COORD c = { x, 2 + y };
		    SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );
		    string o = _field[f] == Computer ? "X" : "O";
		    cout << o;
		}
		f++;
	    }

        c.Y = 9;
	SetConsoleCursorPosition( GetStdHandle( STD_OUTPUT_HANDLE ), c );
    }

    int checkVictory()
    {
	for( int i = 0; i < 8; i++ )
	{
	    if( _field[iWin[i][0]] != None &&
		_field[iWin[i][0]] == _field[iWin[i][1]] && _field[iWin[i][1]] == _field[iWin[i][2]] )
	    {
		return _field[iWin[i][0]];
	    }
	}

	int i = 0;
	for( int f = 0; f < 9; f++ )
	{
	    if( _field[f] != None )
		i++;
	}
	if( i == 9 ) return Draw;

	return None;
    }

    void getHumanMove()
    {
	int m;
	cout << "Enter your move ( 1 - 9 ) ";
	while( true )
	{
	    m = 0;
	    do
	    { cin >> m; }
	    while( m < 1 && m > 9 );

	    if( _field[m - 1] != None )
		cout << "Invalid move. Try again!" << endl;
	    else break;
	}

	_field[m - 1] = Human;
    }

    void getComputerMove()
    {
	int move = 0;

	do{ move = rand() % 9; }
	while( _field[move] != None );

	for( int i = 0; i < 8; i++ )
	{
	    int try1 = iWin[i][0], try2 = iWin[i][1], try3 = iWin[i][2];

	    if( _field[try1] != None && _field[try1] == _field[try2] && _field[try3] == None )
	    {
		move = try3;
		if( _field[try1] == Computer ) break;
	    }

	    if( _field[try1] != None && _field[try1] == _field[try3] && _field[try2] == None )
	    {
		move = try2;
		if( _field[try1] == Computer ) break;
	    }

	    if( _field[try2] != None && _field[try2] == _field[try3] && _field[try1] == None )
	    {
		move = try1;
		if( _field[try2] == Computer ) break;
	    }
        }
	_field[move] = Computer;

    }

int _p;
int _field[9];
};
//--------------------------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
    srand( GetTickCount() );

    ttt tic;
    tic.play();

    return 0;
}
//--------------------------------------------------------------------------------------------------


FOR n = 1 TO 15
  SET COLOR n
  PRINT "Rosetta Code"
NEXT n
END


#!/bin/sh
# Check if the terminal supports colour

# We should know from the TERM evironment variable whether the system
# is comfigured for a colour terminal or not, but we can also check the
# tput utility to check the terminal capability records.

COLORS=8    # Assume initially that the system supports eight colours
case $TERM in
  linux)
    ;;      # We know this is a colour terminal
  rxvt)
    ;;      # We know this is a colour terminal
  *)
    COLORS=`tput colors 2> /dev/null`    # Get the number of colours from the termcap file
esac
if [ -z $COLORS ] ; then
  COLORS=1    # Watch out for an empty returned value
fi

if [ $COLORS -le 2 ] ; then
  # The terminal is not colour
  echo "HW65000 This application requires a colour terminal" >&2
  exit 252    #ERLHW incompatible hardware
fi

# We know at this point that the terminal is colour

# Coloured text
tput setaf 1    #red
echo "Red"
tput setaf 4    #blue
echo "Blue"
tput setaf 3    # yellow
echo "Yellow"

# Blinking
tput setab 1    # red background
tput setaf 3    # yellow foreground
#tput blink     # enable blinking (but does not work on some terminals)
echo "Flashing text"

tput sgr0    # reset everything before exiting


import "timer" for Timer

var colors = ["Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"]

// display words using 'bright' colors
for (i in 1..7) System.print("\e[%(30+i);1m%(colors[i])") // red to white
Timer.sleep(3000)         // wait for 3 seconds
System.write("\e[47m")    // set background color to white
System.write("\e[2J")     // clear screen to background color
System.write("\e[H")      // home the cursor

// display words again using 'blinking' colors
System.write("\e[5m")     // blink on
for (i in 0..6) System.print("\e[%(30+i);1m%(colors[i])") // black to cyan
Timer.sleep(3000)         // wait for 3 more seconds
System.write("\e[0m")     // reset all attributes
System.write("\e[2J")     // clear screen to background color
System.write("\e[H")      // home the cursor


code ChOut=8, Attrib=69;
def Black, Blue, Green, Cyan, Red, Magenta, Brown, White,  \attribute colors
    Gray, LBlue, LGreen, LCyan, LRed, LMagenta, Yellow, BWhite; \EGA palette
[ChOut(6,^C);           \default white on black background
Attrib(Red<<4+White);   \white on red
ChOut(6,^o);
Attrib(Green<<4+Red);   \red on green
ChOut(6,^l);
Attrib(Blue<<4+LGreen); \light green on blue
ChOut(6,^o);
Attrib(LRed<<4+White);  \flashing white on (standard/dim) red
ChOut(6,^u);
Attrib(Cyan<<4+Black);  \black on cyan
ChOut(6,^r);
]


(defun generate-board ()
  (loop repeat 9 collect nil))

(defparameter *straights* '((1 2 3) (4 5 6) (7 8 9) (1 4 7) (2 5 8) (3 6 9) (1 5 9) (3 5 7)))
(defparameter *current-player* 'x)

(defun get-board-elt (n board)
  (nth (1- n) board))

(defun legal-p (n board)
  (null (get-board-elt n board)))

(defun set-board-elt (n board symbol)
  (if (legal-p n board)
      (setf (nth (1- n) board) symbol)
      (progn (format t "Illegal move. Try again.~&")
	     (set-board-elt (read) board symbol))))

(defun list-legal-moves (board)
  (loop for i from 1 to (length board)
     when (legal-p i board)
     collect i))

(defun get-random-element (lst)
  (nth (random (length lst)) lst))

(defun multi-non-nil-eq (lst)
  (and (notany #'null lst)
       (notany #'null (mapcar #'(lambda (x) (eq (car lst) x)) lst))
       (car lst)))

(defun elements-of-straights (board)
  (loop for i in *straights*
     collect (loop for j from 0 to 2
	   collect (get-board-elt (nth j i) board))))

(defun find-winner (board)
  (car (remove-if #'null (mapcar #'multi-non-nil-eq (elements-of-straights board)))))

(defun set-player (mark)
  (format t "Shall a computer play as ~a? (y/n)~&" mark)
  (let ((response (read)))
    (cond ((equalp response 'y) t)
	  ((equalp response 'n) nil)
	  (t (format t "Come again?~&")
	     (set-player mark)))))

(defun player-move (board symbol)
  (format t "~%Player ~a, please input your move.~&" symbol)
  (set-board-elt (read) board symbol)
  (format t "~%"))

(defun computer-move (board symbol)
  (let ((move (get-random-element (list-legal-moves board))))
    (set-board-elt move board symbol)
    (format t "~%computer selects ~a~%~%" move)))

(defun computer-move-p (current-player autoplay-x-p autoplay-o-p)
  (if (eq current-player 'x)
      autoplay-x-p
      autoplay-o-p))

(defun perform-turn (current-player board autoplay-x-p autoplay-o-p)
  (if (computer-move-p current-player autoplay-x-p autoplay-o-p)
      (computer-move board current-player)
      (player-move board current-player)))

(defun switch-player ()
  (if (eq *current-player* 'x)
      (setf *current-player* 'o)
      (setf *current-player* 'x)))

(defun display-board (board)
  (loop for i downfrom 2 to 0
     do (loop for j from 1 to 3
	   initially (format t "|")
	   do (format t "~a|" (or (get-board-elt (+ (* 3 i) j) board) (+ (* 3 i) j)))
	   finally (format t "~&"))))

(defun tic-tac-toe ()
  (setf *current-player* 'x)
  (let ((board (generate-board))
	(autoplay-x-p (set-player 'x))
	(autoplay-o-p (set-player 'o)))
    (format t "~%")
    (loop until (or (find-winner board) (null (list-legal-moves board)))
       do (display-board board)
       do (perform-turn *current-player* board autoplay-x-p autoplay-o-p)
       do (switch-player)
       finally (if (find-winner board)
		   (format t "The winner is ~a!" (find-winner board))
		   (format t "It's a tie.")))))


fcn table(title,mode){
   println("\n\e[1m%s\e[m\n bg\t fg".fmt(title));
   foreach b in ([40..48].chain([100..107])){
      print("%3d\t\e[%s%dm".fmt(b,mode,b));
      foreach f in ([30..38].chain([90..97])){ print("\e[%dm%3d ".fmt(f,f)) }
      println("\e[m");
   }
}

table("normal ( ESC[22m or ESC[m )", 		"22;");
table("bold ( ESC[1m )",			"1;");
table("faint ( ESC[2m ), not well supported",	"2;");
table("italic ( ESC[3m ), not well supported",	"3;");
table("underline ( ESC[4m ), support varies",	"4;");
table("blink ( ESC[5m )",			"5;");
table("inverted ( ESC[7m )",			"7;");


10 FOR l=0 TO 7
20 READ c$: REM get our text for display
30 INK l: REM set the text colour
40 PRINT c$
50 NEXT l
60 PAPER 2: REM red background
70 INK 6: REM yellow forground
80 FLASH 1: REM activate flashing
90 PRINT "Flashing!": REM this will flash red and yellow (alternating inverse)
100 PAPER 7: INK 0: FLASH 0: REM normalize colours before exit
110 STOP

900 DATA "Black","Blue","Red","Magenta","Green","Cyan","Yellow","White"


import std.stdio, std.string, std.algorithm, std.conv, std.random,
       std.ascii, std.array, std.range, std.math;

struct GameBoard {
    dchar[9] board = "123456789";
    enum : dchar { human = 'X', computer = 'O' }
    enum Game { going, humanWins, computerWins, draw }

    const pure nothrow @safe @nogc invariant() {
        int nHuman = 0, nComputer = 0;
        foreach (immutable i, immutable c; board)
            if (c.isDigit)
                assert(i == c - '1'); // In correct position?
            else {
                assert(c == human || c == computer);
                (c == human ? nHuman : nComputer)++;
            }
        assert(abs(nHuman - nComputer) <= 1);
    }

    string toString() const pure {
        return format("%(%-(%s|%)\n-+-+-\n%)", board[].chunks(3));
    }

    bool isAvailable(in int i) const pure nothrow @safe @nogc {
        return i >= 0 && i < 9 && board[i].isDigit;
    }

    auto availablePositions() const pure nothrow @safe /*@nogc*/ {
        return 9.iota.filter!(i => isAvailable(i));
    }

    Game winner() const pure nothrow @safe /*@nogc*/ {
        static immutable wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8],
                                 [0, 3, 6], [1, 4, 7], [2, 5, 8],
                                 [0, 4, 8], [2, 4, 6]];

        foreach (immutable win; wins) {
            immutable bw0 = board[win[0]];
            if (bw0.isDigit)
                continue; // Nobody wins on this one.

            if (bw0 == board[win[1]] && bw0 == board[win[2]])
                return bw0 == GameBoard.human ?
                              Game.humanWins :
                              Game.computerWins;
        }

        return availablePositions.empty ? Game.draw: Game.going;
    }

    bool isFinished() const pure nothrow @safe /*@nogc*/ {
        return winner != Game.going;
    }

    int computerMove() const // Random move.
    out(res) {
        assert(res >= 0 && res < 9 && isAvailable(res));
    } body {
        // return availablePositions.array.choice;
        return availablePositions.array[uniform(0, $)];
    }
}

GameBoard playGame() {
    GameBoard board;
    bool playsHuman = true;

    while (!board.isFinished) {
        board.writeln;

        int move;
        if (playsHuman) {
            do {
                writef("Your move (available moves: %s)? ",
                       board.availablePositions.map!q{ a + 1 });
                readf("%d\n", &move);
                move--; // Zero based indexing.
                if (move < 0)
                    return board;
            } while (!board.isAvailable(move));
        } else
            move = board.computerMove;

        assert(board.isAvailable(move));
        writefln("\n%s chose %d", playsHuman ? "You" : "I", move + 1);
        board.board[move] = playsHuman ? GameBoard.human :
                                         GameBoard.computer;
        playsHuman = !playsHuman; // Switch player.
    }

    return board;
}

void main() {
    "Tic-tac-toe game player.\n".writeln;
    immutable outcome = playGame.winner;

    final switch (outcome) {
        case GameBoard.Game.going:
            "Game stopped.".writeln;
            break;
        case GameBoard.Game.humanWins:
            "\nYou win!".writeln;
            break;
        case GameBoard.Game.computerWins:
            "\nI win.".writeln;
            break;
        case GameBoard.Game.draw:
            "\nDraw".writeln;
            break;
    }
}


len f[] 9
state = 0
textsize 14
#
func init . .
  linewidth 2
  clear
  color 666
  move 34 4
  line 34 80
  move 62 4
  line 62 80
  move 10 28
  line 86 28
  move 10 56
  line 86 56
  linewidth 2.5
  for i range 9
    f[i] = 0
  .
  if state = 1
    timer 0.2
  .
.
func draw ind . .
  c = ind mod 3
  r = ind div 3
  x = c * 28 + 20
  y = r * 28 + 14
  if f[ind] = 4
    color 900
    move x - 7 y - 7
    line x + 7 y + 7
    move x + 7 y - 7
    line x - 7 y + 7
  elif f[ind] = 1
    color 009
    move x y
    circle 10
    color -2
    circle 7.5
  .
.
func sum3 a d . st .
  for i range 3
    s += f[a]
    a += d
  .
  if s = 3
    st = -1
  elif s = 12
    st = 1
  .
.
func rate . res done .
  res = 0
  for i range 3
    call sum3 i * 3 1 res
  .
  for i range 3
    call sum3 i 3 res
  .
  call sum3 0 4 res
  call sum3 2 2 res
  cnt = 1
  for i range 9
    if f[i] = 0
      cnt += 1
    .
  .
  res *= cnt
  done = 1
  if res = 0 and cnt > 1
    done = 0
  .
.
func minmax player alpha beta . rval rmov .
  call rate rval done
  if done = 1
    if player = 1
      rval = -rval
    .
  else
    rval = alpha
    start = random 9
    mov = start
    repeat
      if f[mov] = 0
        f[mov] = player
        call minmax (5 - player) (-beta) (-rval) val h
        val = -val
        f[mov] = 0
        if val > rval
          rval = val
          rmov = mov
        .
      .
      mov = (mov + 1) mod 9
      until mov = start or rval >= beta
    .
  .
.
func show_result val . .
  color 555
  move 16 84
  if val < 0
    # this never happens
    text "You won"
  elif val > 0
    text "You lost"
  else
    text "Tie"
  .
  state += 2
.
func computer . .
  call minmax 4 -11 11 val mov
  f[mov] = 4
  call draw mov
  call rate val done
  state = 0
  if done = 1
    call show_result val
  .
.
func human . .
  mov = floor ((mouse_x - 6) / 28) + 3 * floor (mouse_y / 28)
  if f[mov] = 0
    f[mov] = 1
    call draw mov
    state = 1
    timer 0.5
  .
.
on timer
  call rate val done
  if done = 1
    call show_result val
  else
    call computer
  .
.
on mouse_down
  if state = 0
    if mouse_x > 6 and mouse_x < 90 and mouse_y < 84
      call human
    .
  elif state >= 2
    state -= 2
    call init
  .
.
call init


-module(tic_tac_toe).

-export( [task/0] ).

task() -> io:fwrite( "Result: ~p.~n", [turn(player(random:uniform()), board())] ).

board() -> [{X, erlang:integer_to_list(X)} || X <- lists:seq(1, 9)].

board_tuples( Selections, Board ) -> [lists:keyfind(X, 1, Board) || X <- Selections].

computer_move( Player, Board ) ->
	[N | _T] = lists:flatten( [X(Player, Board) || X <- [fun computer_move_win/2, fun computer_move_block/2, fun computer_move_middle/2, fun computer_move_random/2]] ),
	N.

computer_move_block( Player, Board ) ->	computer_move_two_same_player( player(false, Player), Board ).

computer_move_middle( _Player, Board ) ->
	{5, Y} = lists:keyfind( 5, 1, Board ),
	computer_move_middle( is_empty(Y) ).

computer_move_middle( true ) -> [5];
computer_move_middle( false ) -> [].

computer_move_random( _Player, Board ) ->
	Ns = [X || {X, Y} <- Board, is_empty(Y)],
	[lists:nth( random:uniform(erlang:length(Ns)), Ns )].

computer_move_two_same_player( Player, Board ) ->
        Selections = [X || X <- three_in_row_all(), is_two_same_player(Player, X, Board)],
	computer_move_two_same_player( Player, Board, Selections ).

computer_move_two_same_player( _Player, _Board, [] ) -> [];
computer_move_two_same_player( _Player, Board, [Selection | _T] ) -> [X || {X, Y} <- board_tuples(Selection, Board), is_empty(Y)].

computer_move_win( Player, Board ) -> computer_move_two_same_player( Player, Board ).

is_empty( Square ) -> Square =< "9". % Do not use < "10".

is_finished( Board ) -> is_full( Board ) orelse is_three_in_row( Board ).

is_full( Board ) -> [] =:= [X || {X, Y} <- Board, is_empty(Y)].

is_three_in_row( Board ) ->
	Fun = fun(Selections) -> is_three_in_row_same_player( board_tuples(Selections, Board) ) end,
	lists:any( Fun, three_in_row_all() ).

is_three_in_row_same_player( Selected ) -> three_in_row_player( Selected ) =/= no_player.

is_two_same_player( Player, Selections, Board ) -> is_two_same_player( Player, [{X, Y} || {X, Y} <- board_tuples(Selections, Board), not is_empty(Y)] ).

is_two_same_player( Player, [{_X, Player}, {_Y, Player}] ) -> true;
is_two_same_player( _Player, _Selected ) -> false.

player( Random ) when Random > 0.5 -> "O";
player( _Random ) -> "X".

player( true, _Player ) -> finished;
player( false, "X" ) -> "O";
player( false, "O" ) -> "X".

result( Board ) -> result( is_full(Board), Board ).

result( true, _Board ) -> draw;
result( false, Board ) ->
	[Winners] = [Selections || Selections <- three_in_row_all(), three_in_row_player(board_tuples(Selections, Board)) =/= no_player],
	"Winner is " ++ three_in_row_player( board_tuples(Winners, Board) ).

three_in_row_all() -> three_in_row_horisontal() ++ three_in_row_vertical() ++ three_in_row_diagonal().
three_in_row_diagonal() -> [[1,5,9], [3,5,7]].
three_in_row_horisontal() -> [[1,2,3], [4,5,6], [7,8,9]].
three_in_row_vertical() -> [[1,4,7], [2,5,8], [3,6,9]].

three_in_row_player( [{_X, Player}, {_Y, Player}, {_Z, Player}] ) -> three_in_row_player( not is_empty(Player), Player );
three_in_row_player( _Selected ) -> no_player.

three_in_row_player( true, Player ) -> Player;
three_in_row_player( false, _Player ) -> no_player.

turn( finished, Board ) -> result( Board );
turn( "X"=Player, Board ) ->
    N = computer_move( Player, Board ),
    io:fwrite( "Computer, ~p, selected ~p~n", [Player, N] ),
    New_board = [{N, Player} | lists:keydelete(N, 1, Board)],
    turn( player(is_finished(New_board), Player), New_board );
turn( "O"=Player, Board ) ->
    [turn_board_write_horisontal(X, Board) || X <- three_in_row_horisontal()],
    Ns = [X || {X, Y} <- Board, is_empty(Y)],
    Prompt = lists:flatten( io_lib:format("Player, ~p, select one of ~p: ", [Player, Ns]) ),
    N = turn_next_move( Prompt, Ns ),
    New_board = [{N, Player} | lists:keydelete(N, 1, Board)],
    turn( player(is_finished(New_board), Player), New_board ).

turn_board_write_horisontal( Selections, Board ) ->
	Tuples = [lists:keyfind(X, 1, Board) || X <- Selections],
	[io:fwrite( "~p ", [Y]) || {_X, Y} <- Tuples],
	io:fwrite( "~n" ).

turn_next_move( Prompt, Ns ) ->
	{ok,[N]} = io:fread( Prompt, "~d" ),
	turn_next_move_ok( lists:member(N, Ns), Prompt, Ns, N ).

turn_next_move_ok( true, _Prompt, _Ns, N ) -> N;
turn_next_move_ok( false, Prompt, Ns, _N ) -> turn_next_move( Prompt, Ns ).


!--------------------------------------------
! TRIS.R : gioca a tris contro l'operatore
!--------------------------------------------

PROGRAM TRIS

DIM TRIS%[9],T1%[9],PIECES$[3]

!$SEGMENT=$B800

!$INCLUDE="PC.LIB"

PROCEDURE DELAY(COUNT%)
  FOR Z%=1 TO COUNT DO
  END FOR
END PROCEDURE

PROCEDURE SET_BOARD
!
! Disegna lo schema del gioco
!
  CLS
  BLOAD("TRIS.BLD",0)
!$KEY
END PROCEDURE

PROCEDURE PUT_PIECES
!
! Pone i pezzi sulla scacchiera
!
  Z%=0
  FOR ROW%=6 TO 12 STEP 3 DO     ! posizioni assolute sullo schermo
    FOR COL%=32 TO 48 STEP 8 DO
      LOCATE(ROW%+1,COL%+1)
      Z%=Z%+1
      PRINT(PIECES$[TRIS%[Z%]])
    END FOR
  END FOR
END PROCEDURE

PROCEDURE COMPUTE_MOVE(A%)
  CASE A% OF
    2-> C1%=C1%+1            END ->
    4-> C2%=C2%+1            END ->
    8-> S1%=TRUE  S2%=TRUE   END ->
    3-> N1%=N1%+1            END ->
    9-> N2%=N2%+1            END ->
   27-> S1%=FALSE S2%=FALSE  END ->
 END CASE
END PROCEDURE

PROCEDURE PREPAREMOVE(T1%[],I%->M%)
!
! Prepara la mossa del calcolatore
!
   T1%[I%]=2
   C1%=0
   C2%=0
   N1%=0
   N2%=0
   FOR K%=0 TO 2 DO
     COMPUTE_MOVE(T1%[3*K%+1]*T1%[3*K%+2]*T1%[3*K%+3])
     COMPUTE_MOVE(T1%[K%+1]*T1%[K%+4]*T1%[K%+7])
   END FOR
   COMPUTE_MOVE(T1%[1]*T1%[5]*T1%[9])
   COMPUTE_MOVE(T1%[3]*T1%[5]*T1%[7])
   M%=-63*N2%+31*C2%-15*N1%+7*C1%
END PROCEDURE

PROCEDURE COMPUTER_MOVE
!
! Coordina le mosse del calcolatore
!
  MAXSCORE%=-1000
  FOR I%=1 TO 9 DO
    IF TRIS%[I%]=1
      THEN
       PREPAREMOVE(TRIS%[],I%->MV%)
       EXIT IF S2% AND NOT S1%
       IF S1% AND S2%
         THEN
          TRIS%[I%]=2
          DIARY$=DIARY$+"c"+MID$(STR$(I%),2)+"*"
          PUT_PIECES
          EXIT
       END IF
       IF MV%=0
         THEN
          MOVE%=I%
          EXIT
       END IF
       IF MV%>MAXSCORE%
         THEN
          MOVE%=I%
          MAXSCORE%=MV%
       END IF
    END IF
  END FOR
  IF NOT S2%
    THEN
     TRIS%[MOVE%]=2
     DIARY$=DIARY$+"c"+MID$(STR$(MOVE%),2)+";"
     PUT_PIECES
     NMOVE%=NMOVE%-1
     S1%=(NMOVE%=0)
  END IF
END PROCEDURE

PROCEDURE PLAYER_MOVE
!
! Gioca l'avversario umano usando i tasti cursore per lo spostamento
!
  LOCATE(19,13)
  PRINT("Tocca a te ....                  ")
  REPEAT
    ROW%=7
    COL%=32
    LOCATE(ROW%+1,COL%+1)
    PRINT("Ü")
    REPEAT
      GET(B$)
      IF LEN(B$)=2 THEN
        CASE ASC(RIGHT$(B$,1)+CHR$(0)) OF
          77-> ! codice tastiera per CRSR =>
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             COL%=-(COL%+8)*(COL%<=40)-32*(COL%>40)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          75-> ! codice tastiera per CRSR <=
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             COL%=-(COL%-8)*(COL%>=40)-48*(COL%<40)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          80-> ! codice tastiera per CRSR DOWN
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             ROW%=-(ROW%+3)*(ROW%<=10)-7*(ROW%>10)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
          72-> ! codice tastiera per CRSR UP
             LOCATE(ROW%+1,COL%+1)
             PRINT(" ")
             ROW%=-(ROW%-3)*(ROW%>=10)-13*(ROW%<10)
             LOCATE(ROW%+1,COL%+1)
             PRINT("Ü")
          END ->
       END CASE
      END IF
     UNTIL B$=CHR$(13)
     MM%=ROW%+COL%/8-10 ! da coordinate schermo a coordinate scacchiera
   UNTIL TRIS%[MM%]=1
  TRIS%[MM%]=3
  LOCATE(ROW%+1,COL%+1)
  PRINT(" ")
  DIARY$=DIARY$+"p"+MID$(STR$(MM%),2)+";"
  PUT_PIECES
  NMOVE%=NMOVE%-1
  S1%=(NMOVE%=0)
  LOCATE(19,13)
  PRINT(STRING$(45," "))
END PROCEDURE

BEGIN
  DATA(" ","+","o")
  SET_BOARD
  REPEAT
    S1%=FALSE    S2%=FALSE   ! determinano lo stato della partita
    NMOVE%=9
    FOR Z%=1 TO 3 DO
       READ(PIECES$[Z%])
    END FOR
    FOR Z%=1 TO 9 DO
        TRIS%[Z%]=1
    END FOR
    LOCATE(19,13)
    PRINT("Giochi per primo ?")
    REPEAT
      GET(A$)
    UNTIL A$="S" OR A$="s" OR A$="N" OR A$="n"
    PUT_PIECES
    FOR INDICE%=1 TO 9 DO
      IF A$="s" OR A$="S"
        THEN
          PLAYER_MOVE
          EXIT IF S1% OR S2%
          COMPUTER_MOVE
          EXIT IF S1% OR S2%
        ELSE
          COMPUTER_MOVE
          EXIT IF S1% OR S2%
          PLAYER_MOVE
          EXIT IF S1% OR S2%
      END IF
   END FOR
   LOCATE(19,13)
   CASE TRUE OF
     (S1% AND NOT S2%)->
        PRINT("E' finita pari !!!     ")
     END ->
     (S2% AND NOT S1%)->
        PRINT("HAI VINTO !!!          ")
     END ->
     (S1% AND S2%)->
        PRINT("HO VINTO IO !!!        ")
     END ->
   END CASE
   DELAY(500)
   LOCATE(19,13)
   PRINT(DIARY$)
   DELAY(500)
   LOCATE(19,13)
   PRINT("Vuoi giocare ancora ?       ")
   REPEAT
     GET(A$)
   UNTIL A$="S" OR A$="s" OR A$="N" OR A$="n"
 UNTIL A$="N" OR A$="n"
END PROGRAM


include std/console.e
include std/text.e
include std/search.e
include std/sequence.e

sequence board
sequence players = {"X","O"}

function DisplayBoard()
	for i = 1 to 3 do
		for j = 1 to 3 do
			printf(1,"%s",board[i][j])
			if j < 3 then
				printf(1,"%s","|")
			end if
		end for
		if i < 3 then
			puts(1,"\n-----\n")
		else
			puts(1,"\n\n")
		end if
	end for

	return 1
end function

function CheckWinner()
sequence temp = board
	for a = 1 to 2 do
		for i = 1 to 3 do
			if equal({"X","X","X"},temp[i]) then
				puts(1,"X wins\n\n")
				return 1
			elsif equal({"O","O","O"},temp[i]) then
				puts(1,"O wins\n\n")
				return 1
			end if
		end for
		temp = columnize(board)
	end for
	if equal({"X","X","X"},{board[1][1],board[2][2],board[3][3]}) or
	   equal({"X","X","X"},{board[1][3],board[2][2],board[3][1]}) then
		puts(1,"X wins\n")
		return 1
	elsif equal({"O","O","O"},{board[1][1],board[2][2],board[3][3]}) or
	   equal({"O","O","O"},{board[1][3],board[2][2],board[3][1]}) then
		puts(1,"O wins\n")
		return 1
	end if

	if moves = 9 then
		puts(1,"Draw\n\n")
		return 1
	end if

	return 0
end function

integer turn, row, column, moves
sequence replay
while 1 do
	board = repeat(repeat(" ",3),3)
	DisplayBoard()
	turn = rand(2)
	moves = 0

	while 1 do
		while 1 do
			printf(1,"%s's turn\n",players[turn])
			row = prompt_number("Enter row: ",{})
			column = prompt_number("Enter column: ",{})
			if match(board[row][column]," ") then
				board[row][column] = players[turn]
				moves += 1
				exit
			else
				puts(1,"Space already taken - pick again\n")
			end if
		end while

		DisplayBoard()

		if CheckWinner() then
			exit
		end if

		if turn = 1 then
			turn = 2
		else
			turn = 1
		end if
	end while

	replay = lower(prompt_string("Play again (y/n)?\n\n"))

	if match(replay,"n") then
		exit
	end if

end while


type Brick =
 | Empty
 | Computer
 | User

let brickToString = function
 | Empty -> ' '
 | Computer -> 'X'
 | User -> 'O'

// y -> x -> Brick
type Board = Map<int, Map<int, Brick> >

let emptyBoard =
  let emptyRow = Map.ofList [0,Empty; 1,Empty; 2,Empty]
  Map.ofList [0,emptyRow; 1,emptyRow; 2,emptyRow]

let get (b:Board) (x,y) = b.[y].[x]

let set player (b:Board) (x,y) : Board =
  let row = b.[y].Add(x, player)
  b.Add(y, row)

let winningPositions =
  [for x in [0..2] -> x,x] // first diagonal
  ::[for x in [0..2] -> 2-x,x] // second diagonal
  ::[for y in [0..2] do
     yield! [[for x in [0..2]->(y,x)]; // columns
             [for x in [0..2] -> (x,y)]]] // rows

let hasWon player board =
  List.exists
    (fun ps -> List.forall (fun pos -> get board pos = player) ps)
    winningPositions

let freeSpace board =
  [for x in 0..2 do
     for y in 0..2 do
       if get board (x,y) = Empty then yield x,y]

type Evaluation =
 | Win
 | Draw
 | Lose

let rec evaluate board move =
  let b2 = set Computer board move
  if hasWon Computer b2 then Win
  else
    match freeSpace b2 with
    | [] -> Draw
    | userChoices ->
       let b3s = List.map (set User b2) userChoices
       if List.exists (hasWon User) b3s then Lose
       elif List.exists (fun b3 -> bestOutcome b3 = Lose) b3s
       then Lose
       elif List.exists (fun b3 -> bestOutcome b3 = Draw) b3s
       then Draw
       else Win

and findBestChoice b =
  match freeSpace b with
  | [] -> ((-1,-1), Draw)
  | choices ->
    match List.tryFind (fun c -> evaluate b c = Win) choices with
    | Some c -> (c, Win)
    | None -> match List.tryFind (fun c -> evaluate b c = Draw) choices with
              | Some c -> (c, Draw)
              | None -> (List.head choices, Lose)

and bestOutcome b = snd (findBestChoice b)

let bestChoice b = fst (findBestChoice b)

let computerPlay b = set Computer b (bestChoice b)

let printBoard b =
  printfn "   | A | B | C |"
  printfn "---+---+---+---+"
  for y in 0..2 do
   printfn " %d | %c | %c | %c |"
    (3-y)
    (get b (0,y) |> brickToString)
    (get b (1,y) |> brickToString)
    (get b (2,y) |> brickToString)
   printfn "---+---+---+---+"

let rec userPlay b =
  printfn "Which field do you play? (format: a1)"
  let input = System.Console.ReadLine()
  if input.Length <> 2
     || input.[0] < 'a' || input.[0] > 'c'
     || input.[1] < '1' || input.[1] > '3' then
     printfn "illegal input"
     userPlay b
  else
     let x = int(input.[0]) - int('a')
     let y = 2 - int(input.[1]) + int('1')
     if get b (x,y) <> Empty then
       printfn "Field is not free."
       userPlay b
     else
       set User b (x,y)

let rec gameLoop b player =
  if freeSpace b = [] then
    printfn "Game over. Draw."
  elif player = Computer then
    printfn "Computer plays..."
    let b2 = computerPlay b
    printBoard b2
    if hasWon Computer b2 then
      printfn "Game over. I have won."
    else
      gameLoop b2 User
  elif player = User then
    let b2 = userPlay b
    printBoard b2
    if hasWon User b2 then
      printfn "Game over. You have won."
    else
      gameLoop b2 Computer

// randomly choose an element of a list
let choose =
  let rnd = new System.Random()
  fun (xs:_ list) -> xs.[rnd.Next(xs.Length)]

// play first brick randomly
printfn "Computer starts."
let b = set Computer emptyBoard (choose (freeSpace emptyBoard))
printBoard b
gameLoop b User


create board 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,

\ board: 0=empty, 1=player X, 2=player O
: player. ( player -- ) C"  XO" 1+ + @ emit ;
: spot ( n -- addr ) cells board + ;
: clean-board ( -- ) 9 0 do 0 i spot ! loop ;

: show-board
  CR ." +---+---+---+  +---+---+---+" CR
  3 0 do
    ." | "
    3 0 do
      i j 3 * + spot @ player. ."  | "
    loop
    ."  | "
    3 0 do
      i j 3 * + . ." | "
    loop
    CR ." +---+---+---+  +---+---+---+" CR
  loop ;

: spots-equal ( n1 n2 n3 -- f )
  over   spot @ swap spot @   = >r   spot @ swap spot @   =   r>   and ;
: spots-win ( n1 n2 n3 -- f )
  dup >r spots-equal r> spot @ 0<> and ;

: winner-check ( -- player )
  0 1 2 spots-win if 0 spot @ exit then
  3 4 5 spots-win if 3 spot @ exit then
  6 7 8 spots-win if 6 spot @ exit then
  0 3 6 spots-win if 0 spot @ exit then
  1 4 7 spots-win if 1 spot @ exit then
  2 5 8 spots-win if 2 spot @ exit then
  0 4 8 spots-win if 0 spot @ exit then
  2 4 6 spots-win if 2 spot @ exit then
  0 ;

: player-move ( player -- )
  begin
    key dup emit [char] 0 - dup
    spot @ 0= if spot ! exit else drop then
  again ;

: game
  clean-board show-board
  9 0 do
    i 2 mod 1+ dup ." Player " player. ." : "
    player-move show-board
    winner-check dup 0<> if player. ."  wins !" unloop exit else drop then
  loop
  ." Draw!" ;

game


! This is a fortran95 implementation of the game of tic-tac-toe.
! - Objective was to use less than 100 lines.
! - No attention has been devoted to efficiency.
! - Indentation by findent: https://sourceforge.net/projects/findent/
! - This is free software, use as you like at own risk.
! - Compile: gfortran -o tictactoe tictactoe.f90
! - Run: ./tictactoe
! Comments to: wvermin at gmail dot com
module tic
   implicit none
   integer :: b(9)
contains
   logical function iswin(p)
      integer,intent(in) :: p
      iswin = &
         all(b([1,2,3])==p).or.all(b([4,5,6])==p).or.all(b([7,8,9])==p).or.&
         all(b([1,4,7])==p).or.all(b([2,5,8])==p).or.all(b([3,6,9])==p).or.&
         all(b([1,5,9])==p).or.all(b([3,5,7])==p)
   end function iswin
   subroutine printb(mes)
      character(len=*) :: mes
      integer          :: i,j
      character        :: s(0:2) = ['.','X','O']
      print "(3a3,'   ',3i3)",(s(b(3*i+1:3*i+3)),(j,j=3*i+1,3*i+3),i=0,2)
      if(mes /= ' ') print "(/,a)",mes
   end subroutine printb
   integer recursive function minmax(player,bestm) result(bestv)
      integer :: player,bestm,move,v,bm,win=1000,inf=100000
      real    :: x
      if (all(b .ne. 0)) then
         bestv = 0
      else
         bestv = -inf
         do move=1,9
            if (b(move) == 0) then
               b(move) = player
               if (iswin(player)) then
                  v = win
               else
                  call random_number(x)
                  v = -minmax(3-player,bm) - int(10*x)
               endif
               if (v > bestv) then
                  bestv = v
                  bestm = move
               endif
               b(move) = 0
               if (v == win) exit
            endif
         enddo
      endif
   end function minmax
end module tic
program tictactoe
   ! computer: player=1, user: player=2
   use tic
   implicit none
   integer :: move,ios,v,bestmove,ply,player=2,k,values(8)
   integer,allocatable :: seed(:)
   call date_and_time(values=values)
   call random_seed(size=k)
   allocate(seed(k))
   seed = values(8)+1000*values(7)+60*1000*values(6)+60*60*1000*values(5)
   call random_seed(put=seed)
   mainloop: do
      b = 0
      call printb('You have O, I have X. You enter 0: game ends.')
      plyloop: do ply=0,4
         if (player == 2 .or. ply >0 ) then  ! user move
            write(*,"(/,a)",advance='no'),'Your move? (0..9) '
            getloop: do
               readloop: do
                  read (*,*,iostat=ios),move
                  if (ios == 0 .and. move  >= 0 .and. move <= 9) exit readloop
                  write(*,"(a)",advance='no'),'huh? Try again (0..9): '
               enddo readloop
               if (  move  == 0) exit mainloop
               if (b(move) == 0) exit getloop
               write(*,"(a)",advance='no'),'Already occupied, again (0..9): '
            enddo getloop
            b(move) = 2
            if(iswin(2)) then   ! this should not happen
               call printb('***** You win *****')
               exit plyloop
            endif
         endif
         v = minmax(1,bestmove)   ! computer move
         b(bestmove) = 1
         if(iswin(1)) then
            call printb('***** I win *****')
            exit plyloop
         endif
         write(*,"(/,a,i3)"), 'My move: ',bestmove
         call printb(' ')
      enddo plyloop
      if(ply == 5) write(*,"('***** Draw *****',/)")
      player = 3-player
   enddo mainloop
end program


'About 400 lines of code, but it is a graphical (GUI ish) i.e. mouse driven.
'I have made provision for the player to beat the computer now and then.

Type box
    As long x,y
    As long wide,high,index
    Dim As ulong colour
    As String caption
    Declare Sub show
    Declare Sub NewCaption(s As String)
    Declare Constructor
    Declare Constructor(x As long,y As long,wide As long,_
    high As long,index As long,colour As ulong,caption As String)
End Type
Constructor box
End Constructor
Constructor box(x As long,y As long,wide As long,_
high As long,index As long,colour As ulong,caption As String)
this.x=x
this.y=y
this.wide=wide
this.high=high
this.index=index
this.colour=colour
this.caption=caption
End Constructor
'ALL PROCEDURES:
Declare Function inside(B As box,px As long,py As long) As long
Declare Sub make_frame_image(im As ulong Pointer)
Declare Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
Declare Function all_clicked(b() As box) As long
Declare Sub OnCLICK(a() As box,b As box)
Declare Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
Declare Function Get_Mouse_Events(boxes() As box) As long
Declare Sub thickline(x1 As long,y1 As long,x2 As long,y2 As long,thickness As Single,colour As ulong,im As Any Pointer=0)
Declare Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
Declare Sub startup(b() As box)
Declare Sub get_computer_events(b() As box)

Declare Sub finish
'Macro used by more than one procedure
#macro incircle(cx,cy,radius,x,y)
(cx-x)*(cx-x) +(cy-y)*(cy-y)<= radius*radius
#endmacro
'===============  RUN  ============================
Screen 19,32',1,16
Color ,Rgb(233,236,216)              'background colour
windowtitle string(100," ")+"Noughts and crosses"
'Globals:
Dim Shared As ulong Pointer frame
Dim Shared As long computer,player
Dim Shared As String msg1,msg2,message
message="In Play"
msg1="Computer Start"
msg2="Player Start"
'Custom Frame
frame=Imagecreate(800,600)

Dim  As box boxes(0 To 9)

setup_grid(boxes(),3,3,175,85,150,150)
make_frame_image(frame)

Do
    If player=0 And computer=0 Then
        startup(boxes())
    End If

    If player  Then
        Get_Mouse_Events(boxes())
    End If

    If computer Then
        get_computer_events(boxes())
    End If

    If all_clicked(boxes()) Then get_computer_events(boxes())
Loop Until Inkey=Chr(27)
finish

Sub box.show
    Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),this.colour,bf
    Line(this.x,this.y)-(this.x+this.wide,this.y+this.high),Rgb(200,200,200),b
    ''Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+(.5*this.high-4)),this.caption,Rgb(0,0,0)
    If this.index=0 Then
        Draw String(this.x+.5*this.wide-4*Len(this.caption),this.y+.5*this.high-6),this.caption,Rgb(0,0,0)
    End If
End Sub
Sub box.NewCaption(s As String)
    Var cx=(this.x+this.x+this.wide)/2
    Var cy=(this.y+this.y+this.high)/2
    If s="X" Then
        For k As long=20 To 0 Step -1
            lineto(cx,cy,this.x,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
            lineto(cx,cy,this.x+this.wide,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
            lineto(cx,cy,this.x,this.y+this.high,50,k,Rgb(50+10*k,5*k,0),frame)
            lineto(cx,cy,this.x+this.wide,this.y,50,k,Rgb(50+10*k,5*k,0),frame)
        Next k
    Else
        For k As long=20 To 0 Step -1
            thickcircle(cx,cy,40,k,Rgb(50+10*k,5*k,0),frame)
        Next k
    End If
End Sub
Sub get_computer_events(b() As box)
    #define other(n)  b(n).caption<>"0" And b(n).caption<>"C"
    #define another(n) b(n).caption="0"
    #define rr(f,l) (Rnd*((l)-(f))+(f))
    Dim As long flag,i,k,Cwin,Pwin,NoWin
    Static As long firstclick
    var chance="001100"
    dim as long ch
    'horiz player finish
    For x As long=1 To 3
        If b(1+k).caption="0" And b(2+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
        If b(2+k).caption="0" And b(3+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1=1:Goto fin
        If b(1+k).caption="0" And b(3+k).caption="0" And another((2+k))Then b(2+k).Caption="0":Pwin=1:Goto fin
        k=k+3
    Next x
    k=0
    'vert player finish
    For x As long=1 To 3
        If b(1+k).caption="0" And b(4+k).caption="0" And another((7+k)) Then b(7+k).Caption="0":Pwin=1:Goto fin
        If b(4+k).caption="0" And b(7+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
        If b(1+k).caption="0" And b(7+k).caption="0" And another((4+k))Then b(4+k).Caption="0":Pwin=1:Goto fin
        k=k+1
    Next x
    k=0
    'player finish main diag
    If b(1+k).caption="0" And b(5+k).caption="0" And another((9+k)) Then b(9+k).Caption="0":Pwin=1:Goto fin
    If b(1+k).caption="0" And b(9+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin
    If b(5+k).caption="0" And b(9+k).caption="0" And another((1+k))Then b(1+k).Caption="0":Pwin=1:Goto fin
    'player finish other diag
    If b(7+k).caption="0" And b(5+k).caption="0" And another((3+k)) Then b(3+k).Caption="0":Pwin=1:Goto fin
    If b(5+k).caption="0" And b(3+k).caption="0" And another((7+k))Then b(7+k).Caption="0":Pwin=1:Goto fin
    If b(7+k).caption="0" And b(3+k).caption="0" And another((5+k))Then b(5+k).Caption="0":Pwin=1:Goto fin

    'horiz computer finish
    For x As long=1 To 3
        If b(1+k).caption="C" And b(2+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
        If b(2+k).caption="C" And b(3+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
        If b(1+k).caption="C" And b(3+k).caption="C" And other((2+k))Then b(2+k).Caption="C":Cwin=1:Goto fin
        k=k+3
    Next x
    k=0
    'vert computer finish
    For x As long=1 To 3
        If b(1+k).caption="C" And b(4+k).caption="C" And other((7+k)) Then b(7+k).Caption="C":Cwin=1:Goto fin
        If b(4+k).caption="C" And b(7+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
        If b(1+k).caption="C" And b(7+k).caption="C" And other((4+k))Then b(4+k).Caption="C":Cwin=1:Goto fin
        k=k+1
    Next x
    k=0
    'computer finish main diag
    If b(1+k).caption="C" And b(5+k).caption="C" And other((9+k)) Then b(9+k).Caption="C":Cwin=1:Goto fin
    If b(1+k).caption="C" And b(9+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin
    If b(5+k).caption="C" And b(9+k).caption="C" And other((1+k))Then b(1+k).Caption="C":Cwin=1:Goto fin
    'computer finish other diag
    If b(7+k).caption="C" And b(5+k).caption="C" And other((3+k)) Then b(3+k).Caption="C":Cwin=1:Goto fin
    If b(5+k).caption="C" And b(3+k).caption="C" And other((7+k))Then b(7+k).Caption="C":Cwin=1:Goto fin
    If b(7+k).caption="C" And b(3+k).caption="C" And other((5+k))Then b(5+k).Caption="C":Cwin=1:Goto fin

    'block horizontals
    For x As long=1 To 3
        If b(1+k).caption="0" And b(2+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
        If b(2+k).caption="0" And b(3+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
        If b(1+k).caption="0" And b(3+k).caption="0" And other((2+k))Then b(2+k).Caption="C":flag=1:Goto fin
        k=k+3
    Next x
    k=0
    'block verticals
    For x As long=1 To 3
        If b(1+k).caption="0" And b(4+k).caption="0" And other((7+k)) Then b(7+k).Caption="C":flag=1:Goto fin
        If b(4+k).caption="0" And b(7+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
        If b(1+k).caption="0" And b(7+k).caption="0" And other((4+k))Then b(4+k).Caption="C":flag=1:Goto fin
        k=k+1
    Next x
    k=0
    'block main diag
    If b(1+k).caption="0" And b(5+k).caption="0" And other((9+k)) Then b(9+k).Caption="C":flag=1:Goto fin
    If b(1+k).caption="0" And b(9+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin
    If b(5+k).caption="0" And b(9+k).caption="0" And other((1+k))Then b(1+k).Caption="C":flag=1:Goto fin
    'block other diag
    If b(7+k).caption="0" And b(5+k).caption="0" And other((3+k)) Then b(3+k).Caption="C":flag=1:Goto fin
    If b(5+k).caption="0" And b(3+k).caption="0" And other((7+k))Then b(7+k).Caption="C":flag=1:Goto fin
    If b(7+k).caption="0" And b(3+k).caption="0" And other((5+k))Then b(5+k).Caption="C":flag=1:Goto fin

    If firstclick=0 Then
        firstclick=1
       var st="1379"
       dim as long i=rr(0,3)
    If Valint(b(5).caption)=0  and b(5).caption <> "C" Then b(st[i]-48).caption="C":Goto fin

    End If

     ch=rr(0,5)
    if chance[ch]-48=1 then
    If Valint(b(5).caption)<>0 Then b(5).caption="C":Goto fin
    end if
    If all_clicked(b()) Then Nowin=1:Goto fin
    If flag=0 Then
        Randomize
        Do
            i=rr(1,9)
            If Valint(b(i).caption) <> 0  Then b(i).caption="C":Exit Do
        Loop
    End If
    fin:
    If Cwin=1 Or Pwin=1 Or NoWin=1 Then
        Dim As long mx,my,mb
        dim as integer x,y
        screencontrol 0,x,y
        for z as single=0 to 8*atn(1) step .001
            dim as integer xx=x+100*cos(z)
            dim as integer yy=y+100*sin(z)
            screencontrol 100,xx,yy
        next z
        screencontrol 100,x,y
        If Cwin=1 Then Message="You Loose"
        If Pwin=1 Then Message="You WIN"
        If Nowin=1 Then Message="DRAW"

        cwin=0:k=0:pWin=0:Nowin=0:firstclick=0'i
        Do
            Getmouse mx,my,,mb
            If inside(b(0),mx,my) And mb=1 Then finish

            Var ic=incircle(500,55,20,mx,my)
            If incircle(500,55,20,mx,my) And mb=1 Then Exit Do
            refresh_screen(b(),ic)
        Loop Until Inkey=chr(27)
        For z As long=1 To Ubound(b)
            b(z).caption=Str(b(z).index)
        Next z
        Imagedestroy frame
        frame=Imagecreate(800,600)
        make_frame_image(frame)
        computer=0:player=0
        Exit Sub
    End If
    player=1:computer=0
End Sub

Sub startup(b() As box)
    message="In Play"
    Dim As long mx,my,mb
    Getmouse mx,my,,mb

    For n As long=0 To Ubound(b)
        If inside(b(n),mx,my) And mb=1 Then
            If b(n).index=0 Then
                finish
            End If
        End If
        b(0).colour=Rgb(200,0,0)
    Next n
    Dim As long f1,f2
    If incircle(80,230,10,mx,my) Then
        f1=1:f2=0
        If mb=1 Then computer=1:player=0
    End If
    If incircle(670,230,10,mx,my) Then
        f1=0:f2=1
        If mb=1 Then player=1:computer=0
    End If
    refresh_screen(b(),f1,f2)
End Sub
Sub thickcircle(x As long,y As long,rad As long,th As Single,col As ulong,im As Any Pointer=0)
    Circle(x,y),rad+th/2,col
    Circle(x,y),rad-th/2,col
    Paint(x,y+rad),col,col
End Sub

Sub thickline(x1 As long,_
    y1 As long,_
    x2 As long,_
    y2 As long,_
    thickness As Single,_
    colour As ulong,_
    im As Any Pointer=0)
    Dim p As ulong=Rgb(255, 255, 255)
    If thickness<2 Then
        Line(x1,y1)-(x2,y2),colour
    Else
        Dim As Double s,h,c
        h=Sqr((x2-x1)^2+(y2-y1)^2)
        If h=0 Then h=1e-6
        s=(y1-y2)/h
        c=(x2-x1)/h
        For x As long=1 To 2
            Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x2+s*thickness/2,y2+c*thickness/2),p
            Line im,(x1-s*thickness/2,y1-c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
            Line im,(x1+s*thickness/2,y1+c*thickness/2)-(x1-s*thickness/2,y1-c*thickness/2),p
            Line im,(x2+s*thickness/2,y2+c*thickness/2)-(x2-s*thickness/2,y2-c*thickness/2),p
            Paint im,((x1+x2)/2, (y1+y2)/2), p, p
            p=colour
        Next x
    End If
End Sub
Sub lineto(x1 As long,y1 As long,x2 As long,y2 As long,l As long,th As Single,col As ulong,im As Any Pointer=0)
    Dim As long diffx=x2-x1,diffy=y2-y1,ln=Sqr(diffx*diffx+diffy*diffy)
    Dim As Single nx=diffx/ln,ny=diffy/ln
    thickline(x1,y1,(x1+l*nx),(y1+l*ny),th,col,im)
End Sub

Function inside(B As box,px As long,py As long) As long
    Return (px>B.x)*(px<(B.x+B.wide))*(py>B.y)*(py<(B.y+B.high))
End Function
Sub make_frame_image(im As ulong Pointer)
    #macro map(a,b,x,d,c)
    ((d)-(c))*((x)-(a))/((b)-(a))+(c)
    #endmacro
    #macro logo(sx,sy,rad)
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx,sy),rad+k,Rgb(15,118,155):Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+1.3*rad,sy+rad),rad+k,Rgb(230,193,78),2.,1.7:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+2*1.3*rad,sy),rad+k,Rgb(21,3,0),3.25,3.05:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+3*1.3*rad,sy+rad),rad+k,Rgb(26,143,76),2,1.8:Next
For k As Single=-rad/10 To rad/10 Step .5:Circle im,(sx+4*1.3*rad,sy),rad+k,Rgb(200,63,87),3.25,3.05:Next
#endmacro
    For k As long=0 To 50
        Var r=map(0,50,k,233,193-20)
        Var g=map(0,50,k,236,153-20)
        Var b=map(0,50,k,216,19-19)
        Line im,(0+k,20+k)-(800-k,600-k),Rgb(r,g,b),b
    Next k
    For k As long=0 To 20
        Var r=map(0,20,k,250,0)
        Var g=map(0,20,k,250,0)
        Var b=map(0,20,k,250,255)
        Line im,(0,k)-(780,k),Rgb(r,g,b)',bf
    Next k
    logo(60,8,5)
    logo(380,8,5)
    logo(720,8,5)
End Sub
Sub setup_grid(boxes() As box,cellsacross As long,cellsdown As long,xp As long,yp As long,w As long,h As long)
    Dim As long index
    For y As long=yp To yp+h*(cellsdown-1) Step h
        For x As long=xp To xp+w*(cellsacross-1)   Step w
            index=index+1
            boxes(index)=Type<box>(x,y,w,h,index,Rgb(133,136,116),Str(index))
        Next x
    Next y
    boxes(0)=Type<box>(780,-2,20,24,0,Rgb(200,0,0),"X")
End Sub

Function all_clicked(b() As box) As long
    Dim As long sum
    For z As long=1 To Ubound(b)
        sum=sum+Valint(b(z).caption)
    Next z
    If sum<=0 Then Return -1
End Function

Sub OnCLICK(a() As box,b As box)
    If b.caption="0" Then Exit Sub
    If b.caption="C" Then Exit Sub
    If b.caption <> "C" Then b.caption="0"
    If b.index=0 Then finish
    player=0:computer=1
End Sub

Sub refresh_screen(b() As box,f1 As long=0,f2 As long=0)
    Screenlock:Cls
    For n As long=0 To Ubound(b)
        b(n).show 'draw boxes
        If b(n).caption="0" Then b(n).NewCaption("X")
        If b(n).caption="C" Then b(n).NewCaption("O")
    Next n
    Put(0,0),frame,trans
    Draw String (390,50),message,Rgb(0,0,0)
    If message <>"In Play" Then
        Circle(500,55),20,Rgb(255,20,255),,,,f
        If f1=-1 Then Circle(500,55),20,Rgb(202,200,200),,,,f
        Draw String(480,50),"Click",Rgb(0,0,0)
    End If
    If computer=0 And player=0 Then
        Draw String (60,200),msg1,Rgb(0,0,0)
        Circle(80,230),10,Rgb(0,0,0)
        Circle(80,230),5,Rgb(100,100,100),,,,f
        If f1=1 Then Circle(80,230),10,Rgb(200,0,0),,,,f
        Draw String (650,200),msg2,Rgb(0,0,0)
        Circle(670,230),10,Rgb(0,0,0)
        Circle(670,230),5,Rgb(100,100,100),,,,f
        If f2=1 Then Circle(670,230),10,Rgb(200,0,0),,,,f
    End If
    Screenunlock:Sleep 1,1
End Sub

Function Get_Mouse_Events(boxes() As box) As long
    Static released As long
    Static pressed As long
    Dim As long mousex,mousey,mousebutton ,x,y
    Getmouse mousex,mousey,,mousebutton
    Dim As box bar=Type<box>(0,0,780,50,0,0,"")

    refresh_screen(boxes())
    For n As long=0 To Ubound(boxes)
        If inside(boxes(n),mousex,mousey)  Then
            If released Then
                boxes(n).colour=Rgb(120,123,103)
                If n=0 Then boxes(0).colour=Rgb(255,0,0)
            End If
            If mousebutton=1 Then
                If released Then OnCLICK(boxes(),boxes(n))
                Exit For
            End If
        Else
            boxes(n).colour=Rgb(133,136,116)
            If n=0 Then boxes(0).colour=Rgb(200,0,0)
        End If
    Next n
    If mousebutton=0 Then released=1 Else released=0 'clean clicks
    Return 0
End Function
Sub finish
    Screenunlock
    Imagedestroy frame
    End
End Sub


package main

import (
    "bufio"
    "fmt"
    "math/rand"
    "os"
    "strings"
)

var b []byte

func printBoard() {
    fmt.Printf("%s\n%s\n%s\n", b[0:3], b[3:6], b[6:9])
}

var pScore, cScore int
var pMark, cMark byte = 'X', 'O'
var in = bufio.NewReader(os.Stdin)

func main() {
    b = make([]byte, 9)
    fmt.Println("Play by entering a digit.")
    for {
        // start of game
        for i := range b {
            b[i] = '1' + byte(i)
        }
        computerStart := cMark == 'X'
        if computerStart {
            fmt.Println("I go first, playing X's")
        } else {
            fmt.Println("You go first, playing X's")
        }
    TakeTurns:
        for {
            if !computerStart {
                if !playerTurn() {
                    return
                }
                if gameOver() {
                    break TakeTurns
                }

            }
            computerStart = false
            computerTurn()
            if gameOver() {
                break TakeTurns
            }
        }
        fmt.Println("Score: you", pScore, "me", cScore)
        fmt.Println("\nLet's play again.")
    }
}

func playerTurn() bool {
    var pm string
    var err error
    for i := 0; i < 3; i++ { // retry loop
        printBoard()
        fmt.Printf("%c's move? ", pMark)
        if pm, err = in.ReadString('\n'); err != nil {
            fmt.Println(err)
            return false
        }
        pm = strings.TrimSpace(pm)
        if pm >= "1" && pm <= "9" && b[pm[0]-'1'] == pm[0] {
            x := pm[0] - '1'
            b[x] = pMark
            return true
        }
    }
    fmt.Println("You're not playing right.")
    return false
}

var choices = make([]int, 9)

func computerTurn() {
    printBoard()
    var x int
    defer func() {
        fmt.Println("My move:", x+1)
        b[x] = cMark
    }()
    // look for two in a row
    block := -1
    for _, l := range lines {
        var mine, yours int
        x = -1
        for _, sq := range l {
            switch b[sq] {
            case cMark:
                mine++
            case pMark:
                yours++
            default:
                x = sq
            }
        }
        if mine == 2 && x >= 0 {
            return // strategy 1: make winning move
        }
        if yours == 2 && x >= 0 {
            block = x
        }
    }
    if block >= 0 {
        x = block // strategy 2: make blocking move
        return
    }
    // default strategy: random move
    choices = choices[:0]
    for i, sq := range b {
        if sq == '1'+byte(i) {
            choices = append(choices, i)
        }
    }
    x = choices[rand.Intn(len(choices))]
}

func gameOver() bool {
    // check for win
    for _, l := range lines {
        if b[l[0]] == b[l[1]] && b[l[1]] == b[l[2]] {
            printBoard()
            if b[l[0]] == cMark {
                fmt.Println("I win!")
                cScore++
                pMark, cMark = 'X', 'O'
            } else {
                fmt.Println("You win!")
                pScore++
                pMark, cMark = 'O', 'X'
            }
            return true
        }
    }
    // check for empty squares
    for i, sq := range b {
        if sq == '1'+byte(i) {
            return false
        }
    }
    fmt.Println("Cat game.")
    pMark, cMark = cMark, pMark
    return true
}

var lines = [][]int{
    {0, 1, 2}, // rows
    {3, 4, 5},
    {6, 7, 8},
    {0, 3, 6}, // columns
    {1, 4, 7},
    {2, 5, 8},
    {0, 4, 8}, // diagonals
    {2, 4, 6},
}


class Main {

	def input = new Scanner(System.in)

	static main(args) {
		Main main = new Main();
		main.play();
	}

	public void play() {

		TicTackToe game = new TicTackToe();
		game.init()
		def gameOver = false
		def player = game.player1

		println "Players take turns marking a square. Only squares \n"+
				"not already marked can be picked. Once a player has \n"+
    			"marked three squares in a row, column or diagonal, they win! If all squares \n"+
    			"are marked and no three squares are the same, a tied game is declared.\n"+
				"Player 1 is O and Player 2 is X \n"+
    			"Have Fun! \n\n"
		println "${game.drawBoard()}"

		while (!gameOver && game.plays < 9) {

			player = game.currentPlayer == 1 ? game.player1 :game.player2
			def validPick = false;
			while (!validPick) {

				def square
				println "Next $player, enter move by selecting square's number :"
				try {
					square = input.nextLine();
				} catch (Exception ex) { }

				if (square.length() == 1 && Character.isDigit(square.toCharArray()[0])) {	validPick = game.placeMarker(square)	}
				if (!validPick) {	println "Select another Square"	}

			}

			(game.checkWinner(player))?	gameOver = true	: game.switchPlayers()
			println(game.drawBoard());

		}
		println "Game Over, " + ((gameOver == true)? "$player Wins" : "Draw")
	}

}

public class TicTackToe {

    def board = new Object[3][3]
	def final player1 = "player 1"
	def final player2 = "player 2"
	def final marker1 = 'X'
	def final marker2 = 'O'

    int currentPlayer
	int plays

	public TicTacToe(){

	}

    def init() {
        int counter = 0;
       (0..2).each { row ->
           (0..2).each { col ->
                board[row][col] = (++counter).toString();
            }
        }
	   plays = 0
	   currentPlayer =1
    }

    def switchPlayers() {
        currentPlayer = (currentPlayer == 1) ? 2:1
        plays++
    }

    def placeMarker(play) {
		def result = false
        (0..2).each { row ->
            (0..2).each { col ->
                if (board[row][col].toString()==play.toString()){
                    board[row][col] = (currentPlayer == 1) ? marker2 : marker1;
                    result =  true;
                }
            }
        }
        return result;
    }

    def checkWinner(player) {
    	char current = (player == player1)? marker2:  marker1
        //Checking
        return checkRows(current) || checkColumns(current) ||checkDiagonals(current);
    }

    def checkRows(char current){
		(0..2).any{ line ->
			  board[line].every { it == current}
		}
    }

    def checkColumns(char current){
		(0..2).any{i ->
			(0..2).every{j ->
				 board[j][i]==current }
		}
    }

    def checkDiagonals(char current){
		def rightDiag = [board[0][0],board[1][1],board[2][2]]
		def leftDiag =  [board[0][2],board[1][1],board[2][0]]
		return rightDiag.every{it == current} || leftDiag.every{it == current}
    }

    def drawBoard() {
        StringBuilder builder = new StringBuilder("Game board: \n");
        (0..2).each { row->
            (0..2).each {col ->
                builder.append("[" + board[row][col] + "]");
            }
            builder.append("\n");
        }
        builder.append("\n");
        return builder.toString();
    }
}


module Main where

import System.Random
import Data.List (intercalate, find, minimumBy)
import System.Environment (getArgs)
import Data.Char (digitToInt)
import Data.Maybe (listToMaybe, mapMaybe)
import Control.Monad (guard)
import Data.Ord (comparing)

-- check if there is a horizontal, vertical or diagonal line of
-- X or O
tictactoe :: String -> Bool
tictactoe a = tictactoeFor 'X' a /= tictactoeFor 'O' a

-- check if there is a horizontal, vertical or diagonal line
-- for the given player "n"
tictactoeFor :: Char -> String -> Bool
tictactoeFor n [a,b,c,d,e,f,g,h,i] =
    [n,n,n] `elem` [[a,b,c],[d,e,f],[g,h,i],[a,d,g],
                    [b,e,h],[c,f,i],[a,e,i],[c,e,g]]

-- empty game board
start :: String
start = "         "

-- check if there is an X or an O at the given position
isPossible :: Int -> String -> Bool
isPossible n game = (game !! n) `notElem` "XO"

-- try to place an X or an O at a given position.
-- "Right" + modified board means success, "Left" + unmodified board
-- means failure
place :: Int -> Char -> String -> Either String String
place i c game =
    if isPossible i game
    then Right $ take i game ++ [c] ++ drop (i + 1) game
    else Left game

-- COMPUTER AI
-- get the number of movements, starting from a given non-empty board
-- and a position for the next movement, until the specified player
-- wins or no movement is possible
-- the positions are chosen sequentially, so there's not much
-- intelligence here anyway
developGame :: Bool -> Int -> Int -> Char -> String -> (Int, Char, String)
developGame iterateMore moves i player game
    | i > 8 =
        -- if i arrives to the last position, iterate again from 0
        -- but do it only once
        if iterateMore
        then developGame False moves 0 player game
        -- draw game (after one iteration, still no winning moves)
        else (moves, player, game)
        -- draw game (game board full) or a win for the player
    | moves == 9 || tictactoeFor player game = (moves, player, game)
        -- make a move, if possible, and continue playing
    | otherwise = case place i otherPlayer game of
        -- position i is not empty. try with the next position
        Left _ -> developGame iterateMore moves (i + 1)
                    otherPlayer game
        -- position i was empty, so it was a valid move.
        -- change the player and make a new move, starting at pos 0
        Right newGame -> developGame iterateMore (moves + 1) 0
                    otherPlayer newGame
        where
            otherPlayer = changePlayer player

-- COMPUTER AI
-- starting from a given non-empty board, try to guess which position
-- could lead the player to the fastest victory.
bestMoveFor :: Char -> String -> Int
bestMoveFor player game = bestMove
    where
        -- drive the game to its end for each starting position
        continuations = [ (x, developGame True 0 x player game) |
            x <- [0..8] ]
        -- compare the number of moves of the game and take the
        -- shortest one
        move (_, (m, _, _)) = m
        (bestMove, _) = minimumBy (comparing move) continuations

-- canBlock checks if the opponent has two pieces in a row and the
-- other cell in the row is empty, and places the player's piece there,
-- blocking the opponent
canBlock :: Char -> String -> Maybe Int
canBlock p [a,b,c,d,e,f,g,h,i] =
    listToMaybe $ mapMaybe blockable [[a,b,c],[d,e,f],[g,h,i],[a,d,g],
                                      [b,e,h],[c,f,i],[a,e,i],[c,e,g]]
    where
        blockable xs = do
          guard $ length (filter (== otherPlayer) xs) == 2
          x <- find (`elem` "123456789") xs
          return $ digitToInt x
        otherPlayer = changePlayer p

-- format a game board for on-screen printing
showGame :: String -> String
showGame [a,b,c,d,e,f,g,h,i] =
    topBottom ++
    "|    | 1 | 2 | 3 |\n" ++
    topBottom ++
    row "0" [[a],[b],[c]] ++
    row "3" [[d],[e],[f]] ++
    row "6" [[g],[h],[i]]
    where
        topBottom = "+----+---+---+---+\n"
        row n x = "| " ++ n ++ "+ | " ++
            intercalate " | " x ++ " |\n" ++ topBottom

-- ask the user to press a numeric key and convert it to an int
enterNumber :: IO Int
enterNumber = do
    c <- getChar
    if c `elem` "123456789"
    then do
        putStrLn ""
        return $ digitToInt c
    else do
        putStrLn "\nPlease enter a digit!"
        enterNumber

-- a human player's turn: get the number of pieces put on the board,
-- the next piece to be put (X or O) and a game board, and return
-- a new game state, checking if the piece can be placed on the board.
-- if it can't, make the user try again.
turn :: (Int, Char, String) -> IO (Int, Char, String)
turn (count, player, game) = do
    putStr $ "Please tell me where you want to put an " ++
        [player] ++ ": "
    pos <- enterNumber
    case place (pos - 1) player game of
        Left oldGame -> do
            putStrLn "That place is already taken!\n"
            turn (count, player, oldGame)
        Right newGame ->
            return (count + 1, changePlayer player, newGame)

-- alternate between X and O players
changePlayer :: Char -> Char
changePlayer 'O' = 'X'
changePlayer 'X' = 'O'

-- COMPUTER AI
-- make an automatic turn, placing an X or an O game board.
-- the first movement is always random.
-- first, the computer looks for two pieces of his opponent in a row
-- and tries to block.
-- otherwise, it tries to guess the best position for the next movement.
-- as a last resort, it places a piece randomly.
autoTurn :: Bool -> (Int, Char, String) -> IO (Int, Char, String)
autoTurn forceRandom (count, player, game) = do
    -- try a random position 'cause everything else failed
    -- count == 0 overrides the value of forceRandom
    i <- if count == 0 || forceRandom
            then randomRIO (0,8)
            else return $
                case canBlock player game of
                    -- opponent can't be blocked. try to guess
                    -- the best movement
                    Nothing -> bestMoveFor player game
                    -- opponent can be blocked, so just do it!
                    Just blockPos -> blockPos
    -- if trying to place a piece at a calculated position doesn't work,
    -- just try again with a random value
    case place i player game of
        Left oldGame -> autoTurn True (count, player, oldGame)
        Right newGame -> do
            putStrLn $ "It's player " ++ [player] ++ "'s turn."
            return (count + 1, changePlayer player, newGame)

-- play a game until someone wins or the board becomes full.
-- depending on the value of the variable "auto", ask the user(s) to
-- put some pieces on the board or do it automatically
play :: Int -> (Int, Char, String) -> IO ()
play auto cpg@(_, player, game) = do
    newcpg@(newCount, newPlayer, newGame) <- case auto of
        -- if both players are human, always ask them
        0 -> turn cpg
        -- if both players are computer, always play auto
        1 -> autoTurn False cpg
        -- X is computer, O is human
        2 -> if player == 'X' then autoTurn False cpg else turn cpg
        -- X is human, O is computer
        3 -> if player == 'O' then autoTurn False cpg else turn cpg
    putStrLn $ "\n" ++ showGame newGame
    if tictactoe newGame
    then putStrLn $ "Player " ++ [changePlayer newPlayer] ++ " wins!\n"
    else
        if newCount == 9
        then putStrLn "Draw!\n"
        else play auto newcpg

-- main program: greet the user, ask for a game type, ask for the
-- player that'll start the game, and play the game beginning with an
-- empty board
main :: IO ()
main = do
    a <- getArgs
    if null a
    then usage
    else do
        let option = head a
        if option `elem` ["0","1","2","3"]
        then do
            putStrLn $ "\n" ++ showGame start
            let m = read option :: Int
            play m (0, 'X', start)
        else usage

usage :: IO ()
usage = do
    putStrLn "TIC-TAC-TOE GAME\n================\n"
    putStrLn "How do you want to play?"
    putStrLn "Run the program with one of the following options."
    putStrLn "0 : both players are human"
    putStrLn "1 : both players are computer"
    putStrLn "2 : player X is computer and player O is human"
    putStrLn "3 : player X is human and player O is computer"
    putStrLn "Player X always begins."


# Play TicTacToe

$define E " " # empty square
$define X "X" # X piece
$define O "O" # O piece

# -- define a board
record Board(a, b, c, d, e, f, g, h, i)

procedure display_board (board, player)
  write ("\n===============")
  write (board.a || " | " || board.b || " | " || board.c)
  write ("---------")
  write (board.d || " | " || board.e || " | " || board.f)
  write ("---------")
  write (board.g || " | " || board.h || " | " || board.i)
end

# return a set of valid moves (empty positions) in given board
procedure empty_fields (board)
  fields := set()
  every i := !fieldnames(board) do
    if (board[i] == E) then insert (fields, i)
  return fields
end

procedure game_start ()
  return Board (E, E, E, E, E, E, E, E, E)
end

procedure game_is_drawn (board)
  return *empty_fields(board) = 0
end

procedure game_won_by (board, player)
  return (board.a == board.b == board.c == player) |
         (board.d == board.e == board.f == player) |
         (board.g == board.h == board.i == player) |
         (board.a == board.d == board.g == player) |
         (board.b == board.e == board.h == player) |
         (board.c == board.f == board.i == player) |
         (board.a == board.e == board.i == player) |
         (board.g == board.e == board.c == player)
end

procedure game_over (board)
  return game_is_drawn (board) | game_won_by (board, O) | game_won_by (board, X)
end

# -- players make their move on the board
#    assume there is at least one empty square

procedure human_move (board, player)
  choice := "z"
  options := empty_fields (board)
  # keep prompting until player selects a valid square
  until member (options, choice) do {
    writes ("Choose one of: ")
    every writes (!options || " ")
    writes ("\n> ")
    choice := read ()
  }
  board[choice] := player
end

# pick and make a move at random from empty positions
procedure random_move (board, player)
  board[?empty_fields(board)] := player
end

# -- manage the game play
procedure play_game ()
  # hold procedures for players' move in variables
  player_O := random_move
  player_X := human_move

  # randomly determine if human or computer moves first
  if (?2 = 0)
    then {
      write ("Human plays first as O")
      player_O := human_move
      player_X := random_move
    }
    else write ("Computer plays first, human is X")

  # set up the game to start
  board := game_start ()
  player := O
  display_board (board, player)
  # loop until the game is over, getting each player to move in turn
  until game_over (board) do {
    write (player || " to play next")
    # based on player, prompt for the next move
    if (player == O)
      then (player_O (board, player))
      else (player_X (board, player))
    # change player to move
    player := if (player == O) then X else O
    display_board (board, player)
  }
  # finish by writing out result
  if game_won_by (board, O)
    then write ("O won")
    else if game_won_by (board, X)
      then write ("X won")
      else write ("draw") # neither player won, so must be a draw
end

# -- get things started
procedure main ()
  play_game ()
end


Note 'ttt adjudicates or plays'

   use:  markers ttt characters

   characters represent the cell names.

   markers is a length 3 character vector of the
   characters to use for first and second player
   followed by the opponent's mark.
   'XOX' means X plays 1st, O is the other mark,
   and the first strategy plays 1st.
   'XOO' means X plays 1st, O is the other mark,
   and the second strategy moves first.

   The game  is set  up for  the computer as the
   first strategy (random), and human as second.

   A standard use:
      'XOX'ttt'abcdefghijkl'

   Example game reformatted w/ emacs artist-mode
   to fit your display:

      '#-#'ttt'wersdfxcv'
   w│e│r                     w│e│r        ....    -│e│r           .    -│e│#
   ─┼─┼─                 .   ─┼─┼─       ..       ─┼─┼─         ..     ─┼─┼─
   s│d│f                 .   s│#│f      ..        s│#│f        ..      -│#│f
   ─┼─┼─                ..   ─┼─┼─      .         ─┼─┼─      ...       ─┼─┼─
   x│c│v               ..    -│c│v      .         -│c│#     ..         -│c│#
   d                  ..     v         ..         r         .          VICTORY
   w│e│r             ..      w│e│r     ..         -│e│#     .
   ─┼─┼─           ...       ─┼─┼─     ..         ─┼─┼─    .
   s│#│f         ...         s│#│f     ..         s│#│f    .
   ─┼─┼─        ..           ─┼─┼─   ...          ─┼─┼─  ...
   x│c│v                     -│c│#                -│c│#
   -->cell for -?            -->cell for -?       -->cell for -?
   x                         w                    s
)

while=: conjunction def 'u ^: v ^:_' NB. j assumes while is a verb and needs to know while is a conjunction.

ttt=: [email protected]:(([email protected]:move) while undecided)@:[email protected]:prepare

blindfolded_variant=: [email protected]:[email protected]:(move while undecided)@:[email protected]:prepare

outcome=: {&(>;:'kitty VICTORY')@:won   NB. (outcome does not pass along the state)
move=: post locate
undecided=: won nor full
prepare=: , [email protected]:]                    NB. form the state vector

Note 'locate'
  is a monadic verb.  y is the state vector.
  returns the character of the chosen cell.
  Generally:
  locate=: second_strategy`[email protected](first = mark)
  Simplified:
  locate=: human_locate NB. human versus human
)
locate=: human_locate`[email protected](first = mark)

display=: show [: (1 1,:5 5)&(];.0)@:": [: <"0 fold

computer_locate=: [: [email protected]{. board -. marks NB. strategy: first available
computer_locate=: [: [email protected]({~ [email protected]:#) board -. marks NB. strategy: random

human_locate=: monad define
  state=. y
  m=. mark state
  b=. board state
  cells=. b -. marks state
  show '-->cell for ' , m , '?'
  whilst. cell [email protected]:e. cells do. cell =. {. (1!:1]1) , m end.
)

post=: 2&[email protected]:(3&{.)@:[ prepare [email protected]:[`((i.~ board)~)`([email protected]:[)}

mark=: {.                    NB. mark of the current player from state
marks=: 2&{.                 NB. extract both markers from state
board=: _9&{.                NB. extract board from state
first=: 2&{                  NB. extract first player from state

show=: [ smoutput

full=: 2 = #@:~.
won=: [email protected]:fold
fold=: 3 3 $ board
test=: [: any [: all [: infix_pairs_agree |:@:lines

lines=: , diagonal , [email protected]:|. , |:
diagonal=: (<0 1)&|:
all=: *./
any=: +./
nor=: 8 b.
infix_pairs_agree=: 2&(=/\)


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Hashtable;

public class TicTacToe
{
	public static void main(String[] args)
	{
		TicTacToe now=new TicTacToe();
		now.startMatch();
	}

	private int[][] marks;
	private int[][] wins;
	private int[] weights;
	private char[][] grid;
	private final int knotcount=3;
	private final int crosscount=4;
	private final int totalcount=5;
	private final int playerid=0;
	private final int compid=1;
	private final int truceid=2;
	private final int playingid=3;
	private String movesPlayer;
	private byte override;
	private char[][] overridegrid={{'o','o','o'},{'o','o','o'},{'o','o','o'}};
	private char[][] numpad={{'7','8','9'},{'4','5','6'},{'1','2','3'}};
	private Hashtable<Integer,Integer> crossbank;
	private Hashtable<Integer,Integer> knotbank;

	public void startMatch()
	{
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		System.out.print("Start?(y/n):");
		char choice='y';
		try
		{
			choice=br.readLine().charAt(0);
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
		}
		if(choice=='n'||choice=='N')
		{
			return;
		}

		System.out.println("Use a standard numpad as an entry grid, as so:\n ");
		display(numpad);
		System.out.println("Begin");
		int playerscore=0;
		int compscore=0;
		do
		{
			int result=startGame();
			if(result==playerid)
				playerscore++;
			else if(result==compid)
				compscore++;
			System.out.println("Score: Player-"+playerscore+" AI-"+compscore);
			System.out.print("Another?(y/n):");
			try
			{
				choice=br.readLine().charAt(0);
			}
			catch(Exception e)
			{
				System.out.println(e.getMessage());
			}

		}while(choice!='n'||choice=='N');

		System.out.println("Game over.");
	}
	private void put(int cell,int player)
	{
		int i=-1,j=-1;;
		switch(cell)
		{
		case 1:i=2;j=0;break;
		case 2:i=2;j=1;break;
		case 3:i=2;j=2;break;
		case 4:i=1;j=0;break;
		case 5:i=1;j=1;break;
		case 6:i=1;j=2;break;
		case 7:i=0;j=0;break;
		case 8:i=0;j=1;break;
		case 9:i=0;j=2;break;
		default:display(overridegrid);return;
		}
		char mark='x';
		if(player==0)
			mark='o';
		grid[i][j]=mark;
		display(grid);
	}
	private int startGame()
	{
		init();
		display(grid);
		int status=playingid;
		while(status==playingid)
		{
			put(playerMove(),0);
			if(override==1)
			{
				System.out.println("O wins.");
				return playerid;
			}
			status=checkForWin();
			if(status!=playingid)
				break;
			try{Thread.sleep(1000);}catch(Exception e){System.out.print(e.getMessage());}
			put(compMove(),1);
			status=checkForWin();
		}
		return status;
	}
	private void init()
	{
		movesPlayer="";
		override=0;
		marks=new int[8][6];
		wins=new int[][]	//new int[8][3];
		{
				{7,8,9},
				{4,5,6},
				{1,2,3},
				{7,4,1},
				{8,5,2},
				{9,6,3},
				{7,5,3},
				{9,5,1}
		};
		weights=new int[]{3,2,3,2,4,2,3,2,3};
		grid=new char[][]{{' ',' ',' '},{' ',' ',' '},{' ',' ',' '}};
		crossbank=new Hashtable<Integer,Integer>();
		knotbank=new Hashtable<Integer,Integer>();
	}
	private void mark(int m,int player)
	{
		for(int i=0;i<wins.length;i++)
			for(int j=0;j<wins[i].length;j++)
				if(wins[i][j]==m)
				{
					marks[i][j]=1;
					if(player==playerid)
						marks[i][knotcount]++;
					else
						marks[i][crosscount]++;
					marks[i][totalcount]++;
				}
	}
	private void fixWeights()
	{
		for(int i=0;i<3;i++)
			for(int j=0;j<3;j++)
				if(marks[i][j]==1)
					if(weights[wins[i][j]-1]!=Integer.MIN_VALUE)
						weights[wins[i][j]-1]=Integer.MIN_VALUE;

		for(int i=0;i<8;i++)
		{
			if(marks[i][totalcount]!=2)
				continue;
			if(marks[i][crosscount]==2)
			{
				int p=i,q=-1;
				if(marks[i][0]==0)
					q=0;
				else if(marks[i][1]==0)
					q=1;
				else if(marks[i][2]==0)
					q=2;

				if(weights[wins[p][q]-1]!=Integer.MIN_VALUE)
				{
					weights[wins[p][q]-1]=6;
				}
			}
			if(marks[i][knotcount]==2)
			{
				int p=i,q=-1;
				if(marks[i][0]==0)
					q=0;
				else if(marks[i][1]==0)
					q=1;
				else if(marks[i][2]==0)
					q=2;

				if(weights[wins[p][q]-1]!=Integer.MIN_VALUE)
				{
					weights[wins[p][q]-1]=5;
				}
			}
		}
	}
	private int compMove()
	{
		int cell=move();
		System.out.println("Computer plays: "+cell);
		//weights[cell-1]=Integer.MIN_VALUE;
		return cell;
	}
	private int move()
	{
		int max=Integer.MIN_VALUE;
		int cell=0;
		for(int i=0;i<weights.length;i++)
			if(weights[i]>max)
			{
				max=weights[i];
				cell=i+1;
			}

		//This section ensures the computer never loses
		//Remove it for a fair match
		//Dirty kluge
		if(movesPlayer.equals("76")||movesPlayer.equals("67"))
			cell=9;
		else if(movesPlayer.equals("92")||movesPlayer.equals("29"))
			cell=3;
		else if (movesPlayer.equals("18")||movesPlayer.equals("81"))
			cell=7;
		else if(movesPlayer.equals("73")||movesPlayer.equals("37"))
			cell=4*((int)(Math.random()*2)+1);
		else if(movesPlayer.equals("19")||movesPlayer.equals("91"))
			cell=4+2*(int)(Math.pow(-1, (int)(Math.random()*2)));

		mark(cell,1);
		fixWeights();
		crossbank.put(cell, 0);
		return cell;
	}
	private int playerMove()
	{
		System.out.print("What's your move?: ");
		BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
		int cell=0;
		int okay=0;
		while(okay==0)
		{
			try
			{
				cell=Integer.parseInt(br.readLine());
			}
			catch(Exception e)
			{
				System.out.println(e.getMessage());
			}
			if(cell==7494)
			{
				override=1;
				return -1;
			}
			if((cell<1||cell>9)||weights[cell-1]==Integer.MIN_VALUE)
				System.out.print("Invalid move. Try again:");
			else
				okay=1;
		}
		playerMoved(cell);
		System.out.println();
		return cell;
	}
	private void playerMoved(int cell)
	{
		movesPlayer+=cell;
		mark(cell,0);
		fixWeights();
		knotbank.put(cell, 0);
	}
	private int checkForWin()
	{
		int crossflag=0,knotflag=0;
		for(int i=0;i<wins.length;i++)
		{
			if(crossbank.containsKey(wins[i][0]))
				if(crossbank.containsKey(wins[i][1]))
					if(crossbank.containsKey(wins[i][2]))
					{
						crossflag=1;
						break;
					}
			if(knotbank.containsKey(wins[i][0]))
				if(knotbank.containsKey(wins[i][1]))
					if(knotbank.containsKey(wins[i][2]))
					{
						knotflag=1;
						break;
					}
		}
		if(knotflag==1)
		{
			display(grid);
			System.out.println("O wins.");
			return playerid;
		}
		else if(crossflag==1)
		{
			display(grid);
			System.out.println("X wins.");
			return compid;
		}

		for(int i=0;i<weights.length;i++)
			if(weights[i]!=Integer.MIN_VALUE)
				return playingid;
		System.out.println("Truce");

		return truceid;
	}
	private void display(char[][] grid)
	{
		for(int i=0;i<3;i++)
		{
			System.out.println("\n-------");
			System.out.print("|");
			for(int j=0;j<3;j++)
				System.out.print(grid[i][j]+"|");
		}
		System.out.println("\n-------");
	}
}