Tic Tac Toe - Demo program

by shian ⌂, Thursday, August 20, 2020, 15:58 (29 days ago)
edited by shian, Tuesday, September 01, 2020, 17:20

-- Simple demo of Tic Tac Toe game; You play against the PC.
--
-- Copy/Paste the code into text file, run it in your console
-- and see how it works... (press control-C to break)
--
-- There are 3 levels - 1 is the most easy.
-- The code demonstrates only basic programming methods (procedure,
-- function, constant, include, if..then, for/while loops, etc).
-- (I did not debug too much... so for now I hope that it works OK).
--
-- Language: Euphoria 3.1.1; by shian, 20/8/2020
 
 
include get.e       -- prompt_string(), prompt_number()
include wildcard.e  -- upper()
 
-- with trace
-- trace(1)
 
constant SCREEN = 1
constant TRUE = 1
 
-- X is you; O is the PC; ' ' is blank
constant X = 'X', O = 'O', B = ' ', BOARD_FULL = 'F', CONTINUE_PLAY = -1
 
-- position to print the board
constant BOARD_LINE = 2, PROMPT_LINE = BOARD_LINE + 12, PROMPT_COLUMN = 3
 
sequence matrix -- string-sequence of length 9 (3+3+3)
integer player  -- player can be constant X (you) or O (the PC)
integer level   -- how clever is the PC? from 1 to 3 (1=child)
                --  we could add level 4 but the code is long enough...
 
sequence your_name
 
your_name = ""  -- enter your name before first game
 
procedure print_board()
-- simple/short method to print the board
-- using a single printf() command
    position(BOARD_LINE, 1)
    printf(SCREEN,
        "\t  * TicTacToe * \n" &
        "\t     Level %d  \n" &
        "\t~~~~~~~~~~~~~~~~~\n" &
        "\t    A   B   C  \n" &
        "\t  +---+---+---+\n" &
        "\t1 | %s | %s | %s |\n" &
        "\t  +---+---+---+\n" &
        "\t2 | %s | %s | %s |\n" &
        "\t  +---+---+---+\n" &
        "\t3 | %s | %s | %s |\n" &
        "\t  +---+---+---+\n",
    level & matrix)
end procedure
 
function string_to_index(sequence column_line)
-- example: if column_line is "a3" then return index 7 in matrix
    integer col, row
 
    col = upper(column_line[1]) - ('A' - 1)
    row = column_line[2] - '1'
 
    return row * 3 + col
end function
 
procedure you_play()
    sequence s
    integer p
 
    while TRUE do
        -- erase old prompt
        position(PROMPT_LINE, PROMPT_COLUMN)
        puts(SCREEN, repeat(' ', 80))
 
        -- new prompt
        position(PROMPT_LINE, PROMPT_COLUMN)
        s = prompt_string("Enter X (example: \"b1\"): ")
 
        -- valid input?
        if length(s) = 2 and find(s[1], "abcABC") and find(s[2], "123") then
            p = string_to_index(s)
            if matrix[p] = B then
                matrix[p] = X
                return
            end if
        end if
    end while
end procedure
 
function get_triplets()
    return {
        -- lines                            -- index of triplet
        matrix[1..3],                       -- [1]
        matrix[4..6],                       -- [2]
        matrix[7..9],                       -- [3]
        -- columns
        matrix[1] & matrix[4] & matrix[7],  -- [4]
        matrix[2] & matrix[5] & matrix[8],  -- [5]
        matrix[3] & matrix[6] & matrix[9],  -- [6]
        -- diagonals \ and /
        matrix[1] & matrix[5] & matrix[9],  -- [7]
        matrix[3] & matrix[5] & matrix[7]   -- [8]
    }
end function
 
