搜档网
当前位置:搜档网 › Verilog-HDL高级数字设计实验报告--_俄罗斯方块_FPGA实现

Verilog-HDL高级数字设计实验报告--_俄罗斯方块_FPGA实现

Verilog-HDL高级数字设计实验报告--_俄罗斯方块_FPGA实现
Verilog-HDL高级数字设计实验报告--_俄罗斯方块_FPGA实现

Verilog HDL高级数字设计

实验报告

题目:“俄罗斯方块”FPGA实现

实验目的

通过此次项目,完成以下目的:

1)熟悉Xilinx FPGA的架构及开发流程

2)设计一个功能完整的系统,掌握FSM + Datapath的设计方法。

实验内容

1.项目介绍

本项目主要在FPGA上实现了一个经典小游戏“俄罗斯方块”。本项目基本解决方案是,使用Xilinx Zynq系列开发板ZedBoard作为平台,实现主控模块,通过VGA接口来控制屏幕进行显示。

2.系统框架

整个系统由四部分组成,按键输入处理模块、控制模块、数据路径模块以及VGA显示接口模块。整个系统的结构如下图所示:

图1:系统框图

下面分别对四个模块进行介绍:

1)按键输入处理模块

按键处理模块的主要功能是对输入系统的up,down,left,right四个控制信号进行消抖处理,并对其进行上升沿检测。

消抖模块采用上课所提出的结构,采用了一个4位的移位寄存器,先将输入信号延迟4个时钟周期,再对其以一个较低的时钟频率进行采用。消抖模块的结构如下图所示:

图2:消抖模块结构示意图

为了简化控制系统,在本系统的设计过程中,不考虑长时间按键产生连按效果。因而,需要对按键进行上升沿检测。上升沿检测的基本实现方案是加入一组寄存器,对前一个的按键信号进行暂存,将暂存的值与当前值进行比较,当上一个值为0而当前值为1时,即认为其检测到了一个上升沿。

2)控制模块

控制模块采用FSM的方式进行控制。在控制模块中,定义了10个状态:

S_idle:上电复位后进入的空状态,当start信号为1时进入S_new状态

S_new:用于产生新的俄罗斯方块。

S_hold:保持状态。在这个状态中进行计时,当时间到达一定间隔时,转到S_down 状态;或者等待输入信号(up,down,left,right)时,转到S_down(按键为down)或者S_move(up,left,right)状态。

S_down:判断当前俄罗斯块能否下移一格。如果可以,则转到S_remove_1状态,如果不行,则转到S_shift状态。

S_move:判断当前俄罗斯块能够按照按键信号指定的指令进行移动,如果可以,则转到S_shift状态,如果不可以,则转到S_remove_1状态。

S_shift:更新俄罗斯方块的坐标信息。返回S_hold。

S_remove_1:更新整个屏幕的矩阵信息。转移到S_remove_2状态。

S_remove_2:判断是否可以消除,将可以消除的行消除,并将上面的行下移一行。

重复此过程,直到没有可消除的行为止。跳转到S_isdie状态

S_isdie:判断是否游戏结束。如果结束,则跳转到S_stop状态。如果没有,则跳转到S_new状态,生成新的俄罗斯方块。

S_stop:清楚整个屏幕,并跳转到S_idle状态。

整个控制过程的ASMD图如下图所示:

图3:控制模块ASMD图

3)数据路径

数据路径模块主要功能是,根据控制模块给出的信号,对俄罗斯方块当前的逻辑状态进行判断,更新背景矩阵。具体如下:

方块:

方块分为非活动方块与活动方块。非活动方块为:(1)之前下落的方块;(2)下落后方块消除之后的结果。由背景矩阵表示。活动方块为当前下落中的方块,由活动方块坐标与方块类型表示(后简称方块)。

背景矩阵:

reg [9:0] R [23:0];

背景矩阵R是24行10列的寄存器组,负责保存非活动方块坐标,即R中任一位置,如方块存在,则该位置1,否则为0。

活动方块坐标:

output reg [4:0] n,

