在连接 4 C++算法中检查获胜者

Checking Winner in connect 4 C++ Algorithm

本文关键字:检查 获胜者 算法 C++ 连接      更新时间:2023-10-16

我已经在这些代码段上呆了几个小时,我被困在这一段代码所需的算法上。我讨厌成为发布整个代码的人,但我觉得这是必要的,这样你才能理解它。我完全被困在如何检查获胜者上。我认为可以递归完成,但在与一些人交谈后,他们说这不是最好的方法。我完全不知道如何解决这个问题。

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <iostream>
/**
 * @brief Check if a winner exists
 *
 * @param pBoard The board
 * @param colSize The column size
 * @param rowSize The row size
 *
 * @return The character of the winner, 0 for no winner, and 't' for a tie
 */
char checkWinner(char** pBoard, int colSize, int rowSize, int winSize) {
    // TODO
    **This is where the algorithm needs to go.**
    return 0;
}
/**
 * @brief Place a piece onto the board
 *
 * @param pBoard The game board
 * @param colSize The column size
 * @param rowSize the row size
 * @param columnSelection The column selection
 * @param player The players characterS
 *
 * @return True if the piece was placed, else false
 */
bool placePiece(char** pBoard, int colSize, int rowSize, int columnSelection, char player)
{
    // TODO
    int row = rowSize-1;
    while (pBoard[row][columnSelection]!= ' ' && row > 0){
        row--;
    }
    std::cout << row << std::endl;
    if (pBoard[row][columnSelection] == ' ') {
        pBoard[row][columnSelection] = player;
        return true;
    }   else{
        std::cout << "The space is full." << std::endl;
        return false;
    }
}
/**
 * @brief Print out the game board
 *
 * @param pBoard The game board
 * @param colSize The column size
 * @param rowSize The row size
 */
void printBoard(char** pBoard, int colSize, int rowSize) {
    for (int i = 0; i <= rowSize; ++i){
    std::cout << "|" << i;
    }
    std:: cout << "|" << std::endl;
    for (int i = 0; i < rowSize; ++i){
        std::cout << "|";
        for (int j = 0; j < colSize; ++j){
            std::cout << pBoard[i][j] << "|";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}
int main()
{
    bool running = true;
    printf("Welcome to connect four!n");
    srand (time(NULL));
    int32_t connectedPiecesToWin = 0;
    int32_t rowSize = 0;
    int32_t colSize = 0;
    // setup game
    std::cout << "How many connected pieces does it take to win?" << std::endl;
    std::cin >> connectedPiecesToWin;
    rowSize = connectedPiecesToWin + 2;
    colSize = connectedPiecesToWin + 3;
    std::cout << "You have selected " << connectedPiecesToWin << " in a row with a game board of " << colSize
<< " x " << rowSize << std::endl;
    // setup board
    char** pBoard = NULL; // TODO create the game board

    // initialize board
    pBoard = new char*[rowSize];
    for (int i = 0; i < rowSize; ++i){
        pBoard[i] = new char[colSize];
    }
    for(int i = 0; i < rowSize; ++i){
        for(int j = 0; j < colSize; ++j){
            pBoard[i][j]= ' ';
        }
    }

    // play
    char winner = 0;
    char player = 'p';
    do
    {
        int columnChoice = 0;
        do
        {
            if (player == 'p')
            {
                printBoard(pBoard, colSize, rowSize);
                std::cout << "Player's column: ";
                std::cin >> columnChoice;
            }
            else
            {
                // computers turn
                columnChoice = rand() % colSize;
            }
        } while (!placePiece(pBoard, colSize, rowSize, columnChoice, player));
        winner = checkWinner(pBoard, colSize, rowSize, connectedPiecesToWin);
        player = (player == 'c') ? 'p' : 'c';
    } while (running && winner == 0);
    printBoard(pBoard, colSize, rowSize);
    if (winner == 't')
    {
        std::cout << "Too bad, the game was a tie!" << std::endl;
    }
    else if (winner == 'c')
    {
        std::cout << "Oh man, you lost to a computer that randomly places pieces!" << std::endl;
    }
    else
    {
        std::cout << "Congrats! You won!" << std::endl;
    }
    // cleanup
    // TODO cleanup the board
    for (int i = 0; i < rowSize; ++i){
        delete[] pBoard[i];
    }
    delete[] pBoard;
    return 0;
}

暴力方法是测试每个单元格,以查看它是否在任何有效方向上连接到连接的 PiecesToWin 片段,因此首先编写一个例程,如果 0,0 处的单元格是获胜单元格,则返回 true:

    选择一个偏移量进行搜索,例如 -1
  • ,-1 进行对角线搜索
  • 对于该偏移量:
    • 检查与目标单元格偏移的单元格是否为相同颜色。
    • 如果是,则递增计数器并再次执行相同的测试在偏移单元的偏移量处(此处有一点递归(
    • 当您撞到墙上或同色单元格的数量大于或等于 connectedPiecesToWin.
  • 选取下一个偏移量 (-1,0(、(
  • 0,-1(、(1,1( 等。
  • 如果您搜索所有八个方向并且没有得到胜利返回假。

然后,这个例程是在整个董事会中搜索获胜单元的关键,或者只是检查刚刚做出的举动是否创造了胜利。

还是我错过了什么?

由于这显然是家庭作业,我将在不提供实际代码的情况下为您提供幼稚的策略。

对于任何位置 (x,y(,如果有四块相同颜色的棋子水平、垂直或对角线排列,则为赢家。 因此,让我们看看 RED 在水平方向上获胜的情况:

(x,y)    (x+1,y)  (x+2,y)  (x+3,y)
RED      RED      RED      RED

类似的坐标算术也适用于其他安排。 因此,您实际上只需要查看数组中从 (0,0( 到 (width-4,height-4( 的每个位置(除了在不同范围内操作的对角线情况之一(,并从该位置开始进行"获胜测试"。

更聪明的获胜测试只会检查最近播放的棋子周围的区域。