Сравнение значений всех соседних элементов массива
Дано: двумерный массив - 4 строки, 4 столбца. Необходимо сравнить на равенство значение каждого элемента этого массива со значением предыдущего элемента, следующего элемента, а также со значением элементов "над" и "под" сравниваемым. Как грамотно это можно сделать?
Попытался вот так вот коряво, но этот код не сравнивает элементы "по краям" массива.
bool gameover = true;
int mapSize = 4;
for (int i = 1; i < mapSize - 1; i++)
{
for (int j = 1; j < mapSize - 1; j++)
{
if (labelsMap[i, j].Text == labelsMap[i - 1, j].Text || labelsMap[i, j].Text == labelsMap[i, j - 1].Text || labelsMap[i, j].Text == labelsMap[i, j + 1].Text || labelsMap[i, j].Text == labelsMap[i + 1, j].Text)
{
gameover = false;
}
}
}
if (gameover)
{
MessageBox.Show("Игра окончена!");
}
Ответы (3 шт):
Тут нужно понимать, что
labelsMap[i, j].Text == labelsMap[i + 1, j].Text
это то же самое, что и
labelsMap[i, j].Text == labelsMap[i - 1, j].Text
для следующей i. Поэтому нужно сравнивать элементы с 0 по 2 вперёд и вниз. И всё.
P. S. Разъясняю. Вперёд и вниз означает со следующим элементом по строке и по столбцу. Выглядеть это может примерно так:
int lim = mapSize - 1;
for (int i = 0; i < lim; i++) {
for (int j = 0; j < lim; j++)
if (labelsMap[i, j].Text == labelsMap[i + 1, j].Text
|| labelsMap[i, j].Text == labelsMap[i, j + 1].Text)
{ gameover = false; break; }
if (!gameover) break;
if (labelsMap[i, lim].Text == labelsMap[i + 1, lim].Text
|| labelsMap[lim, i].Text == labelsMap[lim, i + 1].Text)
{ gameover = false; break; }
}
Таким образом будут выполнены все сравнения, а для последней строки и последнего столбца ещё одна команда условия.
P. P. S. @MarkShcerbakov++. Ну, и выход нужно добавить, чтоб совсем хорошо было.
Проблемма в том что крайние клетки не обрабатыватся совсем. У них тоже есть соседи просто их меньше.
Предлгаю вынести код который ищет соседий в отдельный метод, условия добавленны что бы не выйти за пределы поля:
private IEnumerable<(int x, int y)> GetNeighboursIndexes(int x, int y, int maxX, int maxY)
{
if (x > 0)
yield return (x - 1, y);
if (x < maxX)
yield return (x + 1, y);
if (y > 0)
yield return (x, y - 1);
if (y < maxY)
yield return (x, y + 1);
}
Что бы не работать в алгоритме с полями предлагаю сделать маленькую вспомогательную функцию которая достает значение из поля
private string GetMapValue(YoureMapType[,] map, int x, int y) => map[x, y].Text;
Ну и сама функция которая пробегает по каждой клетке, получает соседей клетки и если хоть одна совпадает то считаем что проиграли
public bool IsGameOver(YoureMapType[,] map)
{
var height = map.GetLength(1);
var width = map.GetLength(0);
for (var x = 0; x < width; x++)
{
for (var y = 0; y < height; y++)
{
var currentValue = GetMapValue(map, x, y);
var neighbours = GetNeighboursIndexes(x, y, width - 1, height - 1);
foreach (var neighbour in neighbours)
{
var neighbourValue = GetMapValue(map, neighbour.x, neighbour.y);
if (neighbourValue == currentValue)
{
return false;
}
}
}
}
return true;
}
Такой вариант позволяет проверить весь массив, включая последний столбец и последнюю строку, исключив вероятность возникновения IndexOutOfRangeException
:
private void CheckIfGameOver()
{
bool gameover = true;
int mapSize = 4;
for (int i = 0; i < mapSize; i++)
{
for (int j = 0; j < mapSize; j++)
{
if (i < mapSize - 1 && labelsMap[i, j].Text == labelsMap[i + 1, j].Text)
{
gameover = false;
break;
}
if (j < mapSize - 1 && labelsMap[i, j].Text == labelsMap[i, j + 1].Text)
{
gameover = false;
break;
}
}
}
if (gameover)
{
MessageBox.Show("Игра окончена!");
}
}
ув. @rotabor, благодарю за подсказки.