c++ Gomoku 对角线检查器

c++ Gomoku diagonal checker

提问人:Gabriella 提问时间:5/25/2022 最后编辑:Gabriella 更新时间:5/25/2022 访问量:431

问:

所以我对编码比较陌生。所以我必须为一个项目制作一个 Gomoku 游戏。Gomoku 就像井字游戏,但必须连续获得五个。已获得某些限制,例如板尺寸为 6x6 至 15x15。使用至少一个类。我选择使用数组。我创建了 PlayerOne 作为一种算法,它基于 PlayerOne 的最后一步移动,并在下一步移动中将一个随机方块远离它。第二种算法是随机的。因为在检查获胜时,我的水平和垂直跳棋似乎有效,但我的两个对角线跳棋都出现了问题,他们说对角线连续 3 个连续方块是连续 5 个。我单独创建了我的检查器,手动填写每一行进行测试,对角线检查器在那里很好,但它们在整个代码中并不好。 我将在这里分享两个对角线检查器,然后在下面分享整个代码,希望更容易阅读。此外,它有相当多的 cout 语句,就像试图查看问题在流程早期的位置一样。如果有人能看到问题发生的地方,如果能指出在哪里,将不胜感激。

int game::diagonalCheckerNegSlope(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[j][i] == 1) {

                for (int d = 0; (i + d < size) && (j + d < size); d++)
                    if (arr[i + d][j + d] == 1) {
                        count1++;
                        if (count1 == 5) {
                            whoWon = 1;
                        }
                    } else {
                        count1 = 0;
                    }

            }
            if (arr[j][i] == 2) {

                for (int d = 0; (i + d < size) && (j + d < size); d++)
                    if (arr[i + d][j + d] == 2) {
                        count2++;
                        if (count2 == 5) {
                            whoWon = 2;
                        }
                    } else {
                        count2 = 0;
                    }

            }

        }

    }
    if (whoWon != 1 && whoWon != 2) {
        whoWon = 3;
    }

    return whoWon;
}

int game::diagonalCheckerPosSlope(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[i][j] == 1) {

                for (int d = 0; (i + d < size) && (j - d < size); d++)
                    if (arr[i + d][j - d] == 1) {
                        count1++;
                        if (count1 == 5) {
                            whoWon = 1;
                        }
                    } else {
                        count1 = 0;
                    }

            }
            if (arr[i][j] == 2) {

                for (int d = 0; (i + d < size) && (j - d < size); d++)
                    if (arr[i + d][j - d] == 2) {
                        count2++;
                        if (count2 == 5) {
                            whoWon = 2;
                        }
                    } else {
                        count2 = 0;
                    }
            }
        }

    }
    if (whoWon != 1 && whoWon != 2) {
        whoWon = 3;
    }
    return whoWon;
}

int 主代码

#include <iostream>
#include <fstream>
#include "game.h"
#include <iomanip>
#include <ctime>
using namespace std;



int main() {
    string inputSize = "input.txt";
    int size =0;
    srand(time(0));

    int arr[15][15];

    game Gomuko;

    size = Gomuko.getSize(inputSize, arr);
    if(size >=6 && size <=15){

    Gomuko.initZero(arr, size);
//  Gomuko.printArr(arr,size);

    Gomuko.Play(arr, size);

    Gomuko.printArr(arr,size);

    }else{
        cout << "Invalid input" << endl;
    }


    return 0;
}

类的 .h 文件

#ifndef GAME_H_
#define GAME_H_

#include <string>
#include <ctime>
using namespace std;

class game {
public:
    game();
    int getSize(string inputFileName, int dataArray[15][15]);
    void initZero(int arr[15][15], int size);
    void printArr(int arr[15][15], int size);
    void movePlayerOne(int arr[15][15], int size, int counter2);
    void movePlayerTwo(int arr[15][15], int size);
    void Play(int arr[15][15], int size);
    int PlayerOneSurroundRow(int arr[15][15],int size);
    int PlayerOneSurroundCol(int arr[15][15],int size);
    int findFirstMoveRow(int arr[15][15], int size);
    int findFirstMoveCol(int arr[15][15], int size);
    bool isValid(int newRow, int newCol, int size);
    int horizontalChecker(int arr[15][15], int size);
    int verticalChecker(int arr[15][15], int size);
    int diagonalCheckerNegSlope(int arr[15][15], int size);
    int diagonalCheckerPosSlope(int arr[15][15], int size);
    int WholeWinnerChecker(int arr[15][15], int size);
private:

