⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 block.asm

📁 俄罗斯方块
💻 ASM
📖 第 1 页 / 共 2 页
字号:
	push cx
	push dx
	push di
	;取最左上的地址,放入bx
	mov ah,i
	dec ah
	mov al,12
	mul ah
    mov bx,ax
	mov ah,0
	mov al,j
	dec al
	add bx,ax
    ;取下面的地址放入di
	mov di,bx
	add di,55
    cmp di,299
	jc s35
	mov di,299
s35:
    cmp matrix[bx],byte ptr -1
    jnz s36
	mov matrix[bx],0
s36:
    inc bx
	cmp bx,di
	jnz s35
	pop di
    pop dx
	pop cx
	pop bx
	pop ax
    ret
i_j_clear endp

i_j_paste proc near
;将临时矩阵中的内容粘贴到(i,j)上面去
    push ax
	push bx
	push cx
	push dx
	push si
	push di
	;取最左上的地址,放入bx
	;bx用做矩阵寻址
	mov ah,i
	dec ah
	mov al,12
	mul ah
    mov bx,ax
	mov ah,0
	mov al,j
	dec al
	add bx,ax

    ;di用作temp4x4临时矩阵的寻址
	mov di,0

	;用ah,al,ch,cl来控制双重循环
	;使用直到型循环
	mov ah,i
	mov al,j

	mov ch,ah
	mov cl,al
	add ch,4
	add cl,4

    cmp ch,26
	jc s37
	mov ch,26
s37:
    cmp cl,12
	jc s38
	mov cl,12
s38:
    mov al,j
	mov dx,0
s39:
;*******************
    cmp matrix[bx],byte ptr -1
	jnz s40
	mov matrix[bx],0
s40:
    cmp temp4x4[di],byte ptr 9
	jnz s41
	mov matrix[bx],-1
s41:
;*******************
    inc dx
    inc bx
	inc di
    inc al
	cmp al,cl
	jnz s39
	add bx,12
	sub bx,dx
	add di,4;修补di可能在右边界出现的bug
	sub di,dx
	inc ah
	cmp ah,ch
	jnz s38

	pop di
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
    ret
i_j_paste endp

getmode proc near
;将模型内的图形取到临时矩阵里面去
;要取的模型编号为pasteid
;pasteid的编号为:0,1,2,3...
    push ax
	push bx
	push cx
	push dx
	push si
	push di
    ;取模型号码
    mov cl,pasteid
    ;计算模型第一个元素的偏移地址,用bx保存
	mov al,16
	mul cl
    mov bx,ax
	;用di在temp4x4中寻地址
    mov di,0
    ;开始复制
	mov cx,16
s42:
    mov ah,mode[bx]
    mov temp4x4[di],ah
	inc bx
    inc di
	loop s42

	pop di
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
    ret
getmode endp


i_jchkclash proc near
;将临时矩阵temp4x4与matrix i,j位置比较
;1为有冲突,0为没有冲突
;将比较结果写入变量chkclash
;s43-s48
;我操,被这个函数整死了
    push ax
	push bx
	push cx
	push dx
	push si
	push di

	;先设置为不冲突
    mov chkclash,0

	;寻找matrix第一格元素的偏移地址, 放入bx
	mov ah,i
	dec ah
	mov al,12
	mul ah
	mov bx,ax
	mov al,j
	dec al
    mov ah,0
	add bx,ax
	;寻找辅助矩阵的第一格元素的偏移地址,放入si
	mov si,0

	;开始循环
    mov ch,4
s44:mov cl,4
s43:
    ;*******
	cmp temp4x4[si], byte ptr 9
	jnz s46
    cmp bx,311
	jnc s45
	cmp matrix[bx],byte ptr 1
	jz s45
	cmp matrix[bx],byte ptr 2
	jz s45

	jmp s46
s45:
    ;冲突
    mov chkclash,1
	jmp s47
