我目前正在emu8086中创建一个简单的游戏程序。使用箭头键我能够在我想要的每个方向上打印星号。问题是要求如果我已经打印了5个星号,则应删除星号的尾部,这样我的星号的主体每次打印时都会保留5个。
从我的研究中,主要是使用数组,但我还不知道如何在数组中操作它,因为我不知道如何跟踪数组的尾部和位置,以便能够打印空间来删除尾部。
像:
1. *
2. *
3. *
4. *
5. *
单击方向后,它应该看起来像..
在这种情况下,它只是向下方向..如何组合其他方向?
1.
2.*
3.*
4.*
5.*
6.*
这是我的打印代码
continue:
mov ah, 2 ;print asterisk
mov dl, "*"
int 21h
continue2:
mov ch, 32 ;hide blinking cursor
mov ah, 1
int 10h
mov ah, 00h ;input direction
int 16h
cmp ah, up
je up
cmp ah, left
je left
cmp ah, down
je down
cmp ah, right
je right
答案 0 :(得分:1)
如果你知道蛇的最大长度,你可以使用所谓的"ring buffer"。
"阵列"在汇编中只是连续的内存区域,其结构由您的代码定义。
让我们说你最多会有蛇5个星号,然后我会使用6 [x,y]位置的缓冲来定义,5个位置是从头到尾的星号,第6个位置是前一个尾部位置,即空间被打印到"擦除"尾。
我实际上会在代码中重新安排一下,这样的缓冲区位置长一些2的功率(6的下一个2的功率是8,如果你的蛇会增长,填充屏幕,那么你需要80 * 25 =最多2000个位置,下一个2的幂是2048)。我会保持头部元素的索引(然后只是按照你的意愿选择指向下一个身体部位的方向,我可能会在init期间将头部放在最后,因此缓冲区[0]将包含"空间"尾部, buffer [1]最后一个星号" tail",... buffer [5]将是" head"星号,我会保持headIndex = 5(或者更确切地说是内存偏移量为headOffset = 10
,因为每个元素都是2个字节([x,y]
)和5 * 2 = 10)。
所以你有一些"环形缓冲区"对于数据部分中的身体部位位置:
BUFFER_SIZE EQU 2*8 ; or 2*2048 for growing snake
; everything will be "2*", because each position is 2 bytes big
snakeLength:
dw ?
headOffset:
dw ?
positions:
db BUFFER_SIZE DUP (?)
还有一些代码,它会将蛇的长度初始化为5,然后将positions
中的前6对字节作为蛇开始的位置(包括"空格"在第一个位置的尾巴!),并且头部偏移到10
(缓冲区中的第五个位置字节对)。
现在打印蛇,您将加载headOffset
和snakeLength
,然后执行" snakeLength"很多次:
positions + offset
获取两个字节,如[x,y] and <register with offset>,(BUFFER_SIZE-2)
,这将使它指向内存的最后一个元素,以防偏移量已经为0(这就是原因,为什么两个的力量,允许我环绕&# 34;环形缓冲区&#34;通过单and
指令和位屏蔽操作)。最后还有一次迭代,但这次是打印空间,而不是星号(对于最终元素)。
关于如何绘制在这样的数组中定义的蛇。
如何&#34;移动&#34;它在某个方向上,让我们说(-1,0)(在左边):
headOffset
值[positions + headOffset]
and <register with offset>,(BUFFER_SIZE-2)
指向缓冲区中的下一个元素[positions + offset]
headOffset
(这将使最后的尾部星号位置现在成为新的&#34;空间&#34;尾部,以及之前的&#34;空间&#34;尾部是不可及的用同样的蛇长度)。在您绘制这种新的数据状态后,蛇将会“移动”#34;向左一步。
如何生长蛇:与移动相同,但你也将snakeLength
更新为+1,因此缓冲区的最后两个元素仍用作前一个星号+空格尾部,使尾部保持在同一位置,而头向前移动。 (你可以用这种方法在每一步中只用+1来增长蛇,因为你不会在尾巴上添加新的身体部位......但是当你吃的时候,蛇的游戏确实有多大一些较大的食物会使你的蛇长出N个部分,它会在接下来的N个步骤中完成,而不是立即完成。
所以你有8个阵列的数组,其中只有6个使用。使用哪6个由headOffset
定义,它绕过并绕回(从偏移0开始&#34;向下&#34;回到偏移14(8 * 2-2),从偏移14开始up表示在偏移0处着陆,因此&#34;环形缓冲区&#34;正在变形,如#&#34;响铃&#34;,没有任何开头或结尾)。
替代方案是拥有6个阵列的数组,当您移动蛇时,您实际上将数组中的数据从位置 i 移动到位置 i-1 ,并且然后将新的头部位置写入最后一个数组元素。这可能在第一次尝试时更容易理解,但是&#34;环形缓冲区&#34;解决方案是优越的,因为你不必每次蛇移动时移动内存块,你只需添加新的头并调整偏移/长度数据,而不是移动内存中的位置,你移动你访问数据。 (1500条长蛇意味着通过设置一个新元素并更新偏移量来节省近3000字节memmove
)。这样做的代价是每次从一个元素移动到下一个元素时引入偏移扭曲逻辑(从偏移14到0和从0到14),但这是通过单个and
指令完成的,所以它将比复制缓冲区的内存快得多。