    int randRow(int size);
    int randCol(int size);
};

#endif /* GAME_H_ */

最后是类的.cpp文件

#include "game.h"
#include <iostream>
#include <fstream>
#include <iomanip>
#include <ctime>
using namespace std;

game::game() {
    // TODO Auto-generated constructor stub

}

int game::getSize(string inputFileName, int dataArray[15][15]) {//make between 6 and 15.
    ifstream inputData;

    int size = 0;
    int counter = 0;

    inputData.open(inputFileName);

    if (!inputData) {
        cout << "Cannot open the file \"" << inputFileName << "\"" << endl;
    }
    else {
        while (inputData >> size) {
            counter++;
        }
        cout << "There are " << counter << " board sizes in the inputFile"
                << endl;
        cout << "The size of the board is " << size << "x" << size << endl
                << endl;
    }
    return size;
}

void game::initZero(int arr[15][15], int size) {
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            arr[i][j] = 0;
        }
    }
}

void game::printArr(int arr[15][15], int size) {

    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }

    cout << endl << endl;
}

int game::randRow(int size) {

    int randNoRow = 0;
    randNoRow = rand() % size;
    return randNoRow;
}

int game::randCol(int size) {

    int randNoCol = 0;
    randNoCol = rand() % size;
    return randNoCol;
}

int game::findFirstMoveRow(int arr[15][15], int size) {
    int positionRow;
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (arr[i][j] == 1) {
                positionRow = i;
            }
        }
    }

    return positionRow;
}

int game::findFirstMoveCol(int arr[15][15], int size) {
    int positionCol;
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            if (arr[i][j] == 1) {
                positionCol = j;
            }
        }
    }

    return positionCol;
}

int game::PlayerOneSurroundRow(int arr[15][15], int size) {

    int positionRow = game::findFirstMoveRow(arr, size);
//  cout << "The old row is " << positionRow << endl;

    int oldRow = positionRow;
    int randChoice = 0;
    int newRow = 0;

    randChoice = (rand() % 3);
//  cout << "randChoice Row case:  " << randChoice << endl;

    switch (randChoice) {
    case 0:
        newRow = oldRow - 1;
        break;
    case 1:
        newRow = oldRow;
        break;
    case 2:
        newRow = oldRow + 1;
        break;
    }
//  cout << "Test2" << endl << endl;
    if (newRow > size - 1) {
//      cout << "Row too big as Row is " << newRow << endl;
        newRow = newRow - 1;
//      cout << "Row is now " << newRow << endl;

    }
    if (newRow < 0) {
//      cout << "Row too small as row is " << newRow << endl;
        newRow = newRow + 1;
//      cout << "Row is now " << newRow << endl;

    }

//  cout << "The new row is: " << newRow << endl;

    return newRow;
}

int game::PlayerOneSurroundCol(int arr[15][15], int size) {

    int positionCol = findFirstMoveCol(arr, size);
//  cout << "The old col is " << positionCol << endl;

    int oldCol = positionCol;
    int randChoice = 0;
    int newCol = 0;

    randChoice = (rand() % 3);
    cout << "randChoice Col case: " << randChoice << endl;

    switch (randChoice) {
    case 0:
        newCol = oldCol - 1;
        break;
    case 1:
        newCol = oldCol;
        break;
    case 2:
        newCol = oldCol + 1;
        break;
    }
//  cout << "Test2" << endl << endl;
    if (newCol > size - 1) {
//      cout << "Col too big as is " << newCol << endl;
        newCol = newCol - 1;
//      cout << "Col is now " << newCol << endl;
    }
    if (newCol < 0) {
//      cout << "Col too small as is " << newCol << endl;
        newCol = newCol + 1;
//      cout << "Col is now " << newCol << endl;

    }

//  cout << "The new col is: " << newCol << endl;

    return newCol;
}

