带有链表 C++ 的井字游戏

Posted

技术标签:

【中文标题】带有链表 C++ 的井字游戏【英文标题】:Tic-tac-toe game with Linked List C++ 【发布时间】:2014-09-09 21:00:02 【问题描述】:

在我正在阅读的一本 c++ 书籍中,我遇到了一个练习,建议我使用链表和数组来做一个井字游戏。我决定先尝试使用链表,因为使用数组显然更容易。但是,我陷入了如何检查是否有人赢得了比赛。到目前为止,这是我所拥有的:

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;



如您所见,在我的 struct Board 上,我有一个名为 pos 的 int,我创建它是为了跟踪整个 board。到目前为止,我能想象的唯一解决方案是检查每个位置。例如:将 pos 8 与 pos 9、7、5 和 2 进行比较,将 pos 9 与 pos 8、7、6、3、5 和 1 进行比较。但我认为这太广泛了(也许它也是硬编码?) .您认为我还有哪些其他选择?

提前致谢, 费利佩

【问题讨论】:

嗯,首先,您只需要比较包括最后更改的位置的可能解决方案(如果您将“X”放在位置 8,则无需检查“[1, 2 , 3]") 另外,我不知道它是否符合实践的想法,但是你不能有多个链表吗?如果棋盘的每个位置都包含在一个链表中,表示它所在的行/列/对角线,它可能会更简单(只需检查所有列表,但您不必遍历它们)。 但是这样我还需要更多的指针来存储列和对角线中的下一个和上一个位置? 【参考方案1】:

我需要更多的篇幅来解释“多个列表”的概念。

你的董事会:

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

代表可能解决方案的列表

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

请注意,每个单元格将位于至少 2 个列表中。

选项 1)

您将这些列表存储在一个“列表列表”中。移动完成后,您迭代该列表列表,并且对于每个子列表(上图中的 A、B 等),您迭代单元格。如果子列表中的所有单元格都来自移动的玩家,则您找到了获胜者。

选项 2)

每个单元格都有一个“列表列表”成员。该“列表列表”包含用于检查何时在该单元格中完成移动的列表(例如,对于单元格 1,您将拥有列表 A、E 和 D1)。当在单元格中完成移动时,您从单元格中获取该列表并检查子列表以查看您是否获得了获胜者(它与选项 1 或多或少相同,但限制了您必须遍历每个列表时间)。

请注意,在所有情况下,我们只处理列表(如果您添加“指向对角线的指针”并且类似的结构不再是列表)。只有这样:

有很多列表。 有单元格列表和单元格列表列表。

【讨论】:

你到底是什么意思:“如果你添加“指向对角线的指针”和类似的结构不再是一个列表”?我认为链表无论如何都需要指针,就像我在结构中使用的那样: struct board bool square, circle, empty;位置;板*下一个; ; "getDiagonalCell" 不是在列表中定义的操作。如果你想用列表来实现游戏,你可以使用为列表定义的操作(在链表的情况下,“firstElement”、“next”、“add”和“delete”)。您可以声明并实现一个函数“goToCellXY”,但这不是列表合同的一部分。 哦!我明白!我想我现在有足够的信息来完成这个游戏。但我仍然认为数组更容易和更快,我认为这是练习的一部分。无论如何,你帮了我很多!谢谢!

以上是关于带有链表 C++ 的井字游戏的主要内容,如果未能解决你的问题,请参考以下文章

带有 websockets 连接的井字游戏

在井字游戏 C++ 中使用“新游戏”按钮,win32 应用程序初学者

C++游戏game | 井字棋游戏坤坤版(配资源+视频)赋源码,双人对战

带有井字游戏的 Minimax 算法(但每个玩家只能有 3 个 tacs)

C++实现井字棋小游戏(写得不好,留作纪念!!!)

基于C++的井字棋小游戏(使用数组搭建)