Я пишу игру Connect 4 с минимаксом, но моя функция проверки следующего шага иногда дает неожиданные результаты. Подскажите, пожалуйста, правильный ли мой алгоритм?
Например, если моя доска выглядит так
0000000
0000000
0000000
0000000
1000000
2002120
он вернет колонку 0 как true для игрока 2.
bool Board::check2(int player, int& bestMove)
{
for (int i=0; i<WIDTH; i++)
{
if(addToColumn(i, player))
{if (checkNext(2, i, player))
{
bestMove=i;
removeFromColumn(i, player);
return true;
}
removeFromColumn(i, player);
}
}
return false;
}bool Board::checkNextVertical(int size, int column, int player1)
{
int counter=0;
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
for (int i=0 ; i<DEPTH; i++)
{
if (arrBoard[column][i]==player1)
{
counter++;
}
if (arrBoard[column][i]==player2)
{
return false;
}
if (counter==size)
{
return true;
}}
return false;
}
bool Board::checkNextHorizontal(int size, int column, int player1)
{
int counter=0;
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
for (int i=0 ; i<DEPTH; i++)
{
if (arrBoard[i][column]==player1)
{
for (int j = 0; j<WIDTH; j++)
{
if (arrBoard[i][j]==player1)
{
counter++;
}
if (arrBoard[i][j]!=player1)
{
counter=0;
}
if (counter==size)
{
return true;
}}
}
}
return false;
}
bool Board::checkNext(int size, int column, int player)
{
if (checkNextVertical(size, column, player))
{
// printBoard();
return true;
}if (checkNextHorizontal(size, column, player))
{
// printBoard();
return true;
}return false;
}
Добро пожаловать на форум.
Есть несколько проблем с кодом, который вы разместили:
Ваш checkNextVertical
функция пытается проверить по горизонтали, и ваш checkNextHorizontal
Похоже, что функция пытается проверить как по горизонтали, так и по вертикали.
Если вы заметили, что вы используете оба arrBoard[column][i]
а также arrBoard[i][column]
, Я уверен, что вы согласитесь, что только один из них может быть правильным. Важно понять, что является правильным, иначе ваш код будет пытаться получить доступ к недопустимым местоположениям в массиве, и вы получите непредвиденное поведение, например, ваш j
петля в checkNextHorizontal
функция в настоящее время делает это.
Следует использовать как array[y / depth / row][x / width / column]
— или что вы будете помнить.
Лично этот код кажется запутанным:
int player2;
if (player1==1)
{
player2=2;
}
else
player2=1;
player2=1
похоже на попытку протолкнуть квадратный колышек в круглое отверстие. Не могли бы вы использовать int player
и установите его либо 1
или же 2
чтобы было легче читать?
Я полностью согласен с Joachim — если у вас есть такие проблемы, всегда полезно заполнить массив некоторыми данными, а затем использовать отладчик для просмотра кода и проверки того, что данные, к которым вы обращаетесь, — это те данные, которые вы ожидаете получить. доступ.
В качестве альтернативы, поскольку это игра connect4, я предполагаю, что в какой-то момент вы знаете столбец, в котором был сделан последний ход, и в этом случае вы можете использовать эту функцию, чтобы проверить, был ли это выигрышный ход. Вам просто нужно указать, какой столбец был последним ходом, и требуемый «размер» для победы. Если вы используете его, я бы по-прежнему рекомендовал пройти через него с помощью отладчика, чтобы вы могли понять доступ к массиву. NB: ваш код не проверялся по диагонали — так же как и это. Требуется дополнительная логика, если вы хотите сделать это:
bool winningMove(int column, int size)
{
bool winnerWinnerChickenDinner = false;
int player = 0;
int row = 0;
// Who was the last player to go in this column
// i.e. find the top non-zero entry
for (int i = 0; i < DEPTH; i++)
{
if (arrBoard[i][column] != 0)
{
player = arrBoard[i][column];
row = i;
break;
}
}
// If we found a player, check if it was a winning move
if (player != 0)
{
int count = 0;
// Loop twice, first horizontally, then vertically
for (int i = 0; i < 2 && !winnerWinnerChickenDinner; i++)
{
bool horizontal = (i == 0);
for (int j = 0; j < (horizontal ? WIDTH : DEPTH); j++)
{
// Check if we have 'size' consecutive entries by the same player
// (When we check horizontally, use arrBoard[row][j] to check the row)
// (When we check vertically, use arrBoard[j][column] to check the column)
if (arrBoard[(horizontal ? row : j)][(horizontal ? j : column)] == player)
{
if (++count == size)
{
winnerWinnerChickenDinner = true;
break;
}
}
else
{
count = 0;
}
}
}
}
return winnerWinnerChickenDinner;
}
Старые игры самые лучшие — Connect4 потрясающий, так что удачи.
Других решений пока нет …