output reg [3:0] m,

n, m分别为当前活动方块的行、列指针,指向方块固定点位置。方块固定点为方块旋转时不变的格点,依据方块种类决定,下文方块模型中详述。

方块类型:

output reg [6:0] BLOCK,

BLOCK代表方块类型,由7位编码构成。

数据交换:

Datapath与其余模块的数据交换分为两部分:(1)与control_unit间的状态指令交互;(2)控制merge,间接实现对VGA的控制。

方块模型:

俄罗斯方块共有7中形状的方块(O,L,J,I,T,Z,S),每种方块有1-4种不同的旋转变形方式。为方便起见,将方块定位A-G,旋转编号为1-4,将方块编码成A_1-G_2的19种,如下图:

图中,深色方块是该种方块的固定点。

图4:方块模型示意图

方块运动:

产生:

方块产生由一个简单的伪随机过程决定。系统采用一个3位的计数器产生随机数,进入S_new,BLOCK的值被NEW_BLOCK覆盖,方块坐标n<=1;m<=5;同时,根据计数器,NEW_BLOCK的值刷新为A_1,B_1,…,G_1中的一种,作为下一次方块。

移动:

方块移动分为四种:旋转,下落,向左,向右,由键盘KEYBOARD=[UP, DOWN, LEFT, RIGHT]控制。移动分两步进行:(1)判断;(2)转换。

判断过程包含S_down,S_move。判断分两步:首先,判断变换后方块坐标是否合法,即变换后是否会造成方块越界。然后,判断变换后方块可能占据的新位置是否有背景矩阵方块存在。两步判断通过后返回成功信号,否则失败。因判断代码量较多,仅举一例说明:

判断D_1向右运动(MOVE_ABLE初值为0):

if (m<=8)

if (!((R[n-1][m+1])|(R[n][m+1])|(R[n+1][m+1])|(R[n+2][m+1])))

MOVE_ABLE=1;

else MOVE_ABLE=0;

转换过程(S_shift)进行方块的移动或变形。根据KEYBOARD,移动时,改变方块坐标;变形时,方块按类别变换,如:A_1→A_1;B_1→B_2; B_2→B_3; B_4→B_1;

停止与消除:

方块停止与消除由两个状态完成:S_remove1,S_remove2。

前一状态中,根据BLOCK, n, m,将活动方块位置覆盖至R,变为非活动方块。

后一状态中,根据行满状态,进行行的消除与平移,具体如下:

显然,俄罗斯方块能影响的最大行数为4,因此,在REMOVE_2中,仅对

R[n-1],R[n],R[n+1],R[n+2]四行依次进行处理。处理过程为:如果该行(k)满,则由k行开始,至1行结束,逐行向下平移,当前平移位置由计数器REMOVE_2_C控制,当前行消除截止由标志位SIG确认。

每行处理完后,将REMOVE_FINISH[3:0]中相应位置1,REMOVE_FINISH全1时,REMOVE_2完成。

死亡判定:

R中的0-3行位于屏幕上方,不进行显示,仅有新生成的方块坐标会进入这一区域。因而,当消除完成后,如R[3]不为空,游戏结束。

4)显示部分

输出结果通过VGA接口接入显示屏显示。VGA(Video Graphics Array)视频图形阵列是IBM于1987年提出的一个使用模拟信号的电脑显示标准。VGA接口即电脑采用VGA标准输出数据的专用接口。VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。

使用Verilog HDL语言对VGA进行控制一般只需控制行扫描信号、列扫描信号和红绿蓝三色信号输出即可。

VGA输出可分为四个模块:时钟分频模块、数据组织模块、接口控制模块和顶层模块。以下进行分块描述。

时钟模块分频模块对FPGA系统时钟进行分频。由于使用的显示屏参数为640*480*60Hz,其真实屏幕大小为800*525,因此所需时钟频率为800*525*60Hz=25.175MHz,可近似处理为25MHz。FPGA系统时钟为100M,因此将其四分频即可基本满足显示要求。