s46:
	;*******
	inc si
	inc bx
    dec cl
	jnz s43

	add bx,8
	dec ch
	jnz s44
s47:
    ;结束
    pop di
	pop si
	pop dx
	pop cx
	pop bx
	pop ax
	ret
i_jchkclash endp

i_j_change proc near
;让正在下落的模型变形
    push ax
	push bx
	push cx
	push dx
	;取得当前模型号码
	mov al,mdnow
	;取变形目标的模型号码
    mov ah,0
	mov bx,ax
	mov al,mdchange[bx]

	;取模型数据
	mov pasteid,al
	call getmode
	;判断冲突
	call i_jchkclash
    ;如果不冲突,[清掉当前的-1??],将新模型写入,重新设置now的编号
	cmp chkclash,byte ptr 1
	jz s49
	call i_j_paste
    mov mdnow,al
s49:
    pop dx
    pop cx
	pop bx
	pop ax
    ret
i_j_change endp

new_block proc near
;产生新模型并且判断游戏是否结束
    push ax
	push bx
	push cx
	push dx
	;取得生成位置
	mov ch,borni
	mov cl,bornj
    mov i,ch
	mov j,cl

	;取得模型号码
	mov al,mdnow

	;取模型数据
	mov pasteid,al
	call getmode

	;判断是否冲突
	call i_jchkclash
	cmp chkclash,byte ptr 1
	jnz s50
	;冲突设置游戏结束标记
	mov gameover,1
s50:
	call i_j_paste
    pop dx
    pop cx
	pop bx
	pop ax
    ret
new_block endp

clear_floor proc near
;这个函数实现得太垃圾了
;显示区域[72, 299]
;处理一轮下落之后可能的消层zhi
    push ax
	push bx
	push cx
	push dx
	push si
	push di
;第一轮扫描,做标记,做统计
;用2标记
;用dl统计
	mov dl, 0;统计待clear的层数

    mov si, 299
	mov bx, 299
s61:
    ;统计一行
	mov dh,0;
	mov cx,12
	mov di,si
s62:
    add dh,matrix[si]
	dec si
	loop s62
    cmp dh,4
	jz s64break
	cmp dh,14
	jnz s63
    ;********************
	;累计消层数量
	;在待消层做标记
	inc dl
	dec di
    mov matrix[di],2
    ;********************
s63:
	cmp si,71
	jnz s61
s64break:

    cmp dl,0
	jz s72exit

    ;***********************************
	;消层数量统计在dl里面
	;如果想累计得分功能,可以在附近此添加
    ;***********************************

;第2轮扫描,处理消层
;用si寻找
;用bx更新
    mov si,299
	mov bx,299
s65:
    ;*********一行一行的扫描
	;空行则跳过
    cmp matrix[si-1], byte ptr 2
	jnz s66
    sub si,12
	jmp s68
s66:
    ;非空行
	;这里效率很差,改过让跳转,不过有错,算了不改了
	;之前有比较si和bx,若相等跳到s68,不过会死循环,不知道原因
	mov cx,12
s67:
    mov dh,matrix[si]
	mov matrix[bx],dh
	dec si
	dec bx
    loop s67
s68:
	;***********************
s69:
	cmp si,71
	jnz s65 
    
;将BX扫描到底
s70:
    cmp matrix[bx],2
	jz s71
	mov matrix[bx],0

s71:
    dec bx
    cmp bx,71
	jnz s70
s72exit:
    pop di
    pop si
    pop dx
    pop cx
	pop bx
	pop ax
    ret
clear_floor endp

set_next proc near
;该函数的功能,用mdnext替换mdnow,并且根据
;之前配置的概率信息得到一个新的mdnext
;采用线性同余法生成伪随机数
;线性同余,return :(101 * x + 37) mode 149,这几个参数已经经过了测试
;概率算法,见设计文档
    push ax
	push bx
	push cx
	push dx
	push si
	push di

	;设置当前
    mov ah,mdnext
	mov mdnow,ah
    ;然后准备去产生下一个

	;读取权值和,放到mdnext里面
    mov si,0
	mov bh,0
	mov cx,0
	mov cl,mdcount
