简体   繁体   中英

Tic-tac-toe game with Linked List C++

In one of the c++ books that I am reading, I came across one exercise that proposes me to do a tic-tac-toe game using both linked list and arrays. I decided to try with linked list first, since with arrays is obviously easier. However, I got stuck on how to check if someone won the game. Here's what I have so far:

struct board
{
    bool square, circle, empty;
    int pos;
    board* next;
};
void startGame(int first, board* fullBoard);
board* getBoard(board* fullBoard);


int main()
{
    int dice, first;

    board* fullBoard = NULL;
    cout << "Welcome to Tic-tac-toe DOS Game. (2 Player version)\n\n";
    cout << "X is Player 1 and O is Player 2.\nI will decide who is starting in the first match...\n ";
    srand(time(NULL));
    dice = 1;//rand() % 6 + 1;
    cout << dice;
    if(dice <= 3)
    {
        first = 1;
        cout << "Player 1 is the first!\n";
    }
    else
    {
        first = 2;
        cout << "Player 2 is the first!\n\n";
    }
    system("pause");
    system("cls");
    startGame(first, fullBoard);
}

void startGame(int first, board* fullBoard)
{
    int choice;
    bool isPlaying;
    for(int i = 1; i <= 9; i++)
        fullBoard = getBoard(fullBoard);

    bool isGameOn = true;
    while(isGameOn == true)
    {
        board* current = fullBoard;
        while(current != NULL)
        {
            if(current->empty == true)
                cout << "   " << current->pos;
            else if(current->circle == true)
                cout << "   " << "O";
            else
                cout << "   " << "X";
            if( current->pos == 4 || current->pos == 7)
            {
                cout << "\n";
                cout << "-----------------------\n";
            }
            else if (current->pos == 1)
                cout << "\n";
            else
                cout << "   |";
            current = current->next;
        }



        if(first == 1)
        {
            isPlaying = true;
            while(isPlaying == true)
            {
                cout << "Player 1, please put the number corresponding to the area you want to fill: ";
                cin >> choice;
                while(choice < 1 || choice > 9)
                {
                    cout << "Invalid choice. Please choose a valid option: ";
                    cin >> choice;
                }
                current = fullBoard;
                while(current != NULL && current->pos != choice)
                    current = current->next;

                if(current->empty == true)
                {
                    current->empty = false;
                    current->square = true;
                    isPlaying = false;
                    first = 2;
                }
                else
                    cout << "The field that you chose is already used...\n";
            }

        }
        else
        {
            isPlaying = true;
            while(isPlaying == true)
            {
                cout << "Player 2, please put the number corresponding to the area you want to fill: ";
                cin >> choice;
                while(choice < 1 || choice > 9)
                {
                    cout << "Invalid choice. Please choose a valid option: ";
                    cin >> choice;
                }
                current = fullBoard;
                while(current != NULL && current->pos != choice)
                    current = current->next;

                if(current->empty == true)
                {
                    current->empty = false;
                    current->circle = true;
                    isPlaying = false;
                    first = 1;
                }
                else
                    cout << "The field that you chose is already used...\n";
            }
        }

        system("cls");
    }


}

board* getBoard(board* fullBoard)
{
    board* newBoard = new board;
    newBoard->empty = true;
    newBoard->circle = false;
    newBoard->square = false;
    newBoard->next = fullBoard;
    if(newBoard->next != NULL)
        newBoard->pos = newBoard->next->pos + 1;
    else
        newBoard->pos = 1;
    return newBoard;


}

As you can see, on my struct Board, I have an int called pos, which I created to keep track of the whole board. The only solution that I can imagine so far, is checking every single position. Ex: compare pos 8 with pos 9, 7, 5 and 2, compare pos 9 with pos 8, 7, 6, 3, 5 and 1. But I think that is way too extensive (and maybe it's hard coding as well?). What other options do you think I have?

Thanks in advance, Felipe

I need more space to explain the "multiple lists" concept.

Your board:

 _ _ _
|_|_|_|
|_|_|_|
|_|_|_|

The lists that represent the possible solutions

D1  A B C  D2
    _ _ _
 E |_|_|_|
 F |_|_|_|
 G |_|_|_|

Note that each cell will be in at least 2 lists.

Option 1)

You store those lists in a single "list of lists". When a move is done, you iterate that list of lists, and, for each sublist (which would be A, B, etc. from the previous figure), you iterate the cells. If all the cells in a sublist are from the player who moved, you found a winner.

Option 2)

Each cell has a member that is a "list of lists". That "list of lists" holds the lists to check when a move is done in that cell (for example, for cell 1, you would have lists A, E and D1). When a move is done in a cell, you get that list from the cell and check the sublists to see if you got a winner (it is more or less the same than option 1, but limiting the lists that you have to iterate over each time).

Note that in all the cases, we are dealing only with lists (if you add the "pointer to diagonal" and similar the structure no longer is a list). Only that:

  • there are many lists.
  • there are lists of cells, and lists of lists of cells.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM