Возникли проблемы с получением моей игры … Есть мысли о том, что я мог бы сделать? Я просмотрел большую часть кода и инициализировал его, но по какой-то причине в большинстве функций говорится, что у меня нет подходящих точек. Кроме того, что drawBoard
не имеет типа пустоты. Пожалуйста помоги
Спасибо
#include <iostream>
using namespace std;
// initialize a 2d board (3,3) with asterisk
void drawBoard(char board[][]);
char check_Winner(char [][]);
int main(){
char board[3][3]={{'*','*','*'},{'*','*','*'},{'*','*','*'}};
bool win = false;
bool in_row = false;
bool in_col = false;
int row;
int column;// run a loop:
while (!win) {
// Display the content of the board
drawBoard(char board[][]));
cout << "Player 1's turn:";
// Ask player one to chose a location (row, column)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid)
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.\n";
// ask again (error: row in column not within range)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.\n";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}else {
valid = true;
}}
board[row-1][column-1] = 'X';
drawBoard(char board[][]);
// Check if someone won or if there is a tie
check_Winner(char board[][]);
// Ask player two to chose a location (row, column)
cout << "Player 2's turn:";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid)
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.\n";
// ask again (error: row in column not within range)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.\n";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}else
{
valid = true;
}
board[row-1][column-1] = 'O';
}
drawBoard(char board[][])
// Check if someone won or if there is a tie
check_Winner(char board[][]);
}
system("pause");
return 0;
}
char check_Winner(char board[][]){
char winner = 'T';
// Checks for horizontal:
for (int i = 0; i < 3; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
winner = board[i][0];
// Checks for vertical:
for (int i = 0; i < 3; i++)
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
winner = board[0][1];
// Checks for diagnol:
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) ||
(board[0][2] == board[1][1] && board[1][1] == board[2][0]))
winner = board[1][1];
// checking the result:
switch (winner) {
case 'T': cout << "IT'S A TIE";/* tie */ break;
case 'X': cout << "PLAYER 1 WON!";/* X won */ break;
case 'O': cout << "PLAYER 2 WON!";/* O won */ break;
default : cout << "NEXT PLAYER'S TURN...>"; continue;
}
}
void drawBoard(char board[][])
{
cout << " 1 2 3" << endl;
cout << " +---+---+---+" << endl;
cout << " 1" << " | " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " | " << endl;
cout << " +---+---+---+" << endl;
cout << " 2" << " | " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " | " << endl;
cout << " +---+---+---+" << endl;
cout << " 3" << " | " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " | " << endl;
cout << " +---+---+---+" << endl;
}
Я вставил ваш код в codepad.org и скомпилировал его. Первое сообщение об ошибке:
Строка 6: ошибка: объявление ‘board’ в качестве многомерного массива должно иметь границы для всех измерений, кроме первого
Другими словами — если вы не скажете компилятору что-то о размерах вашего двумерного массива, он не будет знать, как найти элемент. Это почему? Ну, когда вы получаете доступ к двумерному массиву из m x n элементов, a [i] [j], вы действительно вычисляете
*(a + n * i + j)
потому что каждый раз, когда вы увеличиваете строку i
пропускаешь другую n
элементы.
Еще один способ думать об этом — «2D» элементы — это действительно один большой блок. Если у тебя есть
0 1 2 3
4 5 6 7
8 9 10 11
Они действительно хранятся как
0 1 2 3 4 5 6 7 8 9 10 11
И вы найдете элемент [1] [1], скажем, вычисляя смещение (1D индекс, если хотите) 1 * 4 + 1 = 5
, И, конечно же, элемент 5 в линейном массиве имеет значение 5
, что вы бы нашли, пройдя один вниз и один поперек.
Мы исправим эту первую ошибку компилятора, заменив
void drawBoard(char board[][]);
char check_Winner(char [][]);
с
void drawBoard(char board[][3]);
char check_Winner(char [][3]);
(как в стороне, я не уверен, почему check_Winner
определяется как возвращение char
(у вас нет return Winner;
оператор в вашей функции …), и почему вы используете странное сочетание символов подчеркивания и заглавных букв в названии вашей функции. Мы вернемся к этому позже)
Далее компилятор жалуется на то, как вы вызываете эти функции. Вы должны называть их (в строке 23 и в других местах), а не как
drawBoard(char board[][]);
но просто как
drawBoard(board);
Поскольку вы уже определили, что вы передаете char
и вам не нужно [][]
напомнить компилятору о типе board
(вы определили это ранее).
Следующая ошибка (после исправления), которую выдает компилятор,
In function 'int main()':
Line 72: error: redeclaration of 'bool valid'
Действительно, вы определили
bool valid = false;
в строке 33. После этого, при обращении к той же переменной, вы не должны ставить bool
перед именем переменной — похоже, что вы (повторно) объявляете переменную. Просто положи
valid = true
в строке 72. (Кроме того, вы явно произвели копирование-вставку большого блока кода, и именно так закралась эта ошибка. Вы хотите серьезно подумать о поиске способа сделать «ход» единственной функцией, которая может быть призванным либо к игроку 1, либо к игроку 2 — тогда вам не нужно повторять весь этот код, и все будет выглядеть чище. И менее подвержено ошибкам.).
После исправления компилятор жалуется на строку 99:
In function 'int main()':
Line 99: error: expected ';' before 'check_Winner'
Как это часто бывает с подобными ошибками, проблема в строке раньше. Строка 97:
drawBoard(board)
отсутствует точка с запятой в конце, и должен быть
drawBoard(board);
После исправления компилятор жалуется на строку 130:
default : cout << "NEXT PLAYER'S TURN...>"; continue;
In function 'char check_Winner(char (*)[3])':
Line 130: error: continue statement not within a loop
continue
оператор используется, чтобы сказать «переходите прямо к следующей итерации цикла, в котором вы находитесь» (while
, for
…). Но вы используете его внутри switch
оператора, и нет цикла (в пределах функции, в которой вы находитесь), к которому может перейти код. Если вы просто оставите continue;
выкл, код продолжится просто отлично.
На самом деле (хотя это не совсем то, о чем вы спрашиваете), break'
не приведет к остановке программы; это просто приведет вас к концу функции, и код продолжит работу. Вот почему вам действительно нужно возвращаемое значение в вашем check_Winner
функция — и вам нужно проверить его после того, как вы его вызвали, чтобы вы могли предпринять соответствующие действия (распечатать сообщение и выйти из игры).
Вынимая continue
в строке 130 мы теперь нажали предупреждение в строке 133:
In function 'char check_Winner(char (*)[3])':
Line 133: warning: control reaches end of non-void function
Это говорит «вы объявили эту функцию, чтобы вернуть char
, но вы забыли положить в return
заявление! «. Добавить
return winner;
до окончания функции, и жалоба уходит.
Результатом всех этих правок является следующий код. Я не говорю, что это «хороший» код, но по крайней мере ошибки компилятора были удалены. Я надеюсь, что процесс, который я описал, будет полезен для вас в процессе обучения. У большинства компиляторов есть флаги для включения предупреждений и сообщений об ошибках; я сильно рекомендую вам всегда включить каждое предупреждение, которое вы можете, и обратите внимание на то, на что жалуется компилятор. Вы научитесь писать лучший код ..
отказ — Я писал это пока «в дороге», поэтому я мог использовать codepad.org только для базовой отладки. Он не позволяет интерактивное программирование, поэтому я не мог проверить, работает ли окончательный код — я могу только сказать вам, что он перестал жаловаться на ошибки в коде … Я на 99% уверен, что ваш check_Winner
В коде есть логические ошибки — например, вы начинаете с
winner = 'T';
Это означает, что вы будете называть ничью, если не выполнено одно из других условий; Я думаю, что вы должны вызывать ничью, только если у вас нет звездочек (если вы хотите быть по-настоящему умным, вы можете назвать ничью, когда нет возможного решения, но это гораздо сложнее для кода).
В любом случае — вот код, который компилируется. Думаю, еще есть чем заняться, прежде чем вы получите рабочую игру
#include <iostream>
using namespace std;
// initialize a 2d board (3,3) with asterisk
void drawBoard(char board[][3]);
char check_Winner(char board[][3]);
int main(){
char board[3][3]={{'*','*','*'},{'*','*','*'},{'*','*','*'}};
bool win = false;
bool in_row = false;
bool in_col = false;
int row;
int column;// run a loop:
while (!win) {
// Display the content of the board
drawBoard(board);
cout << "Player 1's turn:";
// Ask player one to chose a location (row, column)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
bool valid = false;
while (!valid)
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.\n";
// ask again (error: row in column not within range)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.\n";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}else {
valid = true;
}}
board[row-1][column-1] = 'X';
drawBoard(board);
// Check if someone won or if there is a tie
check_Winner(board);
// Ask player two to chose a location (row, column)
cout << "Player 2's turn:";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
// check if move is valid
//check if location has astericks and its between 0 thru 2
valid = false;
while (!valid)
{
//check if the move is within range.
if(!(row <= 3 && row >= 1 && column <= 3 && column >= 1)){
cout << "Error: Either the row or column is not within range of the board.\n";
// ask again (error: row in column not within range)
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}
else if(board[row-1][column-1] != '*')
{
cout << "Error: The (row,column) is already occupied.\n";
cout << "What is the row:?\n";
cin >> row;
cout << "What is the column?\n";
cin >> column;
}else
{
valid = true;
}
board[row-1][column-1] = 'O';
}
drawBoard(board);
// Check if someone won or if there is a tie
check_Winner(board);
}
system("pause");
return 0;
}
char check_Winner(char board[][3]){
char winner = 'T';
// Checks for horizontal:
for (int i = 0; i < 3; i++)
if (board[i][0] == board[i][1] && board[i][1] == board[i][2])
winner = board[i][0];
// Checks for vertical:
for (int i = 0; i < 3; i++)
if (board[0][i] == board[1][i] && board[1][i] == board[2][i])
winner = board[0][1];
// Checks for diagnol:
if ((board[0][0] == board[1][1] && board[1][1] == board[2][2]) ||
(board[0][2] == board[1][1] && board[1][1] == board[2][0]))
winner = board[1][1];
// checking the result:
switch (winner) {
case 'T': cout << "IT'S A TIE";/* tie */ break;
case 'X': cout << "PLAYER 1 WON!";/* X won */ break;
case 'O': cout << "PLAYER 2 WON!";/* O won */ break;
default : cout << "NEXT PLAYER'S TURN...>";
}
return winner;
}
void drawBoard(char board[][3])
{
cout << " 1 2 3" << endl;
cout << " +---+---+---+" << endl;
cout << " 1" << " | " << board[0][0] << " | " << board[0][1] << " | " << board[0][2] << " | " << endl;
cout << " +---+---+---+" << endl;
cout << " 2" << " | " << board[1][0] << " | " << board[1][1] << " | " << board[1][2] << " | " << endl;
cout << " +---+---+---+" << endl;
cout << " 3" << " | " << board[2][0] << " | " << board[2][1] << " | " << board[2][2] << " | " << endl;
cout << " +---+---+---+" << endl;
}
Постскриптум.
Я не эксперт по C ++ ни в какой степени воображения. Но люди, которые являются склонны настаивать на том, чтобы не использовать using namespace std;
и вместо этого написать
std::cout << "hello world" << std::endl;
и т. д. По мере того, как ваш код усложняется, становится все более очевидным, какая функция / константа принадлежит какому классу. Итак, мне сказали … Смотрите Почему "используя пространство имен std" считается плохой практикой? . И вопрос, и ответ получили ОЧЕНЬ много голосов … предполагая, что это важная вещь, о которой думают люди. Читайте дальше принятого ответа … внизу этой страницы есть несколько жемчужин.
Могу ли я предложить вам использовать typedef для вашей доски?
typedef char tttboard[3][3];
Ваша доска объявлений:
tttboard board={{'*','*','*'},{'*','*','*'},{'*','*','*'}};
ваши функции будут выглядеть так: (по ссылке!)
void drawBoard(tttboard& board);
char check_Winner(tttboard& board);
И, как вам сказали в комментарии, вы называете это без char
а также [][]
как это:
drawBoard(board);
check_Winner(board);