📄 block.asm
字号:
;*******************************************************************
; author:qinjie date:2008-04-03
;
; descript :
; :全部使用80x86的简单汇编指令
;
; :本程序很多东西都可以在数据段配置
; ;可配置方块大小,颜色,界面位置,使用的按键,每个方块模型形状
; ;可配置每个方块模型变化后的形状,每个方块模型出现的概率
; ;可配置自动下落的触发间隔,都是在数据段里面配出来的.
;
;*******************************************************************
;*******************************************************************
; finish:
; 下次应该考虑将墙设置为空心
; 应该考虑将移动和变形用统一的方法
; 应该考虑配置概率的限制,该版本有限制概率和不能超过db的长度
; 下次应该考虑将墙的厚度增加,免得配置新模型的时候出来bug
; 下次应该考虑如何将分数在屏幕上面更新
; 下次应该友好的用户交互,不能游戏结束就弹出去
; 下次应该考虑随着得分增加然后速度自动增加
; 不足之处不再做修改
; qinjie 08-04-05
;*******************************************************************
data segment
;配置游戏框架左上角的象素坐标,以及每个方块的边长象素长
leftpx dw 124
toppx dw 22
l db 5
;初试话显示器模式INT10H的参数:模式,调色盘前景色,调色盘背景色
ctrmod db 5
bgcolor db 15
frontcolor db 10
;俄罗思方块的颜色,以及背景色int 10h的0ch功能,的al参数
blockcolor db 5
blockbgcolor db 12
framecolor db 7
currnetcolor db ?
; 2 为墙
; 1 为下落好的
;-1 为正在下落的
; 0 为空着没有东西的
;定义数组矩阵
i db 8
j db 3
matrix db 2,2,2,2,2,2,2,2,2,2,2,2
db 2,0,0,0,0,0,2,0,0,0,0,2
db 2,0,0,0,0,0,2,0,0,0,0,2
db 2,0,0,0,0,0,2,0,0,0,0,2
db 2,0,0,0,0,0,2,0,0,0,0,2
db 2,2,2,2,2,2,2,2,2,2,2,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,0,0,0,0,0,0,0,0,0,0,2
db 2,2,2,2,2,2,2,2,2,2,2,2
oldmatrix db 312 dup(0);辅助矩阵,为打印屏幕次数更少设置
borni db 7 ;新模型生成位置,x方向第7格
bornj db 5 ;新模型生成位置,y方向第5格
gameover db 0 ; 1为游戏结束
turnover db 0 ; 1为一轮下落结束
movsign db 'd'; 程序只认:'r'向右 | 'l'向左 |'d'向下|其他不移动
;temp四乘四矩阵,粘贴到matrix(i,j)的模型id
temp4x4 db 16 dup(0)
pasteid db ?
;用于保存检测冲突的结果,1为冲突,0为不冲突
;在变形和生成新模型中需要用这个结果
chkclash db 0
;几个变形的按键,配置在这里,方便改变
rtkey db 'd' ;右
ltkey db 'a' ;左
dnkey db 's' ;下
cgkey db 'w' ;变形
;当前模型编号,当前后继模型编号
mdnow db 100
mdnext db 100
;配置模型变化编号
;配置模型出现概率
;配置模型的样子(数组)
; 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14
mdchange db 1, 0, 2, 4, 5, 6, 3, 8, 9,10, 7,12,13,14,11;变化指针
mdchance db 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1;出现机会的权值,注权值总和不要超过127
mdcount db 15 ;模型总数
;0号模型
mode db 0,9,0,0
db 0,9,0,0
db 0,9,0,0
db 0,9,0,0
;1号模型
db 0,0,0,0
db 9,9,9,9
db 0,0,0,0
db 0,0,0,0
;2号模型
db 0,0,0,0
db 0,9,9,0
db 0,9,9,0
db 0,0,0,0
;3号模型
db 0,9,0,0
db 9,9,9,0
db 0,0,0,0
db 0,0,0,0
;4号模型
db 0,9,0,0
db 0,9,9,0
db 0,9,0,0
db 0,0,0,0
;5号模型
db 0,0,0,0
db 9,9,9,0
db 0,9,0,0
db 0,0,0,0
;6号模型
db 0,9,0,0
db 9,9,0,0
db 0,9,0,0
db 0,0,0,0
;7号模型
db 0,9,0,0
db 0,9,0,0
db 0,9,9,0
db 0,0,0,0
;8号模型
db 0,0,0,0
db 9,9,9,0
db 9,0,0,0
db 0,0,0,0
;9号模型
db 9,9,0,0
db 0,9,0,0
db 0,9,0,0
db 0,0,0,0
;10号模型
db 0,0,9,0
db 9,9,9,0
db 0,0,0,0
db 0,0,0,0
;11号模型
db 0,0,9,0
db 0,0,9,0
db 0,9,9,0
db 0,0,0,0
;12号模型
db 0,9,0,0
db 0,9,9,9
db 0,0,0,0
db 0,0,0,0
;13号模型
db 0,9,9,0
db 0,9,0,0
db 0,9,0,0
db 0,0,0,0
;14号模型
db 0,0,0,0
db 0,9,9,9
db 0,0,0,9
db 0,0,0,0
;触发下落的模块的参数
;触发等待时间为 basicwait * mulnum
sec db ? ; 下落秒的历史纪录
persec db ? ; 下落百分之一秒的历史纪录
basicwait db 22 ; 基本间隔,单位为百分之一秒,最好大点,30以上
mulnum db 2 ; 延迟触发基本间隔的倍数
trigger db 0 ; 1触发/0不触发
data ends
code segment
assume ds:data,cs:code
start:
mov ax,data
mov ds,ax
;&&&&&&&&&&&&&&&&&
;设置显示器模式
mov ah,00h
mov al,ctrmod
int 10h
mov ah,0bh
mov bh,0
mov bl,bgcolor
int 10h
mov bh,1
mov bl, frontcolor
int 10h
;&&&&&&&&&&&&&&&&&
call set_next;设置next
call set_next;设置now
call mainloop;主循环
;停一下
mov ah,8
int 21h
;&&&&&&&&&&&&&&&&
;设置字符显示模式
mov ah,00h
mov al,3
int 10h
;&&&&&&&&&&&&&&&&&
;退出
mov ah,4ch
int 21h
draw_a_block proc near
;函数功能,打印一个方块
push ax
push bx
push cx
push dx
push di
;寻找dx的初值,y坐标
mov al,i
dec al
mov ah,l
mul ah
add ax,toppx
mov dx,ax
;用di保存cx的初值,x坐标
mov al,j
dec al
mov ah,l
mul ah
add ax,leftpx
mov di,ax
;fix**************为格子之间有空格打补丁**
cmp l,byte ptr 3
jc s2_1
inc dx
inc ax
dec l
s2_1:
;fix**************************************
;开始打印(i,j)方块
mov ah,0ch
mov al,currnetcolor
mov bh,l
s2: mov bl,l
mov cx,di
s1: int 10h
inc cx
dec bl
jnz s1
inc dx
dec bh
jnz s2
;fix**************为格子之间有空格打补丁
cmp l,byte ptr 3
jc s2_2
inc l
s2_2:
;fix************************************
pop di
pop dx
pop cx
pop bx
pop ax
ret
draw_a_block endp
scan_board proc near
;函数功能,打印全屏幕
push ax
push bx
push cx
push dx
mov ch,i
mov cl,j
mov bx,311;12 X 26
mov i,26
s4: mov j,12
s3:
;**********************************************
;循环体,扫描每个数组
;打印全屏幕
;判断是否需要打印,如果需要打印则走case分支
mov al,matrix[bx]
cmp al,oldmatrix[bx]
jz s8
mov oldmatrix[bx],al
;CASE1: 数组元素为2,是边界
cmp matrix[bx],byte ptr 2
jnz s5
mov al,framecolor
mov currnetcolor,al
call draw_a_block
s5:
;Case2: 数组元素为-1,是正在下落的方块
cmp matrix[bx],byte ptr -1
jnz s6
mov al,blockcolor
mov currnetcolor,al
call draw_a_block
s6:
;Case3:数组元素为1,是下落完毕的方块
cmp matrix[bx],byte ptr 1
jnz s7
mov al,blockcolor
mov currnetcolor,al
call draw_a_block
s7:
;Case4:数组元素为0,没有东西,用背景色填充
cmp matrix[bx],byte ptr 0
jnz s8
mov al,blockbgcolor
mov currnetcolor,al
call draw_a_block
s8:
;**********************************************
dec bx
dec j
jnz s3
dec i
jnz s4
mov i,ch
mov j,cl
pop dx
pop cx
pop bx
pop ax
ret
scan_board endp
i_j_move proc near
;函数功能,该函数没有判断是否能移动
;只负责移动
;所以不能直接调用,需要先判断
push ax
push bx
push cx
push dx
push di
mov ah,i
mov al,j
push ax
;上面的那个地址di
mov ah,0
dec al
mov di,ax
mov ah,i
dec ah
mov al,12
mul ah
add di,ax
;下面的那个地址bx
mov bx,di
add bx,52;48+4
;根据移动方向选择
;替换-1的相对地址si
;和循环中的稍描方向cx
mov al,movsign
cmp al,byte ptr 'r'
jnz s9
mov si,1
mov cx,-1
jmp s12
s9:
cmp al,byte ptr 'l'
jnz s10
mov si,-1
mov cx,1
jmp s12
s10:
cmp al ,byte ptr 'd'
jnz s18exit
mov si,12
mov cx,-1
jmp s12
s12:
;让两个地址不越界
cmp bx,298;最右下角的空白格为298
jc s13
mov bx,298
s13:
cmp dx,72;最左上角的空白格子为72
jnc s14
mov dx,72
s14:
;到这里
;si为于等待修改的元素的地址偏移量
;di为稍描上面界限的那个地址
;bx为稍描上面界限的那个地址
;如果si等于-1(左移动)就从上往下扫描,否则从下往上扫描
cmp si, -1
jnz s15
mov ax,bx
mov bx,di
mov di,ax
s15:
;until循环,di移动到结束的下一个位置,当哨兵
add di,cx
;循环,如果是-1则进行移动
s16:
cmp matrix[bx],byte ptr -1
jnz s17
mov matrix[bx],0
mov matrix[bx+si],-1
s17:
add bx,cx
cmp bx,di
jnz s16
s18exit:
pop ax
mov j,al
mov i,ah
pop di
pop dx
pop cx
pop bx
pop ax
ret
i_j_move endp
block_move proc near
push ax
push bx
push cx
push dx
push si
push di
;dh用做标记,1为block_move 成功,0为block_move失败
mov dh,0
;先判断(i,j)位置的正在下落的方块是否能移动
mov ch,i
mov cl,j
;bx中放数组上部那个界限
mov ah,ch
dec ah
mov al,12
mul ah
mov bx,ax
mov ah,0
mov al,cl
dec ax
add bx,ax
;di放数组下部分那个界限
mov di,bx
add di,52;48+4
;让两个界限不越界[72, 298]
cmp bx,72
jnc s19
mov bx,72
s19:
cmp di,298
jc s20
mov di,298
s20:
;di当哨兵,until型循环
inc di
;先取相对偏移量si,等一下从bx稍描到di
mov al,movsign
cmp al,byte ptr 'd'
jnz s21
mov si,12
jmp s23judge
s21:cmp al,byte ptr 'l'
jnz s22
mov si,-1
jmp s23judge
s22:cmp al,byte ptr 'r'
jnz s31exit
mov si,1
jmp s23judge
s23judge:
;如果执行到这里,表示movsign里面是有数据的
;开始判断
cmp matrix[bx],byte ptr -1
jnz s24
cmp matrix[bx+si],byte ptr 1
jz s31exit
cmp matrix[bx+si],byte ptr 2
jz s31exit
s24:
inc bx
cmp bx,di
jnz s23judge
;如果执行到这里,表示可以移动,马上处理移动,然后设置标记
call i_j_move
mov dh,1
;移动完毕,改变i和j的值,然后结束
mov al,movsign
mov ch,i
mov cl,j
cmp al,byte ptr 'd'
jnz s25
inc ch
jmp s27
s25:
cmp al,byte ptr 'l'
jnz s26
dec cl
jmp s27
s26:
inc cl
s27:
mov i,ch
mov j,cl
s31exit:
;如果下落失败,则设置turnover标记1
mov al,movsign
cmp al,'d'
jnz s34
cmp dh,0
jnz s34
mov turnover,1
;将(i,j)附近-1的元素全部变成1的元素
mov bx,di
sub bx,53;48+4
s32:
cmp matrix[bx],byte ptr -1
jnz s33
mov matrix[bx],1
s33:
inc bx
cmp bx,di
jnz s32
s34:
;清除下落标记
mov movsign,0
pop di
pop si
pop dx
pop cx
pop bx
pop ax
ret
block_move endp
i_j_clear proc near
push ax
push bx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -