Я создаю игру 2048 WinForms для удовольствия.
Обратите внимание, что речь идет не о 2048 AI. Я просто пытаюсь сделать игру 2048, которую могут сыграть люди.
Сначала я решил использовать 0-17 для представления плиток. 0 представляет собой пустую плитку. 1 представляет собой 2 плитки. 2 представляет собой 4 плитки. 3 представляет собой 8 плиток и т.д.
Затем я подумал о том, как вычислить полученную доску, учитывая направление движения и доски перед движением. Вот о чем я думал:
- Чтобы двигаться вверх, он просто поворачивает доску против часовой стрелки на 90 градусов, перемещается влево, затем поворачивает плату обратно
- Чтобы двигаться вправо, он просто поворачивает плату по часовой стрелке на 180 градусов, перемещается влево, затем поворачивается назад
- Чтобы двигаться вниз, он просто поворачивает плату по часовой стрелке на 90 градусов, перемещается влево, а затем поворачивается назад.
Поэтому мне просто нужно выяснить, как вычислить полученную доску, когда игрок движется влево, тогда я могу просто определить остальные направления, вращая доску, двигаюсь влево и поворачиваясь назад. Затем я пришел с этим довольно странным алгоритмом для перемещения слева.
- Преобразуйте каждый из начальных целых чисел в символы, добавив 96 и отбрасывая на
char
. Теперь обратный тик (') представляет собой пустую черепицу,a
представляет собой 2 плитки,b
представляет собой 4 плитки и т.д., А также путь кp
. - Объедините символы, чтобы сформировать 4 строки, каждая из которых представляет ряд досок.
-
Примерная панель может выглядеть так:
aa'' '''' '''b ''cb
-
Для каждой строки,
- Удалите все обратные тики
- Используйте регулярное выражение (да, я использую регулярное выражение в игре 2048)
([ap])\1
и получаю первое совпадение строки. - замените первый матч новой плиткой
- сопоставьте остальную часть строки, которая еще не была сопоставлена, пока не будет найдено больше совпадений.
- Вставьте строку вправо, если она содержит менее 4 символов.
- Поверните каждую строку обратно в массив целых чисел, вычитая 96
Так вот как я оцениваю каждую строку:
int[] EvaluateRow(int[] row) {
// RowToString converts an int[] to a string like I said above
StringBuilder rowString = new StringBuilder(RowToString(row));
rowString.Replace("'", "");
var regex = new Regex("([a-p])\\1");
int lastIndex = -1;
while (true) {
var match = regex.Match(rowString.ToString(), lastIndex + 1);
if (match.Success) {
// newChar is the new tile after the merge
char newChar = (char)(match.Value[0] + 1);
rowString.Remove(match.Index, match.Length);
rowString.Insert(match.Index, newChar);
lastIndex = match.Index;
Score += // some calculation for score, irrelevant
} else {
break;
}
}
// StringToRow converts a string to an int[]
return StringToRow(rowString.ToString());
}
Тем не менее, есть действительно большая проблема с моим текущим алгоритмом. Этот алгоритм говорит мне только о конечном результате движения, но я не знаю, какой ящик для картинок (я использую окна с картинками, чтобы показывать плитки). Мне нужно перемещать, сколько пробелов должно быть перемещено в каждом поле изображения, и какой снимок ящики должны показать новое изображение. Я действительно не хочу использовать другое решение, и хочу внести некоторые изменения в свое текущее решение.
Вот что мне нужно получить от каждой строки (строки):
-
List<(int x, int spaces)>
. Каждый элемент представляет, какую плиту нужно перемещать (координату x) и сколько пробелов он должен перемещать (spaces
). -
List<int>
. Каждый элемент представляет x координаты плиток, которые объединены.
Как я могу получить эту информацию из строки строки? Пример:
Строка строки:
'a'a
будет создавать список, подобный [(1, 1), (3, 3)]
и другой список, подобный [1]
.