数据组织模块是将预备输出的数据组织为可以通过VGA接口控制的数据形式,本次设计中因接口已经协调,数据可不经过此模块进行组织,故可忽略该模块。

接口控制模块通过VGA接口对显示屏进行控制。VGA的扫描顺序是从左到右,从上到下。例如在640X480的显示模式下,从显示器的左上角开始往右扫描,直到640个像素扫完,再回到最左边,开始第二行的扫描,如此往复,到第480行扫完时即完成一帧图像的显示。这时又回到左上角,开始下一帧图像的扫描。如果每秒能完成60帧,则称屏幕刷新频率为60Hz。宏观上,一帧屏幕由480个行和640个列填充而成,而实际上,一帧屏幕除了显示区,还包含其他未显示部分,作为边框或者用来同步。具体而言,一个完整的行同步信号包含了左边框、显示区、右边框还有返回区四个部分,总共800个像素,其分配如下:

图5:VGA行扫描时序

同样的,一个完整的垂直同步信号也分为四个区域,总共525个像素,分配如下:

图6:VGA场扫描时序

模块通过组织输出行扫描信号、列扫描信号和三原色信号对显示屏实现控制。

实验结果

实验结果图如下:

图7:实验结果图

实验总结

1)完成情况

本次项目我们完成了既定目标,即完成一个经典小游戏“俄罗斯方块”的核心功能。在本次实验过程中,我们通过采用分工合作的方式,通过对系统功能的分析,确定解决方案,完成了对一个系统自上而下的设计,并尝试采用控制单元+数据路径这样的方式来处理核心模块。

2)不足与改进之处

由于时间仓促,加之对俄罗斯方块逻辑复杂度估计不足,到最后展示之前我们才完成了对核心模块的调试。因此,在用户界面上没有做过多的调整。另外,由于在进行模块划分时,一些接口没有事先定义好,导致在最后系统整合时,不得不进行修改与调整,由此而造成了一部分时间的浪费。

总的来说,通过这个项目,小组成员对于硬件设计“并行”的特点有了比较直接的认识,同时也在调试的过程中掌握了一些硬件调试常用的方法,也认识到了仿真的重要意义所在。另外就是关于团队协作方面的一个教训,在系统划分时要注意把接口定义好,以免造成不必要的代价。

实验代码KeyBoard模块

