【问题标题】:Connect-N game in C check for wins functions not workingC中的Connect-N游戏检查获胜功能不起作用
【发布时间】:2017-11-23 01:47:03
【问题描述】:

我正在尝试编写一个程序来玩 Connect-N 游戏,它基本上是 Connect-4,但用户确定棋盘的大小(不一定是正方形)和连续获胜的棋子数(这可能大于棋盘的大小——如果棋盘是 3x3,用户可以指定您需要 4 块才能获胜,而我的代码必须将游戏打成平局,因为不可能获胜)。我正在检查 4 种情况:水平赢、垂直赢、左对角赢和右对角赢。我写出了实际检查胜利的逻辑步骤,然后尝试将其转换为代码。但是,当我运行实际程序时,即使玩家获胜,它也会不断返回这是一场平局游戏,只有当所有 4 个获胜函数都返回 false 时才能达到。谁能发现我的代码中的错误?

这是我的代码: (仅供参考,变量pieces代表X或O)

横胜:

bool horizontalWin(char **board, const int numRows, const int numCols, const char blankSpace, const int numToWin, const char pieces) {
  int match = 0;

  if (numCols < numToWin) {
    return false;
  }
  else {
    for (int row = 0; row < numRows; ++row) {
      for (int col = 0; col <= numCols - numToWin; ++col) {
        for (int k = 0; k < numToWin; ++k) {
          if (board[row][col + k] != pieces) {
            match = 0;
          }
          else {
            ++match;
            if (match == numToWin) {
              return true;
            }
          }
        }
      }
    }
  }
  return false;
}

垂直赢:

bool verticalWin(char **board, const int numRows, const int numCols, const char blankSpace, const int numToWin, const char pieces) {
  int match = 0;

  if (numRows < numToWin) {
    return false;
  }
  else {
    for (int col = 0; col < numCols; ++col) {
      for (int row = 0; row <= numRows - numToWin; ++row) {
        for(int k = 0; k < numToWin; ++k){
          if (board[row + k][col] != pieces) {
            match = 0;
          }
          else {
            ++match;
            if (match == numToWin) {
              return true;
            }
          }
        }
      }
    }
  }
  return false;
}

左对角线:

bool leftDiagonalWin(char **board, const int numRows, const int numCols, const char blankSpace, const int numToWin, const char pieces) {
  int match = 0;

  if (numCols < numToWin || numRows < numToWin) {
    return false;
  }
  else {
    for (int row = 0; row <= numRows - numToWin; ++row) {
      for (int col = 0; col <= numCols - numToWin; ++col) {
        for (int k = 0; k < numToWin; ++k) {
          if(board[k][k] != pieces) {
            match = 0;
          }
          else {
            ++match;
            if (match == numToWin) {
              return true;
            }
          }
        }
      }
    }
  }
  return false;
}

右对角线:

bool rightDiagonalWin(char **board, const int numRows, const int numCols, const char blankSpace, const int numToWin, const char pieces) {
  int match = 0;

  if (numCols < numToWin || numRows < numToWin) {
    return false;
  }
  else {
    for (int row = numRows - 1; row >= numRows - numToWin; --row) {
      for (int col = 0; col <= numCols - numToWin; ++col) {
        for (int k = 0; k < numToWin; ++k) {
          if (board[numRows - 1 - k][col + k] != pieces) {
            match = 0;
          } else {
            ++match;
            if (match == numToWin) {
              return true;
            }
          }
        }
      }

    }
  }
  return false;
}

编辑:这是我用来创建板的函数:

char** createBoard(const int numRows, const int numCols, const char blankSpace) {
  char** board = (char**) malloc(numRows * sizeof(char*));
  for (int row = 0; row < numRows; ++row) {
    board[row] = (char*) malloc(numCols * sizeof(char));
    for (int col = 0; col < numCols; ++col) {
      board[row][col] = blankSpace;
    }
  }
  return board;
}

