【问题标题】:Tic Tac Toe Generating Combinations of Boards C++井字游戏生成板 C++ 组合
【发布时间】:2018-02-19 01:48:46
【问题描述】:

注意:这是课堂作业,必须以这种方式完成,我知道这效率低下,我并不是要求我完成作业,我只是需要一些指导我做错了什么。

我想创建一个函数,生成所有可能的井字游戏组合,格式为“xoxxooxox”,每三个字母代表一排棋盘。当我调用函数时,我需要它返回一个向量。

到目前为止,我所拥有的是一个 循环,它可以生成 0,1 和 2 的所有可能的 9 位组合,直到 19683,这只是 3^9 的板组合。然后我让它将 0 转换为 #(这意味着一个空格),将 1 转换为“o”,将 2 转换为“x”。

#include<iostream>
#include<vector>
#include<string>
using namespace std;
vector<string> get_all_boards() {

  vector<int> numboard;
  std::string board;
  for(int i = 0; i < 19683; ++i) {
    int c = i;
    for (int j = 0; j < 9; ++j) {

      int playnum = c % 3;
        if (playnum == 0) {
        playnum = 35;
        numboard.push_back(playnum);
      } else if (playnum == 1) {
        playnum = 111;
        numboard.push_back(playnum);
      } else if (playnum == 2) {
        playnum = 120;
        numboard.push_back(playnum);
      }
      c /= 3;
    }
    for (auto x : numboard) {
      board += static_cast<char>(x);
    }
    std::copy( board.begin(), board.end(), std::back_inserter(numboard));
  }
}
int main() {
  get_all_boards();
}

我不确定如何检查它是否在输出我想要的内容,并且我收到“错误分配”的错误。有没有更有效的方法来做到这一点?如何修复错误的分配错误?

【问题讨论】:

  • board 是您尝试将 int 放入的字符串向量
  • 你知道很多 19683 组合是不可能的吧?例如“呜呜呜”……
  • 补充@John3136 所说的,您需要消除已经赢得/平局的位置(继续比赛没有意义),并考虑将删除大量重复位置的旋转和反射。
  • 使用极小极大算法解决最佳可能移动
  • 你不会 static_cast int's to char 来获得一个 int 的字符串表示。将 int 转换为 char 使用 ASCII 表进行转换。

标签: c++ c++11 vector tic-tac-toe


【解决方案1】:

对于井字游戏,生成每一个可能的 X 和 O 组合是多余的。由于玩家交替进行,一个完全填满的棋盘将正好有 5 个 X 和 4 个 O。所以要生成一堆板子,只需从一个简单的板子开始,然后生成所有可能的排列:

#include <algorithm>
#include <cstddef>
#include <iostream>
#include <string>

int main() {
    std::string board = "XXXXXOOOO";
    std::sort(std::begin(board), std::end(board));
    do {
        std::cout << board << '\n';
    } while (std::next_permutation(std::begin(board), std::end(board));
    return 0;
}

但是请注意,这些棋盘中有许多代表不可能的位置。例如,第一个是不可能的,因为它有连续三个 X 和连续三个 O。

【讨论】:

    【解决方案2】:

    假设玩家先输入“x”,那么组合的数量比你想象的要少很多,

    • 让 A 表示“x”的数量
    • 让 B 表示“o”的数量

    比 A = B+1 或 A=B

    所以你必须考虑以下排列:

    • A = 0,B = 0
    • A = 1,B = 0
    • A = 1,B = 1
    • A = 2,B = 1
    • A = 2,B = 2

    等等,

    对于每种情况,排列的数量可以计算如下:

    9!/( (9-A-B)!*A!*B!)

    例如,如果 A = 3 且 B = 2 第一个 X:9 个选项 第二个 X:8 个选项 第三个 X:7 个选项 第一个O:6个选项 第二个O:5个选择

    即9*8*7*6*5,即9!/(9-A-B)!

    但我们还没有完成,因为“X”和“O”是相同的,你必须将它除以 3!还有 2 个!

    所以这种情况的总排列是 9!/(4!*3!*2!)

    -A B 排列

    -0 0 1

    -1 0 9

    -1 1 72

    -2 1 252

    -2 2 756

    -3 2 1260

    -3 3 1680

    -4 3 1260

    -4 4 630

    -5 4 126

    总计 = 6046

    你也需要代码吗?

    【讨论】:

    • 谢谢,但这是课堂作业,很遗憾,它需要按照我上面概述的方式完成。我只是想知道我的代码做错了什么以及任何修复它的方法
    【解决方案3】:

    此代码将为您提供所有排列,请注意其中很多是不可接受的,因为 Os 的数量和 X 的数量可能相差不超过一个

    {{{
    #include "stdafx.h"
    #include<iostream>
    #include<vector>
    #include<string>
    using namespace std;
    
    std::string ConvertPermutationToString( int permutation )
    {
        std::string board = "#########";
    
        int counter = 0;
    
        while ( permutation > 0 )
        {
            switch ( permutation %3 )
            {
            case 0: 
                //do nothing
                break;
    
            case 1:
                board[counter] = 'O';
                break;
    
            case 2:
                board[counter] = 'X';
                break;
            }
    
            counter++;
            permutation = permutation/3;
        }
    
        return board;
    }
    vector<string> get_all_boards() {
    
    
      std::string board;
      vector<string> allBoards;
      for(int i = 0; i < 19683; ++i) {
          allBoards.push_back( ConvertPermutationToString( i ) );
      }
    
      return allBoards;
    }
    
    int main() {
      get_all_boards();
    }
    
    }}}
    

    现在如果你想过滤掉不好的组合,使用下面的代码

    #include "stdafx.h"
    #include<iostream>
    #include<vector>
    #include<string>
    #include<math.h>
    using namespace std;
    
    std::string ConvertPermutationToString( int permutation )
    {
        std::string board = "#########";
    
        int counter = 0;
        int xCount = 0;
        int oCount = 0;
    
        while ( permutation > 0 )
        {
            switch ( permutation %3 )
            {
            case 0: 
                //do nothing
                break;
    
            case 1:
                board[counter] = 'O';
                oCount++;
                break;
    
            case 2:
                board[counter] = 'X';
                xCount++;
                break;
            }
    
            counter++;
            permutation = permutation/3;
        }
    
        if ( abs( xCount - oCount ) > 1 ) 
        {
            board = "";
        }
    
        return board;
    }
    vector<string> get_all_boards() {
    
    
      std::string board;
      vector<string> allBoards;
      for(int i = 0; i < 19683; ++i) {
    
          board = ConvertPermutationToString( i );
    
          if ( board.length() )
          {
            allBoards.push_back( ConvertPermutationToString( i ) );
          }
      }
    
      return allBoards;
    }
    
    int main() {
      get_all_boards();
    }
    

    您有 8953 种可接受的组合

    【讨论】:

      猜你喜欢
      • 2022-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 2015-06-12
      相关资源
      最近更新 更多