`timescale1ns/1ps

module key(

input clk,

input rst_n,

input UP_KEY,

input LEFT_KEY,

input RIGHT_KEY,

input DOWN_KEY,

outputreg rotate,

outputreg left,

outputreg right,

outputreg down

);

reg[3:0] shift_up;

reg[3:0] shift_left;

reg[3:0] shift_right;

reg[3:0] shift_down;

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n)

shift_up <=0;

else

shift_up

<={shift_up[2:0], UP_KEY};

end

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n)

shift_right <=0;

else

shift_right

<={shift_right[2:0], RIGHT_KEY}; end always@(posedge clk ornegedge rst_n)

begin

if(!rst_n)

shift_left <=0;

else

shift_left

<={shift_left[2:0], LEFT_KEY}; end

always@(posedge clk ornegedge rst_n)

begin

if(!rst_n)

shift_down <=0;

else

shift_down

<={shift_down[2:0], DOWN_KEY}; end

reg clk_div;

reg[7:0] clk_cnt;

always@(posedge clk ornegedge rst_n)

begin

if(!rst_n)

begin

clk_cnt <=0;

clk_div <=0;

end

elseif(clk_cnt <=8'd49)

begin

clk_cnt <= clk_cnt +1; clk_div <= clk_div;

end

else

begin

clk_cnt <=0;

clk_div <=~clk_div;

end

end

always@(posedge clk_div ornegedge rst_n)

begin

if(!rst_n)

begin

rotate <=0;

left <=0;

right <=0;

down <=0;

end

else

begin

rotate <= shift_up[3];

left <= shift_left[3];

right <= shift_right[3];

down <= shift_down[3];

end

end

endmodule

控制模块程序

module game_control_unit (

input clk,

input rst_n,

input rotate,

input left,

input right,

input down,

input start,

outputreg[3:0] opcode,

outputreg gen_random,

outputreg hold,

outputreg shift,

outputreg move_down,

outputreg remove_1,

outputreg remove_2,

outputreg stop,

outputreg move,

outputreg isdie,outputreg auto_down,

input shift_finish,

input remove_2_finish,

input down_comp,

input move_comp,

input die

);

reg left_reg;

reg right_reg;

reg up_reg;

reg down_reg;

always@(posedge clk ornegedge rst_n)

begin

if(!rst_n)

begin

left_reg <=0;

right_reg <=0;

up_reg <=0;

down_reg <=0;

end

else

begin

left_reg <= left;

right_reg <= right; up_reg <= rotate;

down_reg <= down; end

end

reg auto_down_reg;

always@(posedge clk ornegedge rst_n)

begin

if(!rst_n)

auto_down_reg <=0; elseif(time_cnt == time_val) auto_down_reg <=1; else

auto_down_reg <=0; end

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n)

auto_down <=0;

else

auto_down <=

auto_down_reg;

end

parameter time_val =26'd2*******; reg[25:0] time_cnt;

localparam S_idle =4'd0,

S_new =4'd1,

S_hold =4'd2,

S_move =4'd3,

S_shift =4'd4,

S_down =4'd5,

S_remove_1 =4'd6, S_remove_2 =4'd7, S_isdie =4'd8,

S_stop =4'd9;

reg[3:0] state, next_state;

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n)

state <= S_idle;

else

state <= next_state; end

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n)

time_cnt <=0;

elseif(hold ==0&& time_cnt <

time_val) time_cnt <=time_cnt +1; elseif(move_down ==1)

time_cnt <=0;

elsebegin

time_cnt <= time_cnt; end

end

always@(posedge clk ornegedge

rst_n)

begin

if(!rst_n) opcode<=0;

else opcode<={right, left, down, rotate};

end

always@(*)

begin

next_state = S_idle;

hold =1;

gen_random =0;

//opcode = 4'b0000;

shift =0;

move_down =0;

remove_1 =0;

remove_2 =0;

stop =0;

move =0;

isdie =0;

case(state)

S_idle:

begin

if(start)

next_state = S_new; else

next_state =S_idle; end

S_new:

begin

gen_random =1;

next_state = S_hold; end

S_hold:

begin

hold =0;

if(time_cnt == time_val)

begin

next_state =S_down; end

elseif((down_reg ==0)&&(down

==1))

begin

next_state = S_down; end

elseif((left_reg ==0&& left

==1)||( right_reg ==0&& right

==1)||(up_reg ==0&& rotate ==1)) begin

next_state =S_move; end

else

next_state =S_hold; end

S_move:

begin

move =1;

if(move_comp)

next_state =

S_shift;

else

next_state =S_hold; end

S_shift:

begin

shift =1;

next_state = S_hold; end

S_down:

begin

move_down =1;

if(down_comp)

next_state =

S_shift;

else

next_state =

S_remove_1;

end

S_remove_1:begin

remove_1 =1;

next_state =

S_remove_2;

end

S_remove_2:

begin

remove_2 =1;

if(remove_2_finish)

next_state =

S_isdie;

else

next_state =

S_remove_2;

end

S_isdie:

begin

isdie =1;

if(die ==1)

next_state =S_stop; else

next_state = S_new; end

S_stop:

begin

stop =1;

next_state = S_idle; end

default next_state = S_idle; endcase

end

endmodule

数据路径

module Datapath_Unit #(

parameter A_1 =7'b0001000,

B_1 =7'b0011000,

B_2 =7'b0010100,

B_3 =7'b0010010,

B_4 =7'b0010001,

C_1 =7'b0101000,

C_2 =7'b0100100,

C_3 =7'b0100010,

C_4 =7'b0100001,

D_1 =7'b0111000,

D_2 =7'b0110100,

E_1 =7'b1001000,

E_2 =7'b1000100,

E_3 =7'b1000010,

E_4 =7'b1000001,

F_1 =7'b1011000,

F_2 =7'b1010100,

G_1 =7'b1101000,

G_2 =7'b1100100

)(

outputreg

MOVE_ABLE,SHIFT_FINISH,DOWN_ABLE ,DIE_TRUE,

output[239:0] M_OUT,

outputreg[4:0] n,

outputreg[3:0] m,

outputreg[6:0] BLOCK,

//output reg REMOVE_1_FINISH, outputreg REMOVE_2_FINISH,

//output reg NEW_BLOCK,

input

clk,rst_n,MOVE,DOWN,DIE,SHIFT,RE MOVE_1,REMOVE_2,NEW,STOP,AUTODOW N,

input[3:0] KEYBOARD

);

reg[2:0] RAN;

reg[9:0] R [23:0];

reg[6:0] NEW_BLOCK;

reg[6:0] BLOCK_P;

reg[4:0] remove_cnt;

reg[3:0] REMOVE_2_S;

reg[3:0] REMOVE_FINISH;

reg[4:0] REMOVE_2_C;

reg SIG;

always@(posedge clk ornegedge

rst_n)begin

if(!rst_n)

RAN<=0;

elseif(RAN==7) RAN<=1;

else RAN<=RAN+1;

end

// MOVE_ABLE signal

always@(*)

begin

MOVE_ABLE =0;

if(MOVE)

begin

if(KEYBOARD[0])//UP

begin

// MOVE_ABLE=1;

case(BLOCK)

A_1: MOVE_ABLE=0; B_1:if(m>=1)

beginif(!((R[n][m-1])|(R[n][m+1] )|(R[n-1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;end B_2:if(n<=22) beginif(!((R[n+1][m-1])|(R[n+1][ m])|(R[n-1][m])))

MOVE_ABLE=1;else MOVE_ABLE=0;end B_3:if(m<=8)

beginif(!(R[n][m-1]| R[n][m+1]| R[n+1][m-1])) MOVE_ABLE=1;else MOVE_ABLE=0;end

B_4:beginif(!((R[n-1][m])|(R[n+1 ][m])|(R[n+1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;end C_1:if(m<=8)

beginif(!((R[n][m-1])|(R[n][m+1] )|(R[n+1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;end

C_2:beginif(!((R[n-1][m])|(R[n-1 ][m+1])|(R[n-1][m])))

MOVE_ABLE=1;else MOVE_ABLE=0;end C_3:if(m>=1)

beginif(!((R[n-1][m-1])|(R[n][m-1])|(R[n][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;end C_4:if(n<=22) beginif(!((R[n-1][m])|(R[n+1][m-1])|(R[n+1][m])))

MOVE_ABLE=1;else MOVE_ABLE=0;end

D_1:if((m>=1)&(m<=7))

beginif(!((R[n][m-1])|(R[n][m+1] )|(R[n][m+2]))) MOVE_ABLE=1;else MOVE_ABLE=0;end

D_2:if(n<=21) beginif(!((R[n-1][m])|(R[n+1][m] )|(R[n+2][m]))) MOVE_ABLE=1;else MOVE_ABLE=0;end

E_1:if(n<=22) beginif(!(R[n+1][m]))

MOVE_ABLE=1;else MOVE_ABLE=0;end E_2:if(m<=8)

beginif(!(R[n][m+1]))

MOVE_ABLE=1;else MOVE_ABLE=0;end

E_3:beginif(!(R[n-1][m]))

MOVE_ABLE=1;else MOVE_ABLE=0;end E_4:if(m>=1)

beginif(!(R[n][m-1]))

MOVE_ABLE=1;else MOVE_ABLE=0;end F_1:if(m>=1)

beginif(!((R[n-1][m-1])|(R[n-1][ m]))) MOVE_ABLE=1;else

MOVE_ABLE=0;end

F_2:if(n<=22) beginif(!((R[n-1][m+1])|(R[n+1][ m]))) MOVE_ABLE=1;else

MOVE_ABLE=0;end

G_1:if(m>=1)

beginif(!((R[n-1][m+1])|(R[n][m-1]))) MOVE_ABLE=1;else

MOVE_ABLE=0;end

G_2:if(n<=22) beginif(!((R[n][m+1])|(R[n+1][m+ 1]))) MOVE_ABLE=1;else

MOVE_ABLE=0;end default MOVE_ABLE=0;

endcase

end

elseif(KEYBOARD[2])//LEFT

begin

// MOVE_ABLE<=0;

case(BLOCK)

A_1:if(m>=1)if(!((R[n+1][m-1])|( R[n][m-1]))) MOVE_ABLE=1;else MOVE_ABLE=0;

B_1:if(m>=1)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

B_2:if(m>=2)if(!((R[n][m-1])|(R[ n-1][m]))) MOVE_ABLE=1;else MOVE_ABLE=0;

B_3:if(m>=2)if(!((R[n-1][m-2])|( R[n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

B_4:if(m>=2)if(!((R[n][m-2])|(R[ n+1][m-2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

C_1:if(m>=2)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-2])))

MOVE_ABLE=1;else MOVE_ABLE=0;

C_2:if(m>=2)if(!((R[n][m-2])|(R[ n+1][m]))) MOVE_ABLE=1;else MOVE_ABLE=0;

C_3:if(m>=1)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

C_4:if(m>=2)if(!((R[n-1][m-2])|( R[n][m-2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

D_1:if(m>=1)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-1])|(R[n+2] [m-1]))) MOVE_ABLE=1;else

MOVE_ABLE=0;

D_2:if(m>=2)if(!(R[n][m-2])) MOVE_ABLE=1;else MOVE_ABLE=0;

E_1:if(m>=2)if(!((R[n-1][m-1])|( R[n][m-2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

E_2:if(m>=2)if(!((R[n-1][m-1])|( R[n][m-2])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

E_3:if(m>=2)if(!((R[n][m-2])|(R[ n+1][m-1]))) MOVE_ABLE=1;else MOVE_ABLE=0;

E_4:if(m>=1)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

F_1:if(m>=1)if(!((R[n-1][m])|(R[ n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

F_2:if(m>=2)if(!((R[n-1][m-2])|( R[n][m-1]))) MOVE_ABLE=1;else MOVE_ABLE=0;

G_1:if(m>=1)if(!((R[n-1][m-1])|( R[n][m-1])|(R[n+1][m-1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

G_2:if(m>=2)if(!((R[n-1][m-1])|( R[n][m-2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

default MOVE_ABLE=0;

endcase

end

elseif(KEYBOARD[3])//RIGHT begin

//MOVE_ABLE=1;

case(BLOCK)

A_1:if(m<=7)if(!((R[n+1][m+2])|( R[n][m+2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

B_1:if(m<=7)if(!((R[n+1][m+2])|( R[n][m+1])|(R[n-1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

B_2:if(m<=7)if(!((R[n][m+2])|(R[ n+1][m+2]))) MOVE_ABLE=1;else MOVE_ABLE<=0;

B_3:if(m<=8)if(!((R[n-1][m+1])|( R[n][m+1])|(R[n+1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

B_4:if(m<=7)if(!((R[n][m+2])|(R[ n+1][m]))) MOVE_ABLE=1;else MOVE_ABLE=0;

C_1:if(m<=8)if(!((R[n-1][m+1])|( R[n][m+1])|(R[n+1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

C_2:if(m<=7)if(!((R[n-1][m+2])|( R[n][m+2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

C_3:if(m<=7)if(!((R[n-1][m+2])|( R[n][m+1])|(R[n+1][m+1])))

MOVE_ABLE=1;else MOVE_ABLE=0;

C_4:if(m<=7)if(!((R[n-1][m])|(R[ n][m+2]))) MOVE_ABLE=1;else MOVE_ABLE=0;

D_1:if(m<=8)if(!((R[n-1][m+1])|( R[n][m+1])|(R[n+1][m+1])|(R[n+2] [m+1]))) MOVE_ABLE=1;else

MOVE_ABLE=0;

相关主题