bool game::isValid(int newRow, int newCol, int size) {
    bool valid = false;
    if (((newRow < size) && (newCol < size))
            && ((newRow >= 0) && (newCol >= 0))) {
        valid = true;
    }
    return valid;
}

void game::movePlayerOne(int arr[15][15], int size, int counter2) {

    int newRow = 0;
    int newCol = 0;
    int oldRow = 0;
    int oldCol = 0;
    int count3 = 0;

    if (counter2 == 0) {
        oldRow = randRow(size);
        oldCol = randCol(size);

        arr[oldRow][oldCol] = 1;
//      cout << "Test1" << endl << endl << endl;
        counter2++;
    }

    else {

//      cout << "Test 3" << endl;

        newRow = game::PlayerOneSurroundRow(arr, size);
        newCol = game::PlayerOneSurroundCol(arr, size);

        if (arr[newRow][newCol] == 0 && isValid(newRow, newCol, size)) {
            arr[newRow][newCol] = 1;
//          cout << "Test4" << endl;
//          cout << "randNoRow = " << newRow << endl;
//          cout << "randNoCol = " << newCol << endl;

            oldRow = newRow;
            oldCol = newCol;
        }

        else if ((arr[newRow][newCol] == 1) || (arr[newRow][newCol] == 2)
                || (newRow > size) || (newCol > size) || (newRow < 0)
                || (newCol < 0)) {
            cout
                    << "There has been a match, or even out of bounds, going again. "
                    << endl << endl;

            while ((arr[newRow][newCol] == 1) || (arr[newRow][newCol] == 2)) {

//              cout << "Test5" << endl;
                newRow = game::PlayerOneSurroundRow(arr, size);
                newCol = game::PlayerOneSurroundCol(arr, size);

//              cout << "randNoRow = " << newRow << endl;
//              cout << "randNoCol = " << newCol << endl;

                count3++;
                if ((arr[newRow][newCol] != 1 && arr[newRow][newCol] != 2)
                        && isValid(newRow, newCol, size)) {
                    arr[newRow][newCol] = 1;
//                  cout << "Test6" << endl;
//
//                  cout << "randNoRow = " << newRow << endl;
//                  cout << "randNoCol = " << newCol << endl;

                    oldRow = newRow;
                    oldCol = newCol;
                    break;
                }

                if (count3++ > 3) {
//                  cout << "Test 7" << endl;
//                  newRow = randRow(size);
//                  newCol = randCol(size);
                    while (arr[newRow][newCol] == 1 || arr[newRow][newCol] == 2) {
                        newRow = randRow(size);
                        newCol = randCol(size);
//                      cout << "Test 8" << endl;
//                      cout << "randNoRow = " << newRow << endl;
//                      cout << "randNoCol = " << newCol << endl;

                        if (arr[newRow][newCol] == 0) {
                            arr[newRow][newCol] = 1;
//                          cout << "Test 9" << endl;
//                          cout << "randNoRow = " << newRow << endl;
//                          cout << "randNoCol = " << newCol << endl;
                            oldRow = newRow;
                            oldCol = newCol;
                            break;
                        }
                    }

                    break;
                }
            }

        }
    }
}

void game::movePlayerTwo(int arr[15][15], int size) {

//  cout << "Test" << endl;

    int randNoRow = 0;
    int randNoCol = 0;

    randNoRow = randRow(size);
    cout << "randNoRow = " << randNoRow << endl;

    randNoCol = randCol(size);
    cout << "randNoCol = " << randNoCol << endl;

    cout << endl;

    if ((arr[randNoRow][randNoCol] == 1) || (arr[randNoRow][randNoCol] == 2)) {
        //cout << "There has been a match, going again. " << endl << endl;
        while ((arr[randNoRow][randNoCol] == 1)
                || (arr[randNoRow][randNoCol] == 2)) {

            int randNoRow = 0;
            int randNoCol = 0;

            randNoRow = randRow(size);
            //cout << "randNoRow = " << randNoRow << endl;

            randNoCol = randCol(size);
            //cout << "randNoCol = " << randNoCol << endl;

            //cout << endl;

            if (arr[randNoRow][randNoCol] == 0) {
                arr[randNoRow][randNoCol] = 2;
                break;
            }
        }

    } else {
        arr[randNoRow][randNoCol] = 2;
    }
}

