贪食蛇男的贪食蛇

贪食蛇男 2011-05-26 11:08:27
加精
WIN32汇编的贪食蛇,体积可想而知。好像代码有点长,CSDN不支持,分几段吧。

;*********************************************************************************
; 程 序: snake.exe *
; 源文件: snake.asm *
; 环 境: masmplus 1.2 *
; 编 译: ml /c /coff /Fo"snake.obj" ".\snake.asm" *
; 链 接: link /out:snake.exe /subsystem:windows /merge:.rdata=.text snake.obj *
; 作 者: hiroyukki *
; 日 期: 2011.03.04 *
; 玩 法: P: 暂停和继续 C: 切换颜色模式 上下左右WASD键: 调整蛇头方向 *
; Q或ESC: 退出游戏 N: 开始新游戏 *
; 说 明: 模型如下,因为总共的格子是有限的,所以我采取了静态内存的方法,以 *
; 避免每吃一个食物就申请一次内存的麻烦,在程序初始化时,就把所有空格上 *
; 的结点初始化好了,类似内存池的机制。 *
; 程序共 23 * 17 = 391个格子,故在 data? 域申请 391 个 DWORD。这些 *
; DWORD的4个字节从高到低分别表示一个结点的 x位置 y位置 结点类型(食物还 *
; 是蛇身,绘制时根据此指定不同颜色) 有效标志(即蛇到达的位置的结点才是 *
; 有效的)。 *
; 程序时刻记录着当前头的结点,在每次移动时根据方向不同来获取下一个 *
; 将要到达的位置,如果该位置是墙或蛇身,则撞死,否则把下一个位置上的结 *
; 点标志为有效(同时应该把当前蛇尾标志为无效)。 *
; 当前的所有有效结点都存放在另一个数组中,此数组看做一个结点的链表 *
; 数组的第一个元素是蛇尾,最后一个非0元素是蛇头。每当吃掉一个食物或者 *
; 前进一步,视做换掉了蛇头。但是不一样的是,吃掉食物时只简单地把新结点 *
; 放到数组的第一个0元素,即成为新的蛇头。而前进的情况下,在数组最后加 *
; 入新结点后,要把蛇尾,即数组中第一个结点移除,做法是把数组后面的结点 *
; 依次左移。绘制时其实是使用这个链表里的元素进行绘制,所以要保持链表里 *
; 元素与全局结点列表里的相应元素同步。 *
; 共 23 * 17个结点,第一个结点位置为 (1, 1),最后一个为(23, 17)。 *
; 这些结点在一个一维数组中,则由 (x, y)得到相应结点在一维数组中的索引的 *
; 公式为 (y - 1) * 23 + (x - 1) *
; 为了进一步减小可执行文件体积,合并了只读数据段和代码段,然后使用 *
; upx 压,EXE为 4096 bytes 。 *
;*********************************************************************************

.386
.model flat, stdcall
option casemap:none
;***************************************************************************
; Include
;***************************************************************************
include windows.inc
include gdi32.inc
includelib gdi32.lib
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
includelib Coredll.lib

;***************************************************************************
; 这个结构并未使用,只是大致描述下一个结点的样子,一个节点是一个DWORD *
; 从高位到低位分别是: x坐标 y坐标 类型(食物或蛇身) 有效标志 *
; 每个字段点一个字节 *
;***************************************************************************
Node struct
x BYTE ?
y BYTE ?
ntype BYTE ?
bValid BYTE ?
Node ends

TIMER equ 1
FOOD equ 0
BODY equ 1
RIGHT equ 2
LEFT equ 3
UP equ 4
DOWN equ 5
;***************************************************************************
; 数据段
;***************************************************************************

.data?
hInstance dd ?
hWinMain dd ?
hDc dd ?
isPaused dd ?
isAlive dd ?
bRanColor dd ?
bTurnPending dd ?
direction dd ?
food dd ?
nodes dd 391 dup (?)
nodeList dd 391 dup (?)
curX dd ?
curY dd ?
foodX dd ?
foodY dd ?
score dd ?
rClient RECT <>
wndWidth dd ?
wndHeight dd ?
szScoreBuffer db 32 dup (?)
seed dd ?
speed dd ?
timerCounts dd ?
eatCounts dd ?

.const
szClassName db '1', 0
szCaptionMain db '贪食蛇', 0
szCaptionPause db '已暂停', 0
szCaptionDie db '游戏结束,请按N键开始新游戏', 0
szDown db '下', 0
szUp db '上', 0
szRight db '右', 0
szLeft db '左', 0
szScore db '得分:%d', 0

;***************************************************************************
; 代码段
;***************************************************************************
.code
;***************************************************************************
; 随机数生成
;***************************************************************************
_NextInt proc uses edx ebx max
push edx
invoke GetTickCount
add eax, seed
add seed, eax
xor edx, edx
mov ebx, max
div ebx
xor seed, eax
mov eax, edx
inc eax
pop edx
ret
_NextInt endp

;***************************************************************************
; 初始化所有蛇身结点把前三个置为有效
;***************************************************************************
_InitNodes proc
push edi
push edx
push ebx
push ecx
xor edi, edi
@@:
xor edx, edx
mov eax, edi
mov ebx, 17h
div ebx
; 商是 y 坐标,余数是 x 坐标
xor ecx, ecx
or ecx, edx
inc ecx
shl ecx, 8
or ecx, eax
inc ecx
shl ecx, 8
or ecx, BODY
shl ecx, 8
; ecx 为结点, ebx 为有效结点列表
; nodeList 数组首元素即蛇尾,最后一个不为0的元素为蛇头
xor ebx, ebx
.if edi < 4
or ecx, 1
mov ebx, ecx
.endif
mov [offset nodes + edi * 4], ecx
mov [offset nodeList + edi * 4], ebx
inc edi
.if edi >= 187h
jmp @F
.endif
jmp @B
@@:
pop ecx
pop ebx
pop edx
pop edi
ret
_InitNodes endp

