Task: Tic-tac-toe


C++: #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;
}



C#: using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RosettaTicTacToe
{
  class Program
  {

    
    static string[][] Players = new string[][] { 
      new string[] { "COMPUTER", "X" }, 
      new string[] { "HUMAN", "O" }     
    };

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

    
    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 } };


    
    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);  
        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;
      }
    }

    
    static int getMoveFor(int player)
    {
      if (player == Human)
        return getManualMove(player);
      else
      {
        
        
        int selectedMove = getSemiRandomMove(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();  
        if (keyInfo.Key == ConsoleKey.Escape)
          return Unplayed;
        if (keyInfo.Key >= ConsoleKey.D1 && keyInfo.Key <= ConsoleKey.D9)
        {
          int move = keyInfo.KeyChar - '1';  
          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++)  
      {
        if (GameBoard[i] == Unplayed && x < 0)    
          return i;
        x--;
      }
      return Unplayed;
    }

    
    static int getSemiRandomMove(int player)
    {
      int posToPlay;
      if (checkForWinningMove(player, out posToPlay))
        return posToPlay;
      if (checkForBlockingMove(player, out posToPlay))
        return posToPlay;
      return getRandomMove(player);
    }

    
    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);
    }

    
    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();  
      return playerToken(GameBoard[boardPosition]);
    }

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

}