int game::horizontalChecker(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[i][j] == 1) {
                count1++;
                if (count1 == 5) {
                    whoWon = 1;
                }

            } else {
                count1 = 0;
            }
            if (arr[j][i] == 2) {
                count2++;
                if (count2 == 5) {
                    whoWon = 2;
                }

            } else {
                count2 = 0;
            }

        }
        if (whoWon != 1 && whoWon != 2) {
            whoWon = 3;
        }
    }
    return whoWon;
}

int game::verticalChecker(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[j][i] == 1) {
                count1++;
                if (count1 == 5) {
                    whoWon = 1;
                }

            } else {
                count1 = 0;
            }
            if (arr[j][i] == 2) {
                count2++;
                if (count2 == 5) {
                    whoWon = 2;
                }

            } else {
                count2 = 0;
            }

        }
        if (whoWon != 1 && whoWon != 2) {
            whoWon = 3;
        }
    }
    return whoWon;
}
int game::diagonalCheckerNegSlope(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[j][i] == 1) {

                for (int d = 0; (i + d < size) && (j + d < size); d++)
                    if (arr[i + d][j + d] == 1) {
                        count1++;
                        if (count1 == 5) {
                            whoWon = 1;
                        }
                    } else {
                        count1 = 0;
                    }

            }
            if (arr[j][i] == 2) {

                for (int d = 0; (i + d < size) && (j + d < size); d++)
                    if (arr[i + d][j + d] == 2) {
                        count2++;
                        if (count2 == 5) {
                            whoWon = 2;
                        }
                    } else {
                        count2 = 0;
                    }

            }

        }

    }
    if (whoWon != 1 && whoWon != 2) {
        whoWon = 3;
    }

    return whoWon;
}

int game::diagonalCheckerPosSlope(int arr[15][15], int size) {
    int count1;
    int count2;
    int whoWon = 0;

    for (int i = 0; i < size; i++) {
        count1 = 0;
        count2 = 0;
        for (int j = 0; j < size; j++) {
            if (arr[i][j] == 1) {

                for (int d = 0; (i + d < size) && (j - d < size); d++)
                    if (arr[i + d][j - d] == 1) {
                        count1++;
                        if (count1 == 5) {
                            whoWon = 1;
                        }
                    } else {
                        count1 = 0;
                    }

            }
            if (arr[i][j] == 2) {

                for (int d = 0; (i + d < size) && (j - d < size); d++)
                    if (arr[i + d][j - d] == 2) {
                        count2++;
                        if (count2 == 5) {
                            whoWon = 2;
                        }
                    } else {
                        count2 = 0;
                    }
            }
        }

    }
    if (whoWon != 1 && whoWon != 2) {
        whoWon = 3;
    }
    return whoWon;
}

int game::WholeWinnerChecker(int arr[15][15], int size) {
    int finalWinner = 0;
    int outcome1 = horizontalChecker(arr, size);
    if ((outcome1 == 1) || (outcome1 == 2)) {
        finalWinner = outcome1;
        cout << "Horizontal Win" << endl;
    }
    int outcome2 = verticalChecker(arr, size);
    if ((outcome2 == 1) || (outcome2 == 2)) {
        finalWinner = outcome2;
        cout << "Vertical Win" << endl;
    }
    int outcome3 = diagonalCheckerPosSlope(arr, size);
    if ((outcome3 == 1) || (outcome3 == 2)) {
        finalWinner = outcome3;
        cout << "Diag Pos Win" << endl;
    }
    int outcome4 = diagonalCheckerNegSlope(arr, size);
    if ((outcome4 == 1) || (outcome4 == 2)) {
        finalWinner = outcome4;
        cout << "Diag Neg Win" << endl;
    }

    else if ((finalWinner != 1) && (finalWinner != 2)) {
        finalWinner = 3;
    }

    return finalWinner;
}