;***************************************************************************
; 节点构造函数,参数分别是X坐标,Y坐标,类型(食物还是身体),有效标志
;***************************************************************************
_CreateNode proc nx, ny, nntype, nInvalid
xor eax, eax
or eax, nx
shl eax, 8
or eax, ny
shl eax, 8
or eax, nntype
shl eax, 8
or eax, nInvalid
ret
_CreateNode endp

;***************************************************************************
; 查看指定结点是否在(x, y)
;***************************************************************************
_IsNodeAt proc node, x, y
push ebx
push ecx

mov eax, node
mov ebx, eax
mov ecx, eax
shr ebx, 24
and ebx, 0ffh
sub ebx, x

shr ecx, 16
and ecx, 0ffh
sub ecx, y

.if ecx == 0 && ebx == 0
xor eax, eax
.endif

pop ecx
pop ebx
ret
_IsNodeAt endp

;***************************************************************************
; 绘制单个节点
;***************************************************************************
_DrawNode proc uses ebx ecx _hDC, hNode
local @stColor: COLORREF
local @hBrush: HBRUSH
local @hOldBrush: HBRUSH
local @stRect: RECT
push ecx
push ebx

mov eax, hNode
; 先取标志状态,如果是无效,直接退出
and eax, 000000ffh
.if !eax
jmp @F
.endif
invoke _IsNodeAt, hNode, curX, curY
mov ecx, eax
mov eax, hNode
and eax, 0000ff00h
shr eax, 8
.if (eax == BODY) && (ecx == 0)
mov @stColor, 00ffffffh
.elseif eax == BODY
.if bRanColor
invoke _NextInt, 255
mov ecx, eax
shl ecx, 8
invoke _NextInt, 255
or ecx, eax
shl ecx, 8
invoke _NextInt, 255
or ecx, eax
mov @stColor, ecx
.else
mov @stColor, 000000ffh
.endif
.else
mov @stColor, 0000ff00h
.endif
invoke CreateSolidBrush, @stColor
mov @hBrush, eax
invoke SelectObject, _hDC, @hBrush
mov @hOldBrush, eax
; 算出左右要画的地方
mov ecx, hNode
and ecx, 0ff000000h
shr ecx, 24
xor eax, eax
mov al, cl
mov bl, 20
mul bl
sub eax, 4
mov @stRect.left, eax
add eax, 18
mov @stRect.right, eax
; 算出上下要画的地方
mov ecx, hNode
and ecx, 00ff0000h
shr ecx, 16
xor eax, eax
mov al, cl
mov bl, 20
mul bl
sub eax, 4
mov @stRect.top, eax
add eax, 18
mov @stRect.bottom, eax
invoke FillRect, _hDC, addr @stRect, NULL
invoke SelectObject, _hDC, @hOldBrush
; 狂他妈漏啊……
invoke DeleteObject, @hBrush

@@:
pop ebx
pop ecx
ret
_DrawNode endp
...全文
5665 177 打赏 收藏 转发到动态 举报
写回复
用AI写文章
177 条回复
切换为时间正序
请发表友善的回复…
发表回复
labadavid 2013-12-25
  • 打赏
  • 举报
回复
学习了!感谢分享!
糅合 2013-08-13
  • 打赏
  • 举报
回复
新手学习中~~~
c789kai 2012-11-11
  • 打赏
  • 举报
回复
牛人啊,感觉汇编和C编程的思维上不太一样,学过C后,学汇编,有时脑子转不过来了
高屾蓅渁 2012-10-16
  • 打赏
  • 举报
回复
厉害,顶顶顶。
  • 打赏
  • 举报
回复
顶一下,学习学习!!
键盘上的疯兔 2011-12-03
  • 打赏
  • 举报
回复
呵呵 你这个也不错呀
艾迪mirror 2011-12-03
  • 打赏
  • 举报
回复
却是强大
fanrsl 2011-08-15
  • 打赏
  • 举报
回复
牛人啊 顶
zhisou2006 2011-07-31
  • 打赏
  • 举报
回复
老大 犀利啊
q821391987 2011-07-27
  • 打赏
  • 举报
回复
学习汇编中!
medky 2011-06-02
  • 打赏
  • 举报
回复
楼主写的不错,
不过我们真的有必要用汇编来写吗?
用C写出来,转换成ASM文件,稍加修改就能达到这种效果,但是时间能省很多。
汇编拿来开发游戏真的是大材小用了,我觉的。
Avending 2011-06-02
  • 打赏
  • 举报
回复
不错,牛人
zhlwm 2011-06-01
  • 打赏
  • 举报
回复
学习了
huanglijin123456 2011-06-01
  • 打赏
  • 举报
回复
学了好久的汇编,水平还没你一个手指头,悲剧ing
alanta0506 2011-06-01
  • 打赏
  • 举报
回复
牛,楼住强悍啊。。。。
xinxuyan 2011-06-01
  • 打赏
  • 举报
回复
牛人啊,专业
qwert_666 2011-06-01
  • 打赏
  • 举报
回复
太有才了,谢谢
zzyoucancan 2011-06-01
  • 打赏
  • 举报
回复
反正我是看不懂,不知你怎么样 不解释.....
zihan_free 2011-06-01
  • 打赏
  • 举报
回复
太牛啦!
jakey0108 2011-06-01
  • 打赏
  • 举报
回复
貌似汇编不好学 呵呵 真是牛人 学习了
加载更多回复(157)

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