winston mcnair Ответов: 4

Нужна помощь с программой C++ tic tac toe


Я хочу, чтобы программа печатала "вы выиграли", когда задается любой из экземпляров функции champion (). Он показывает победителя только тогда, когда вводится "123". Всякий раз, когда три X отображаются в другом месте, программа продолжается. Например, если три X заданы по диагонали, программа все равно будет продолжаться. Начинающий программист так что любая критика очень ценится.

#include <iostream>
#include <string>
#include<cstdio>
#include <stdlib.h>

#define GRID_SIZE 3

class TicTacToe {
private:
    char map[GRID_SIZE][GRID_SIZE];
    
public:
    
     void computers_turn() {
        while (true) {
            int choice = (rand() % 9) + 1 ;
            
            int row = choice / 3;
            int col = choice % 3;
            char grid_position = map[row][col];
            
            if (grid_position == 'X' || grid_position == 'O') {
                std::cout << "Space taken. Try again" << std::endl;
            } else {
                map[row][col] = (char) 'O';
                break;
            }            
        }            
    }
    
    void champion() {
        const char *possiblities[8] = {
            "123",
            "456",
            "789",
            "147",
            "258",
            "369",
            "159",
            "753"
        };
        
        for (int i = 0; i < 8; i++) {            
            char previous_pos = '0';
            const char *possible_moves = possiblities[i];
            bool winner = true;
            
            for (int index = 0; index < GRID_SIZE; index++) {
                char character = possible_moves[index];
                int entered_num = character - '0';
                int grid_space = entered_num - 1;
                
                int row = index / GRID_SIZE;
                int col = index % GRID_SIZE;
                
                char grid_coordinate = map[row][col];                
                
                if (previous_pos == '0') {
                    previous_pos = grid_coordinate;
                } else if
                    (previous_pos == grid_coordinate) {
                        continue;
                    } else {
                        winner = false;
                        break;
                    }
            }
            if (winner ) {
                puts("You win");
                exit(0);                
            }            
        }              
    }
    
    void playgame() {
        std::string input;
        
        while (true) {
            puts( "Go player one");
            getline(std::cin, input);
            if (input != "") {
                char entered = input.c_str()[0];
                
                if (entered >= '1' && entered <= '9') {
                    int entered_num = entered - '0';
                    int index = entered_num - 1;
                    int row = index / 3;
                    int col = index % 3;
                    char grid_position = map[row][col];
                    
                    if (grid_position == 'X' || grid_position == 'O') {
                        std::cout << "Space taken. Try again" << std::endl;
                    } else {
                        map[row][col] = (char) 'X';
                        break;
                    }                    
                } else {
                    std::cout << "Only numbers 1 - 9" << std::endl;
                }
            } else {
                std::cout << "Have to enter something, try again" << std::endl;
            }                  
        }
    }
    
    void generateGrid() {
        int number = 1;
        
        for (int x = 0; x < GRID_SIZE; x++) {
            for (int y = 0; y < GRID_SIZE; y++) {
                map[x][y] = std::to_string(number).c_str()[0];
                number += 1;
            }
        }
    }
    
    void tictacToeMap() {                
        std::cout << std::endl;
        
        for (int x = 0; x < GRID_SIZE; x++) {
            for (int y = 0; y < GRID_SIZE; y++) {
                std::printf(" %c ", map[x][y]);
            }
            std::cout << std::endl;
        }        
    }    
    
    TicTacToe() {
        generateGrid();        
        
        while (true) {        
            tictacToeMap();
            champion();
            playgame();                               
        }
    }
};

int main( int argc, char *argv[] ) {
    TicTacToe letsplat;
        
    return 0;    
}


Что я уже пробовал:

Я перепробовал все, что я знаю, чтобы исправить это, но я не могу понять это.

4 Ответов

Рейтинг:
2

CPallini

Попробуй

bool champion()
{
  int possibilities[8][3] =
  {
    {0,1,2},
    {3,4,5},
    {6,7,8},
    {0,3,6},
    {1,4,7},
    {2,5,8},
    {0,4,8},
    {6,4,2}
  };

  for (size_t i = 0; i<8; ++i)
  {
    size_t j = 0;
    for ( ; j <3; ++j)
    {
      size_t r = possibilities[i][j] / 3;
      size_t c = possibilities[i][j] - r * 3;
      if ( map[r][c] != 'X')
        break;
    }
    if (j == 3)
    {
      puts("you win");
      return true;
    }
  }
  return false;
}
и
 TicTacToe() 
{
  generateGrid();
  while (true) 
  {
    tictacToeMap();
    if ( champion() ) break;
    playgame();
  }
}