void game::Play(int arr[15][15], int size) {
    int counter = 0;
    int Winner=0;
    int boardFull= size*size;
        while(((Winner != 1)&&(Winner != 2))&& (counter < boardFull)){
        cout << "This is turn " << counter + 1 << endl;
        if (counter % 2 == 0) {
            cout << "PlayerOne: " << endl;
            game::movePlayerOne(arr, size, counter);
            if (counter >= 4) {
                Winner = game::WholeWinnerChecker(arr, size);
                if(Winner ==1){
                cout << endl <<"======================" << endl;
                cout << "Winner = " << Winner << endl;
                cout <<"======================" << endl;
                }
            }
        }
        if (counter % 2 == 1) {
            cout << "PlayerTwo:" << endl;
            game::movePlayerTwo(arr, size);
            if (counter >= 5) {
                Winner = game::WholeWinnerChecker(arr, size);
                if (Winner == 2) {
                    cout << endl << "======================" << endl;
                    cout << "Winner = " << Winner << endl;
                    cout << "======================" << endl;
                }
            }
        }
        if(counter == boardFull){
            cout << "Draw" << endl;
        }

        counter++;

    }

}

我也一直在使用

6
C++ 算法 Gomoku

评论

0赞 user4581301 5/25/2022
这就是所谓的大量代码。它不适合像 Stack Overflow 这样的问答网站,因为它的数量要么不必要地隐藏了问题,要么保证问题是如此具体,以至于给出的任何解决方案对未来的提问者来说都毫无价值。我强烈建议制作一个最小的可重现示例(MRE),如果您在制作 MRE 时没有自己发现并修复错误,请将问题中的代码替换为 MRE。
0赞 pm100 5/25/2022
了解如何使用调试器。它会在这里帮助你,比 SO 能做的更多。最多需要 10 分钟才能完成调试器基础知识
0赞 Gabriella 5/25/2022
@user4581301 谢谢你的提示。所以我尝试制作一个 MRE,对角线检查器在那里运行良好。但是,当它放在主代码中时,有些东西不起作用,这就是为什么决定在下面添加其余代码的原因,并希望有人能够提供帮助。

答:

1赞 Dialecticus 5/25/2022 #1

问题可能是您没有设置 j 循环,而是依靠语句中要重置的变量。但是,如果你的 d 循环在语句执行之前结束(“过早”变为 false),则计数器不会被重置。解决方案:将零初始化移至 j 循环内部。count1count2elseelse(i + d < size) && (j - d < size)

一些改进:

如果许多方法具有相同的参数(例如 和 ),则这可能是这些参数应该成为类成员的标志。int arr[15][15]int size

可以只有一个检查器功能。此函数的参数将是搜索方向(int deltaX、int deltaY)以及正在检查的值(1 或 2)。所有 8 个方向的增量值如下:

(1, 0), (1, 1), (0, 1), (-1, 1), (-1, 0), (-1, 1), (0, 1), (1, 1)

因此,在 d 循环中,您不会对 和 进行加法或减法,但您总是会对 和 进行加法。dijdeltaXideltaYj

另外,有点高级,但也很有趣。可以以这样一种方式排列代码,您可以拥有三种类型的游戏:人与人、人与计算机、计算机与计算机。例如,您只需将一个类的对象分配给玩家 1,将一个类的对象分配给玩家 2。这将使您能够选择谁先玩,并且还有几种算法与之抗衡。这两个类都必须使用一些已知方法(如“move”)从基类派生,并且有些类会在循环中将此方法称为“move”,更新游戏状态,并检查游戏是否已结束。HumanPlayerComputerPlayerPlayerGameCoordinator