gpt4 book ai didi

c# - 我如何确定在我的 2048 实现中移动和合并了哪些图 block ?

转载 作者:可可西里 更新时间:2023-11-01 08:11:52 27 4
gpt4 key购买 nike

我正在构建一个 2048 WinForms 小游戏只是为了好玩。

请注意,这与 2048 AI 无关.我只是想制作一款人类可以玩的 2048 游戏。

我首先决定使用 0-17 来表示方 block 。 0 代表一个空瓦片。 1 代表 2 block 。 2 代表 4 block 。 3 代表 8 block ,依此类推。

然后我就在考虑如何计算结果板,给定移动方向和移动前的板。这是我的想法:

  • 要向上移动,就是逆时针旋转90度,向左移动,然后向后旋转
  • 要向右移动,就是将棋盘顺时针旋转180度,向左移动,然后向后旋转
  • 要向下移动,只需将棋盘顺时针旋转 90 度,向左移动,然后向后旋转。

所以我只需要弄清楚当玩家向左移动时如何计算结果板,然后我可以通过旋转板、向左移动和向后旋转来计算其余的方向。然后我提出了这个非常奇怪的向左移动算法。

  • 通过添加 96 并转换为 char 将每个初始板的整数转换为字符.现在反勾号 (`) 表示一个空图 block ,a代表 2 个图 block ,b代表 4 个方 block ,依此类推,一直到 p。 .
  • 将字符连接起来形成 4 个字符串,每个字符串代表棋盘的一行。
  • 示例板可能如下所示:

    aa``
    ````
    ```b
    ``cb
  • 对于每个字符串,

    • 去掉所有的反勾
    • 使用正则表达式(是的,我在 2048 游戏中使用了正则表达式)([a-p])\1并获取字符串的第一个匹配项。
    • 用新图 block 替换第一个匹配项
    • 匹配字符串中尚未匹配的其余部分,直到找不到更多匹配项为止。
  • 如果字符串少于 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());
}

但是,我当前的算法存在一个非常大的问题。这个算法只告诉我移动的最终结果,但我不知道我需要移动哪个图片框(我正在使用图片框来显示瓷砖),每个图片框应该移动多少空间,以及哪张图片盒子需要显示新图像。我真的不想使用其他解决方案,只想对当前的解决方案进行一些更改。

以下是我需要从每一行(字符串)中获取的内容:

  • A List<(int x, int spaces)> .每个元素代表哪个图 block 需要移动(x 坐标),以及它应该移动多少空间(spaces)。
  • A List<int> .每个元素表示合并到的图 block 的 x 坐标。

如何从行字符串中获取这些信息?示例:

行字符串:

`a`a

将生成类似 [(1, 1), (3, 3)] 的列表和另一个列表,如 [1] .

最佳答案

我认为转换为字符并没有真正添加任何有用的东西。如果您坚持使用数字表示法(0 = 空),那么您可以使用以下逻辑来查找目标配置哪个 block 去了哪里。这是伪代码(给出了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 数组将为每个索引指示原始位置的 block 去了哪里。 result 将具有最终值。从这两条信息中,您还可以知道合并了哪些 block 。当 result[fromTo[i]] != row[i] 时,原始位置 i 的 block 被合并。您还知道 block 将移动的距离:i - fromTo[i]。简而言之,您拥有为每个 block 设置动画的所有信息。

例子

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]

关于c# - 我如何确定在我的 2048 实现中移动和合并了哪些图 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48871936/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com