KarstenK

запускать весь код в конструкторе-не самая лучшая идея. :-O

CPallini

По крайней мере, это не моя идея. :-)

merano99

Метод игры также может быть улучшен:

void playgame() {
  std::string input;

  while (true) {
	puts("Go player one");
	getline(std::cin, input);
	if (input != "") {
		int index = std::stoi(input) - 1;
		if ((index >= 0) && (index <= 8)) {
			int row = index / 3;
			int col = index % 3;
			char grid_position = map[row][col];
			...

Рейтинг:
2

merano99

С исправлением ошибки Palinis было бы хорошей идеей разделить определение класса от
реализация.

class TicTacToe {
public:
	TicTacToe();
	void computers_turn();
	bool champion();
	void playgame();
	void generateGrid();
	void tictacToeMap();

private:
	char map[GRID_SIZE][GRID_SIZE];
	int possibilities[8][3] = {
		{ 0,1,2 },
		{ 3,4,5 },
		{ 6,7,8 },
		{ 0,3,6 },
		{ 1,4,7 },
		{ 2,5,8 },
		{ 0,4,8 },
		{ 6,4,2 } };
};

// Constructor
TicTacToe::TicTacToe()
{
	generateGrid();
}

...

int main(int argc, char *argv[]) 
{
	TicTacToe letsplay;

	while (!letsplay.champion())
	{
		letsplay.tictacToeMap();
		letsplay.playgame();
	}

	return 0;
}


Вместо использования поля "возможности" следует рассчитать ситуацию с прибылью. Возможно, вы захотите изменить размер поля позже ...


Рейтинг:
1

Patrice T

Цитата:
Начинающий программист так что любая критика очень ценится.
...
Я перепробовал все, что я знаю, чтобы исправить это, но я не могу понять это.

Ваш код ведет себя не так, как вы ожидаете, или вы не понимаете, почему !

Существует почти универсальное решение: запускайте свой код на отладчике шаг за шагом, проверяйте переменные.
Отладчик здесь, чтобы показать вам, что делает ваш код, и ваша задача-сравнить с тем, что он должен делать.
В отладчике нет никакой магии, он не знает, что должен делать ваш код, он не находит ошибок, он просто помогает вам, показывая, что происходит. Когда код не делает того, что ожидается, вы близки к ошибке.
Чтобы увидеть, что делает ваш код: просто установите точку останова и посмотрите, как работает ваш код, отладчик позволит вам выполнять строки 1 на 1 и проверять переменные по мере их выполнения.

Отладчик - Википедия, свободная энциклопедия[^]

Освоение отладки в Visual Studio 2010 - руководство для начинающих[^]
Базовая отладка с помощью Visual Studio 2010 - YouTube[^]

1.11 — отладка программы (пошаговое выполнение и останова) | выучить C++[^]

Отладчик здесь только для того, чтобы показать вам, что делает ваш код, и ваша задача-сравнить его с тем, что он должен делать.


Рейтинг:
0

Stefan_Lang

I have tried everything I know

Вы не пытались использовать свой компилятор, чтобы он генерировал предупреждения и реагируя на них (переменная character не используется). Если он не генерировал это предупреждение, используйте-Wall, чтобы сделать это так.

Кроме того, вы должны были попробовать отладчик чтобы посмотреть, что происходит. Тогда вы быстро поняли бы, что в вашем champion функция, вы никогда не проверяете ячейки в нижних строках: row всегда равно 0 И это 0, потому что вы вычисляете его как index/3, где index это значение находится в диапазоне от 0 до 2 ...

Ошибка в том, что вы должны использовать character здесь-нет index.

Урок, который следует усвоить здесь, таков: научитесь использовать инструменты, которые у вас есть. При правильном использовании они помогут вам гораздо больше, чем вы можете себе представить.

P.S.: Еще один совет, который может помочь вам распознать ошибки еще до того, как компилятор коснется вашего кода: используйте значимые имена переменных.

Это включает в себя переменные цикла, особенно если у вас есть вложенные циклы: using 'i' и 'index- это не очень полезно. Называя их 'i_possibility' и 'string_pos- вместо этого было бы гораздо яснее, и, возможно, вы заметили бы, что не очень разумно определять индекс строки и столбца на основе ... string_pos'.
row = string_pos / GRID_SIZE; // this doesn't look right to me. How about you?
А также имя 'character- это очень плохая нежить: характер-это его тип, а не его значение! Значение, хранящееся в этой переменной, представляет собой индекс в вашей матрице крестиков-ноликов, так почему бы не назвать его matrix_index? Тогда код для определения вашей строки будет следующим
row = matrix_index / GRID_SIZE;