我在设计一种算法时遇到了麻烦,这种算法几乎可以像使用包含线上所有点的数组一样在蛇形游戏中移动一条线。我会做点像......
for (int x = 0; i < array.length; i++) {
array[i] = array[i+1]
}
array[array.length] = (the new point)
但这会每秒发生很多次而且非常慢。我想做类似的事情,但不是每次都移动每个数字,而是保持在数组中的相同位置,但保存一个int以跟踪下一个将被删除的哪个以及哪个将包含新的数字。 如果你知道我刚才说的话,请帮助我。感谢
答案 0 :(得分:4)
使用circular buffer。这可以使用数组和两个索引来实现(一个用于头部,一个用于尾部)。如果蛇总是有相同的长度,你可以使用一个索引。
使用这样的结构,您需要的整个操作可以在恒定时间内完成(即与阵列的大小无关)。
答案 1 :(得分:1)
你认为每次移动所有的块都很慢是正确的。
有一种更有效的方法。
每次移动时,只有最后一个位置的第一个位置发生变化。
所以,如果你有你的蛇array[i]
和一个“头”标记head
,那么你可以简单地将head
推进到你的阵列中并覆盖头部移动到的位置的下一个位置转动。
你刚刚覆盖的地方?这就是尾巴的位置,你不再需要了它。
如果蛇长大会变得有点棘手,但不会太多。
(NPE指出,数据结构是一个循环缓冲区。)
答案 2 :(得分:0)
int front, back, length; // 0<=front,back<length
increaseLength()
{
back--;
if(back<0)
back=length-1;
}
goForward()
{
front++;
back++;
if (front==length)
front=0;
if (back==length)
back=0;
}
checkFull() // check every time you increase length
{
if (back==front)
return true;
return false;
}
答案 3 :(得分:0)
NPE是正确的,循环缓冲区是最佳解决方案。这是使用C ++的循环缓冲区的简单示例。注意模数运算符而不是if
测试。
#include <iostream>
int main(int argc, char **argv)
{
int front = 4;
int back = 0;
int length = 10;
int snake[10] = { 1,1,1,1,1,0,0,0,0,0 };
for (int i = 0; i < length * 3; i++)
{
for (int j = 0; j < length; j++)
std::cout << snake[j] << " ";
std::cout << std::endl;
snake[back] = 0;
front = (front + 1) % length;
back = (back + 1) % length;
snake[front] = 1;
}
}
输出:
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
1 1 1 1 1 0 0 0 0 0
0 1 1 1 1 1 0 0 0 0
0 0 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 0
0 0 0 0 0 1 1 1 1 1
1 0 0 0 0 0 1 1 1 1
1 1 0 0 0 0 0 1 1 1
1 1 1 0 0 0 0 0 1 1
1 1 1 1 0 0 0 0 0 1
注意输出如何很好地证明了蛇“移动”通过缓冲区。