s73:
    add bh,mdchance[si]
	inc si
	loop s73
	mov mdnext,bh

	;初始化随机数据种子,dl做种子
    MOV AH,2CH
    INT 21H

    ;计算随机数字,线性同余
	mov al,101
	mul dl
	add ax,37
	mov dl,149
	div dl
	mov al,ah
	mov ah,0
    div mdnext
    mov al,ah
	mov ah,0
	;al为0~权值和减1之间的随机数
	;下面来根据随机al和权值情况选节点
	;算法见设计文档
	;使用ah来累计权值
	mov ah,0
	mov bx,-1

s74:
    inc bx
	add ah,mdchance[bx]
	cmp mdchance[bx],0
	jz s74
	cmp al,ah
	jc s75
	jmp s74
s75:
    ;得到模型,写入mdnext
    mov mdnext,bl

	;然后将该模型贴入右上角区域
    mov pasteid,bl
	mov ch,i
	mov cl,j
	mov i,2
	mov j,8
	call getmode
	call i_j_paste

    pop di
    pop si
    pop dx
    pop cx
	pop bx
	pop ax
    ret
set_next endp

judgedn proc near
;下落触发器
    push ax
	push bx
	push cx
	push dx
    ;取间隔放入bx里面    
	mov al,mulnum
    mul basicwait
	mov bx,ax

	;读取现在的秒和百分秒
    MOV AH,2CH
    INT 21H

	;秒的差距放
	sub dh,sec
	jns s77
	add dh,60
s77:
    mov al,100
	mul dh

	mov dh,0
	add ax,dx

	mov dl,persec
	mov dh,0
	sub ax,dx
     
	;比较百分秒差距和间隔
	cmp ax,bx
	jc s78else
	;触发下落的情况
	mov trigger,1
    MOV AH,2CH
    INT 21H
	mov sec,dh
	mov persec,dl
	jmp s79exit
s78else:
    ;非触发下落的情况
    mov trigger,0
s79exit:
    pop dx
	pop cx
	pop bx
	pop ax
    ret
judgedn endp

mainloop proc near
;主游戏循环
;由于跳转的长度有限制
;没办法把结束的代码放到前面来
;以后再改
    push ax
	push bx
	push cx
	push dx

s91:
    call set_next
    call new_block
	mov turnover,0
	call scan_board
	cmp gameover, byte ptr 1
    jnz s92
	pop dx
	pop cx
	pop bx
	pop ax
    ret
s92:
    ;如果有合法按键,处理变形或移动
    mov ah,1
	int 16h
	jz s93

    mov ah,0
    int 16h
    mov ah,al

	cmp al,dnkey
	jnz s92_1
	mov ah,'d'
    mov movsign,ah
	call block_move
	call scan_board
	jmp s93
s92_1:
    cmp al,rtkey
	jnz s92_2
	mov ah,'r'
    mov movsign,ah
	call block_move
	call scan_board
	jmp s93
s92_2:
    cmp al,ltkey
	jnz s92_3
	mov ah,'l'
    mov movsign,ah
	call block_move
	call scan_board
	jmp s93
s92_3:
    cmp al,cgkey
	jnz s92_4
    call i_j_change
	call scan_board
	jmp s93
s92_4:

s93:
    cmp turnover,1
	jz s94
    ;添加处理触发下落的模块,添到什么地方呢
    call judgedn
	cmp trigger,1
	jnz s94
	;触发下落
	mov ah,'d'
    mov movsign,ah
	call block_move
	call scan_board
s94:
	cmp turnover,1
	jnz s92
    call clear_floor
    jmp s91
mainloop endp
code ends
    end start

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -