Реализация c++ крестики-нолики


Я написал простой код для крестики-нолики.

#include <iostream>
#include <vector>

void draw_board(const std::vector< std::vector<char> >& vec)
{
    std::cout << "    0   1   2  \n";
    std::cout << "  +---+---+---+\n";
    for (int i = 0; i < vec.size(); i++)
    {
        std::cout << i << " " ;
        for (int j = 0; j < vec[i].size(); j++)
        {
            std::cout << "| " << vec[i][j] << " ";
        }
        std::cout << "|";
        std::cout << '\n';
        std::cout << "  +---+---+---+\n";
    }
}

void enter(int row, int col, char ch, std::vector< std::vector<char> >& vec)
{
    vec[row][col] = ch;
}

bool check(const std::vector< std::vector<char> >& vec)
{
    //to check diagonals
    if ((vec[0][0] == 'X' && vec[1][1] == 'X' && vec[2][2] == 'X')
        || (vec[0][2] == 'X' && vec[1][1] == 'X' && vec[2][0] == 'X'))
        {
            std::cout << "Player X won this game\n";
            return true;
        }
    else if ((vec[0][0] == 'O' && vec[1][1] == 'O' && vec[2][2] == 'O')
             || (vec[0][2] == 'O' && vec[1][1] == 'O' && vec[2][0] == 'O'))
             {
                std::cout << "Player O won this game\n";
                return true;
             }

    //to check horizonatal and vertical
    for (int i = 0; i < vec.size(); i++)
    {
        if ((vec[i][0] == 'X' && vec[i][1] == 'X' && vec[i][2] == 'X')
              || (vec[0][i] == 'X' && vec[1][i] == 'X' && vec[2][i] == 'X'))
              {
                  std::cout << "Player X won this game\n";
                  return true;
              }
        else if((vec[i][0] == 'O' && vec[i][1] == 'O' && vec[i][2] == 'O')
              || (vec[0][i] == 'O' && vec[1][i] == 'O' && vec[2][i] == 'O'))
              {
                  std::cout << "Player O won this game\n";
                  return true;
              }
    }
}

void start(std::vector< std::vector<char> >& vec)
{
    int row, col, res = 0;
    char ch;

    std::vector<int> index = {0, 1, 2};

    for (int i = 0; i < vec.size(); i++)
    {
        for (int j = 0; j < vec[i].size(); j++)
        {
            vec[i][j] = ' ';
        }
    }

    for (int i = 0; i < 9;)
    {
        if (i == 0 || i%2 == 0)
        {
            ch = 'X';
            std::cout << "Chance to enter X\n";
        }
        else
        {
            ch = 'O';
            std::cout << "Chance to enter O\n";
        }
        std::cout << "Enter row number ";
        std::cin >> row;
        std::cout << "Enter column number ";
        std::cin >> col;
        if (vec[row][col] == ' ' || vec[row][col] == ' ')
        {
            enter(row, col, ch, vec);
            draw_board(vec);
            if ( i >= 2)
            {
                res = check(vec);
                if (res == 1)
                {
                    break;
                }
            }
            i++;
        }
        else
        {
            std::cerr << "This position already contains a character\n";
        }

    }
    if (res == 0)
    {
        std::cout << "This game draws\n";
    }
}

int main()
{
    std::vector< std::vector<char> > board(3, std::vector<char>(3));
    draw_board(board);
    start(board);
}


585
5
задан 3 апреля 2018 в 03:04 Источник Поделиться
Комментарии
2 ответа

Проверить ваш вклад в enter()

Вы не проверить, что пользователь ввел действительный индекс вектора. Например, если я вхожу в 3 как строку и/или столбец номер программа зависает. Вам следует отказаться от входа, если пользователь вводит недопустимое строку и/или столбец номер (например, вы будете делать, если пользователь выбирает пространство, которое уже занято).

Контроль пути check() должна возвращать значение

Вы только когда-либо return true в check(). Если ни один из проверить условия, то вы должны явно return false в конце функции.

Используйте правильный тип для индексации

У вас для петли, как for (int i = 0; i < vec.size(); i++)сравнение знаковое целое число i в беззнаковое целое vec.size(). Использовать std::vector< std::vector<char> >::size_type.

Использовать псевдоним типа / типа определение std::vector< std::vector<char> > контейнер

Использовать псевдоним типа как using container = std::vector< std::vector<char> >; если ваш компилятор поддерживает его, в противном случае использовать определение типа как typedef std::vector< std::vector<char> > container;. Вы можете положить его после #include заявления, так что вы можете использовать его для всех ваших функций. Это полезно по нескольким причинам:


  1. Это короткое имя для контейнера. Это очень удобно при обращении к контейнеру и/или его size_typeнапример: container::size_type короче и легче читать, чем std::vector< std::vector<char> >::size_type.

  2. Проще поменять контейнер. Вы, возможно, захотите использовать std::array вместо этого, в этом случае вам нужно только изменить using заявление, а не все экземпляры std::vector< std::vector<char> >.

4
ответ дан 3 апреля 2018 в 03:04 Источник Поделиться


  • Не объявлять несколько переменных в строке

  • Вы можете пропустить свой код инициализации для вектора и просто сделать это, когда вы объявляете его: std::vector< std::vector<char> > board(3, std::vector<char>(3, ' '));

  • Вы перепутали строки и столбцы

  • Вы не вернуться false в конце вашего проверить функцию, которая делает игра заканчивается после 3 поворотов.

  • index не представляется использовать?

4
ответ дан 3 апреля 2018 в 03:04 Источник Поделиться