Looking for an alternate method(s)

I was modifying someone's Tic-Tac-Toe game for fun, and this is the function s/he used to check if a Tic-Tac-Toe was made:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    if(BOARD[0] == BOARD[1] && BOARD[1] == BOARD[2])
    {
        if(BOARD[0] == 'X')     return 1;
        return 2;
    }
    if(BOARD[3] == BOARD[4] && BOARD[4] == BOARD[5])
    {
        if(BOARD[3] == 'X')     return 1;
        return 2;
    }
    if(BOARD[6] == BOARD[7] && BOARD[7] == BOARD[8])
    {
        if(BOARD[6] == 'X')     return 1;
        return 2;
    }
    if(BOARD[0] == BOARD[3] && BOARD[3] == BOARD[6])
    {
        if(BOARD[0] == 'X')     return 1;
        return 2;
    }
    if(BOARD[1] == BOARD[4] && BOARD[4] == BOARD[7])
    {
        if(BOARD[1] == 'X')     return 1;
        return 2;
    }
    if(BOARD[2] == BOARD[5] && BOARD[5] == BOARD[8])
    {
        if(BOARD[2] == 'X')     return 1;
        return 2;
    }
    if(BOARD[0] == BOARD[4] && BOARD[4] == BOARD[8])
    {
        if(BOARD[0] == 'X')     return 1; 
        return 2;
    }
    if(BOARD[2] == BOARD[4] && BOARD[4] == BOARD[6])
    {
        if(BOARD[2] == 'X')     return 1;
        return 2;
    }
    return 0;

It returns the number of the player who wins, or zero if it's a tie game.

Now I modified the code to where this function isn't utilized until it's possible to win (Turn 5 through Turn 9). Now if nobody wins until Turn 9, then there are 4 occasions where the function is executed fully with 18 rounds of logic checks, totaling 72 logic checks (4*18).

I'd like to turn this into two separate functions to check for a win unique to each player which utilizes the location the player just put his/her mark.
1
2
3
4
5
6
7
8
    get_input();
    check_if_win(chosen_point, unique_player_id);
}
check_if_win(int chosen_point, int unique_player_id)
{
    //test chosen_point compared to the possible ways you could win
    //after you placed your X there
}


I'd also like to use something along the lines of vector.erase(/*stuff*/) which will erase one of the logic checks in a player's own function, thereby reducing the number of checks gone through the his/her next turn

I know it's confusing. Just looking for ideas.
If you are playing on a tic tac toe board larger than 3 x 3 then ignore the following:

Note that if nobody wins until turn 9, then the person who made the first move has the last move. So you are only checking for 1 person at turn 9.

Turn 8 - the second player has 2 moves to make
Turn 7 - the first player has 3 moves available to him/her
...

An idea is to have an array or vector of possible win situations for each player:

1
2
3
win_edge[][3] = {{0, 1, 2}, {0, 3, 6}, {0, 4, 8},
                 {1, 4, 7}, {2, 4, 6}, {2, 5, 8},
                 {3, 4, 5}, {6, 7, 8}};


Then whenever each player makes a move, rather than checking if they won, you go to the win_edge array for the other player and remove any sub-array which contains that move. The numbers in the subarray are indices of the board.

Example:
1
2
get_input();
remove_move(chosen_point, other_player);


Then by the 5-9th moves, there is only a few number of these subarrays that define the number of possible wins left for each player, then you can start doing the checks after every move to see if any of them won.
> win unique to each player which utilizes the location the player just put his/her mark.

Use a pre-created lookup table?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <utility>
#include <vector>
#include <map>
#include <algorithm>
#include <array>

using pos_type = std::pair< std::size_t, std::size_t > ;

// maps position to row, col, diags positions to look up
// the vector lobically contains a sequence of (n-1)-tuples where n == board_size
// where each (n-1)-tuple represents the remaing n-1 positions to look up
using map_type = std::map< pos_type, std::vector<pos_type> > ;

template < std::size_t N > map_type make_map()
{
    map_type m ;

    for( std::size_t row = 0 ; row < N ; ++row )
        for( std::size_t col = 0 ; col < N ; ++col )
        {
            auto& vec = m[ {row,col} ] ;

            // row
            for( std::size_t c = 0 ; c < N ; ++c ) if( c!=col ) vec.emplace_back(row,c) ;

            // col
            for( std::size_t r = 0 ; r < N ; ++r ) if( r!=row ) vec.emplace_back(r,col) ;

            // diaganols
            if( row == col ) for( std::size_t i = 0 ; i < N ; ++i )
                    if( i != row ) vec.emplace_back(i,i) ;

            if( row == N -col-1 ) for( std::size_t i = 0 ; i < N ; ++i )
                    if( i != row ) vec.emplace_back( i, N-i-1 ) ;
        }

     return m ;
}

template< typename BOARD >
bool check_win( const BOARD& board, pos_type last_move,
                const map_type& look_up, std::size_t N )
{
    const auto& v = board[last_move.first][last_move.second] ;
    const std::vector<pos_type>& seq = look_up.find(last_move)->second ;

    // size of row, col diuag == N, so check blocks of N-1 (other positions) at a time
    const std::size_t NLOOKUPS = N-1 ;
    for( auto iter = seq.begin() ; iter < seq.end() ; iter += NLOOKUPS )
    {
        std::size_t cnt = 0 ;
        for( auto subiter = iter ; subiter < iter + NLOOKUPS ; ++subiter )
            if( board[subiter->first][subiter->second] == v ) ++cnt ;
            else break ;
        if( cnt == NLOOKUPS ) return true ; // found row, col or diag with all N == v
    }

    return false ;
}

template< typename BOARD >
bool check_win( const BOARD& board, pos_type last_move, const map_type& look_up )
{ return check_win( board, last_move, look_up, board.size() ) ; }

int main()
{
    constexpr std::size_t BOARD_SZ = 7 ;
    int board[BOARD_SZ][BOARD_SZ] =
    {
        { 0, 1, 0, 5, 0, 0, 5 },
        { 0, 0, 0, 0, 0, 5, 0 },
        { 1, 0, 0, 0, 5, 0, 0 },
        { 0, 1, 0, 5, 1, 0, 1 },
        { 0, 0, 5, 0, 1, 0, 0 },
        { 0, 5, 5, 0, 1, 0, 0 },
        { 5, 0, 0, 0, 1, 0, 0 }
    };

    const map_type look_up = make_map<BOARD_SZ>() ;

    std::cout << std::boolalpha << check_win( board, {2,4}, look_up, BOARD_SZ ) << '\n' ;
}

http://coliru.stacked-crooked.com/a/2da46bac7d77267a
Topic archived. No new replies allowed.