【问题讨论】:

  • 横胜太复杂了。为什么需要 3 个循环?只需计算您在这一行中看到了多少正确的部分 - 当您看到错误的部分时重置为 0。只需要 rows 和 cols 循环,而不需要额外的“k” - 与垂直相同,但这次你想先遍历列然后再遍历行。对角线比较复杂,需要一些想法。
  • 这些函数是怎么调用的?我很好奇board是如何在主程序中声明的。
  • @AlexP 在 main.c 中,我使用 char** board = createBoard(numRows, numCols, blankSpace);我会将 createBoard 添加到我的帖子中。

标签: c iteration


【解决方案1】:

您的横向解决方案太复杂了。 “blankSpace”参数甚至没有被使用或需要。这是一个非常简化的版本:

bool horizontalWin(char **board, const int numRows, const int numCols,
                  const int numToWin, const char piece) {

    int match = 0;

    for (int row = 0; row < numRows; ++row) {
        for (int col = 0; col <= numCols; ++col) {
            match = (board[row][col] == piece) ? (match + 1) : 0;
            if (match == numToWin) {
                break;
            }
        }
     }
    return (match >= numToWin);
}

您也几乎可以为verticalWin 函数复制同样的逻辑。

【讨论】:

  • 你对对角函数有什么见解吗?我真的很苦恼如何在没有第三个 for 循环的情况下迭代对角线。
  • 您可以进行的最简单的优化之一是使用最后一块的位置作为如何扫描的提示。例如,如果最后一块被丢弃在 row=4,column=3,那么您只需要垂直扫描第 3 列和水平扫描第 4 行。它也将使您的对角线逻辑更容易。
【解决方案2】:

我知道这已经晚了:(但这就是我的做法,希望对您有所帮助

    //check win
int checkWin(char *board){
    return (horizontalCheck(board) || verticalCheck(board) || diagonalCheck(board));
}

int checkFour(char *board, int a, int b, int c, int d){
    //board[a] = won;
    //board[b] = won;
    //board[c] = won;
    //board[d] = won;
    return (board[a] == board[b] && board[b] == board[c] && board[c] == board[d] && board[a] != ' ');
}

int horizontalCheck(char *board){
    int row, col, idx;
    const int WIDTH = 1;

    for(row = 0; row < BOARD_ROWS; row++){
       for(col = 0; col < BOARD_COLS - 3; col++){
          idx = BOARD_COLS * row + col;
          if(checkFour(board, idx, idx + WIDTH, idx + WIDTH * 2, idx + WIDTH * 3)){
             return 1;
          }
       }
    }
    return 0;
}

int verticalCheck(char *board){
    int row, col, idx;
    const int HEIGHT = 7;

    for(row = 0; row < BOARD_ROWS - 3; row++){
       for(col = 0; col < BOARD_COLS; col++){
          idx = BOARD_COLS * row + col;
          if(checkFour(board, idx, idx + HEIGHT, idx + HEIGHT * 2, idx + HEIGHT * 3)){
              return 1;
          }
       }
    }
    return 0;
}

//diagonal check for win
int diagonalCheck(char *board){
   int row, col, idx, count = 0;
   const int DIAG_RGT = 6, DIAG_LFT = 8;

   for(row = 0; row < BOARD_ROWS - 3; row++){
      for(col = 0; col < BOARD_COLS; col++){
         idx = BOARD_COLS * row + col;
         if(((count <= 3) && (checkFour(board, idx, idx + DIAG_LFT, idx + DIAG_LFT * 2, idx + DIAG_LFT * 3))) ||
             ((count >= 3) && (checkFour(board, idx, idx + DIAG_RGT, idx + DIAG_RGT * 2, idx + DIAG_RGT * 3)))){
            return 1;
         }
         count++;
      }
      count = 0;
   }
   return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-29
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2016-04-15
    相关资源
    最近更新 更多