Task: Tic-tac-toe




Go: 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 {
        
        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++ { 
        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
    }()
    
    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 
        }
        if yours == 2 && x >= 0 {
            block = x
        } 
    }
    if block >= 0 {
        x = block 
        return
    }
    
    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 {
    
    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 
        } 
    }
    
    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}, 
    {3, 4, 5},
    {6, 7, 8},
    {0, 3, 6}, 
    {1, 4, 7},
    {2, 5, 8},
    {0, 4, 8}, 
    {2, 4, 6},
}








Ada: with Ada.Text_IO, Ada.Numerics.Discrete_Random;
  
  

procedure Tic_Tac_Toe is

   type The_Range is range 1 .. 3;
   type Board_Type is array (The_Range, The_Range) of Character;

   package Rand is new Ada.Numerics.Discrete_Random(The_Range);
   Gen: Rand.Generator; 

   procedure Show_Board(Board: Board_Type) is
      use Ada.Text_IO;
   begin
      for Row in The_Range loop
         for Column in The_Range loop
            Put(Board(Row, Column));
         end loop;
         Put_Line("");
      end loop;
      Put_Line("");
   end Show_Board;

   function Find_Winner(Board: Board_Type) return Character is
      

      function Three_Equal(A,B,C: Character) return Boolean is
      begin
         return (A=B) and (A=C);
      end Three_Equal;

   begin 
      for I in The_Range loop
         if    Three_Equal(Board(I,1), Board(I,2), Board(I,3)) then
            return Board(I,1);
         elsif  Three_Equal(Board(1,I), Board(2,I), Board(3,I)) then
            return Board(1,I);
         end if;
      end loop;
      if Three_Equal(Board(1,1), Board(2,2), Board (3,3)) or
         Three_Equal(Board(3,1), Board(2,2), Board (1,3)) then
         return Board(2,2);
      end if;
      return ' ';
   end Find_Winner;

   procedure Do_Move(Board: in out Board_Type;
                     New_Char: Character; Computer_Move: Boolean) is
      Done: Boolean := False;
      C: Character;
      use Ada.Text_IO;

      procedure Do_C_Move(Board: in out Board_Type; New_Char: Character) is
         Found: Boolean := False;
         X,Y: The_Range;
      begin
         while not Found loop
            X := Rand.Random(Gen);
            Y := Rand.Random(Gen);
            if (Board(X,Y) /= 'x') and  (Board(X,Y) /= 'o') then
               Found := True;
               Board(X,Y) := New_Char;
            end if;
         end loop;
      end Do_C_Move;

   begin
      if Computer_Move then
         Do_C_Move(Board, New_Char);
      else 
         Put_Line("Choose your move, " & New_Char);
         while not Done loop
            Get(C);
            for Row in The_Range loop
               for Col in The_Range loop
                  if Board(Row, Col) = C then
                     Board(Row, Col) := New_Char;
                     Done := True;
                  end if;
               end loop;
            end loop;
         end loop;
      end if;
   end Do_Move;

   The_Board : Board_Type := (('1','2','3'), ('4','5','6'), ('7','8','9'));
   Cnt_Moves: Natural := 0;
   Players: array(0 .. 1) of Character := ('x', 'o'); 
   C_Player: array(0 .. 1) of Boolean := (False, False);
   Reply: Character;

begin 

   
   for I in Players'Range loop
      Ada.Text_IO.Put_Line("Shall " & Players(I) &
                             " be run by the computer? (y=yes)");
      Ada.Text_IO.Get(Reply);
      if Reply='y' or Reply='Y' then
         C_Player(I) := True;
         Ada.Text_IO.Put_Line("Yes!");
      else
         Ada.Text_IO.Put_Line("No!");
      end if;
   end loop;
   Rand.Reset(Gen); 

   
   while (Find_Winner(The_Board) = ' ') and (Cnt_Moves < 9) loop
      Show_Board(The_Board);
      Do_Move(The_Board, Players(Cnt_Moves mod 2), C_Player(Cnt_Moves mod 2));
      Cnt_Moves := Cnt_Moves + 1;
   end loop;
   Ada.Text_IO.Put_Line("This is the end!");

   
   Show_Board (The_Board);
   if Find_Winner(The_Board) = ' ' then
      Ada.Text_IO.Put_Line("Draw");
   else
      Ada.Text_IO.Put_Line("The winner is: " & Find_Winner(The_Board));
   end if;
end Tic_Tac_Toe;