我决定制作一个2048命令行版,但我无法获得合适的磁贴运动......
我目前的结构是电路板是一个二维阵列(4x4)的整数。当收到一个输入时,它会尝试在该方向上推动每个图块(忽略值为0的图块),如果注意到它将重新开始更改(因为底行上的图块必须一直向上,不只是一步)。然而,这样的副作用是以下问题:
[2] [2] [4]使用命令 - >应该给[0] [4] [4]但是因为它重新开始,程序将能够合并4和4并获得[0] [0] [8] intead ...
另一个难题是[4] [4] [8] [8]应该给出[0] [0] [8] [16]所以我不能在合并后停止。
下面的代码是我的processCommand函数。它需要一个板和一个输入(即“d”,“你”,“l”或“r”。如果游戏注意到游戏,它将把“gameover”作为输入)。它不是很漂亮,我试图为移动的瓷砖做一个单独的循环(如果你写“l”,一个值horiz将为-1,如果你写“r”它将是1然后我移动瓷砖横向水平,但我无法做到这一点。)
任何关于如何做到这一点的想法(以及对我的编程的批评)将不胜感激!
func processCommand(board [][]int, input string) {
board_new := board
switch input {
case "d":
for i := 0; i < height - 1; i++ {
for j := 0; j < width; j++ {
if board[i][j] == 0 {
continue
}
if board[i + 1][j] == 0 || board[i + 1][j] == board[i][j] {
board_new[i + 1][j] = board[i + 1][j] + board[i][j]
board_new[i][j] = 0
i = 0
j = 0
change = true
}
}
}
case "u":
for i := 1; i < height; i++ {
for j := 0; j < width; j++ {
if board[i][j] == 0 {
continue
}
if board[i - 1][j] == 0 || board[i - 1][j] == board[i][j] {
board_new[i - 1][j] = board[i - 1][j] + board[i][j]
board_new[i][j] = 0
i = 1
j = 0
change = true
}
}
}
case "l":
for i := 0; i < height; i++ {
for j := 1; j < width; j++ {
if board[i][j] == 0 {
continue
}
if board[i][j - 1] == 0 || board[i][j - 1] == board[i][j] {
board_new[i][j - 1] = board[i][j - 1] + board[i][j]
board_new[i][j] = 0
i = 0
j = 1
change = true
}
}
}
case "r":
for i := 0; i < height; i++ {
for j := 0; j < width - 1; j++ {
if board[i][j] == 0 {
continue
}
if board[i][j + 1] == 0 || board[i][j + 1] == board[i][j] {
board_new[i][j + 1] = board[i][j + 1] + board[i][j]
board_new[i][j] = 0
i = 0
j = 0
change = true
}
}
}
case "gameover":
gameOver = true
default:
processCommand(board, input)
}
board = board_new
}
答案 0 :(得分:5)
目前,您始终从上到下和从左到右扫描您的瓷砖,与玩家的移动无关。然而,对于2048年,最好以与玩家移动相反的方向扫描,因为瓷砖只会在该方向上合并。例如,让我们采取以下方案:
0 0 2 0 |
0 0 2 2 | Player move
0 2 4 8 v
2 32 4 2
让我们假设玩家的移动方向朝向底部,因此我们开始从底部向顶部扫描。在第三列中,我们需要首先合并4 + 4然后合并2 + 2,即从下到上。沿着那个方向进行允许你合并4 + 4,然后将列的最底部字段标记为合并,从而不允许进一步合并(由数字周围的括号表示):
0 0 0 0 |
0 0 2 2 | Player move
0 2 2 8 v
2 32 (8) 2
在合并最底部的单元格(如果可能的话)之后,我们继续进行上面的单元格等等......
0 0 0 0 |
0 0 0 2 | Player move
0 2 (4) 8 v
2 32 (8) 2
[...]
0 0 (0) 0 |
0 0 (0) 2 | Player move
0 2 (4) 8 v
2 32 (8) 2
当不再有可能进行合并时,移动结束并移除所有“合并”标记,我们等待下一轮。此方法可修复多重合并问题。
扫描方向的另一个例子(数字现在表示循环如何在字段中运行):
Player move
---->
4 3 2 1
8 7 6 5
12 11 10 9
16 15 14 13
查看代码,注意到有关循环的代码重复很多。对于每个case
,您执行单独的嵌套for
- 循环,这不是最佳选择。相反,你可能会做这样的事情:
for i := 1; i < height; i++ {
for j := 0; j < width; j++ {
if board[i][j] == 0 {
continue
}
switch input {
case "d":
updateBoardDown(board, i, j)
case "u":
updateBoardUp(board, i, j)
[...]
}
}
}