procedure pc_play()
    integer row, pos, fallback
    sequence triplets, trio
 
    if level > 1 then -- (not used by level 1)
        fallback = 0
        triplets = get_triplets()
        pos = 0
    end if
 
    -- this loop tries level 3 then level 2 (then exits to level 1)
    for le = level to 2 by -1 do
 
        if level = 3 and fallback != 2 then
            -- PC tries to win you in level 3 (i.e. "OOO")
            trio = {{B,O,O}, {O,B,O}, {O,O,B}}
            fallback = 2
        elsif level = 2 or fallback = 2 then
            -- PC tries to block you in level 2 (e.g. "XXO")
            trio = {{B,X,X}, {X,B,X}, {X,X,B}}
            fallback = 1
        end if
 
        -- this loop checks each element of the current trio
        for col = 1 to 3 do
 
            -- win/block line (row is 1,2,3 here)
            row = find(trio[col], triplets[1..3])
            if row then
                pos = (row - 1) * 3 + col
                exit
            end if
 
            -- win/block column (row is A,B,C here)
            row = find(trio[col], triplets[4..6])
            if row then
                pos = row + (col - 1) * 3
                exit
            end if
 
            -- win/block diagonal \
            if equal(trio[col], triplets[7]) then
                pos = (col - 1) * 3 + col
                exit
            end if
 
            -- win/block diagonal /
            if equal(trio[col], triplets[8]) then
                pos = (col - 1) * 3 + (3 - col + 1)
                exit
            end if
        end for -- trio
 
        -- pos is the actual index in the matrix string
        if pos then
            matrix[pos] = O
            return
        end if
 
    end for -- level
 
    -- level 1 is a simple random guess
    if level = 1 or fallback = 1 then
        while TRUE do
            pos = rand(9)
            if matrix[pos] = B then
                matrix[pos] = O
                return
            end if
        end while
    end if
end procedure
 
function check_if_game_over()
    sequence t
 
    t = get_triplets()
 
    if find(repeat(X, 3), t) then
        return X            -- your triplet wins
    elsif find(repeat(O, 3), t) then
        return O            -- PC triplet wins
    elsif not find(B, matrix) then
        return BOARD_FULL   -- no winner
    else
        return CONTINUE_PLAY
    end if
end function
 
function well_done(integer over)
    sequence prefix, suffix
    integer new
 
    prefix = "       *** GAME OVER - THE WINNER IS "
    suffix = "! ***       "
    position(PROMPT_LINE, PROMPT_COLUMN)
    if over = X then
        puts(SCREEN, prefix & "YOU !!" & suffix)
    elsif over = O then
        puts(SCREEN, prefix & "THE PC" & suffix)
    elsif over = BOARD_FULL then
        puts(SCREEN, prefix & "NOBODY" & suffix)
    end if
 
    position(PROMPT_LINE + 2, PROMPT_COLUMN)
    printf(SCREEN, "New game %s [Y,N]? ", {your_name})
    new = 0
    while new != 'Y' and new != 'N' do
        new = upper(wait_key())
        puts(SCREEN, new)
    end while
 
    return new
end function
 
procedure start_new_game()
    sequence players
 
    -- who starts the game?
    players = {X, O}
    player = players[rand(2)]
 
    -- new blank board {B,B,B, B,B,B, B,B,B}, 9 blanks
    matrix = repeat(B, 9)
 
    clear_screen()
    position(2, 3)
    level = floor(prompt_number("Enter Level [1,2,3]: ", {1, 3}))
 
    if length(your_name) = 0 then
        position(4, 3)
        your_name = prompt_string("Enter your name: ")
    end if
    clear_screen()
end procedure
 
procedure main()
    integer over, new
 
    new = 'Y'
 
    -- this is the main loop of the games
    while new = 'Y' do
        start_new_game()
        print_board()
 
        over = CONTINUE_PLAY
 
        -- this loop is for a single game
        while over = CONTINUE_PLAY do
 
            if player = X then
                you_play()
                player = O
            else -- plyaer = O
                pc_play()
                player = X
            end if
 
            print_board()
            over = check_if_game_over()
        end while
 
        new = well_done(over)
    end while
 
end procedure
 
main()
 
-- End.
 
 

Tags:
demo


Complete thread:

 RSS Feed of thread

powered by my little forum