Как я могу определить, какие плитки перемещаются и сливаются в моей реализации 2048?
Я создаю игру 2048 WinForms для удовольствия.
Обратите внимание, что речь идет не о 2048 AI. Я просто пытаюсь сделать игру 2048, которую могут сыграть люди.
Сначала я решил использовать 0-17 для представления плиток. 0 представляет собой пустую плитку. 1 представляет собой 2 плитки. 2 представляет собой 4 плитки. 3 представляет собой 8 плиток и т.д.
Затем я подумал о том, как вычислить полученную доску, учитывая направление движения и доски перед движением. Вот о чем я думал:
- Чтобы двигаться вверх, он просто поворачивает доску против часовой стрелки на 90 градусов, перемещается влево, затем поворачивает плату обратно
- Чтобы двигаться вправо, он просто поворачивает плату по часовой стрелке на 180 градусов, перемещается влево, затем поворачивается назад
- Чтобы двигаться вниз, он просто поворачивает плату по часовой стрелке на 90 градусов, перемещается влево, а затем поворачивается назад.
Поэтому мне просто нужно выяснить, как вычислить полученную доску, когда игрок движется влево, тогда я могу просто определить остальные направления, вращая доску, двигаюсь влево и поворачиваясь назад. Затем я пришел с этим довольно странным алгоритмом для перемещения слева.
Так вот как я оцениваю каждую строку:
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]
.
Ответы
Ответ 1
Я не думаю, что превращение в персонажей действительно добавляет что-нибудь полезное. Если вы придерживаетесь представления числа (0 = пустое), вы можете использовать следующую логику, чтобы найти как целевую конфигурацию, так и какой блок отправился туда. Это псевдокод (row
задана):
fromTo = [-1, -1, -1, -1];
result = [0, 0, 0, 0];
prevVal = 0;
pos = 0;
for (i = 0; i < 4; i++) {
if (row[i]) { // Not empty
if (row[i] == prevVal) {
result[pos-1]++; // merged
fromTo[i] = pos-1;
prevVal = 0; // avoid triple merge
} else {
result[pos] = row[i];
fromTo[i] = pos;
prevVal = row[i];
pos++;
}
}
}
Теперь массив fromTo
будет указывать для каждого индекса, куда пошел блок в этом исходном положении. result
будет иметь окончательные значения. Из этих двух частей информации вы также можете узнать, какие блоки были объединены. Блок в исходном положении я объединяется в result[fromTo[i]] != row[i]
. Вы также знаете расстояние, на которое будет двигаться блок: i - fromTo[i]
. Короче говоря, у вас есть вся информация, чтобы настроить анимацию для каждого блока.
Примеры
row | fromTo | result
------------+----------------+-----------
[0,1,0,1] | [-1,0,-1,0] | [2,0,0,0]
[0,1,1,1] | [-1,0,0,1] | [2,1,0,0]
[1,1,1,1] | [0,0,1,1] | [2,2,0,0]
[1,2,2,3] | [0,1,1,2] | [1,3,3,0]