初始的设计思路

我们把那个底盘称为Board,该Board类实一个容器,是一个6*6(n*n)的棋盘。对于该棋盘,我们抽象的看,那是不是一个表格呢?

所以我设想,这个Board类从我们的Table类继承,该Board类负责对底盘中的所有容器的控制。
Board类应该封装一个6*6(n*n)的棋盘的事实(细节),然后应该提供一个AddDevice(obj,x,y)的方法,x和y很显然,就是设备要放置的位置,这个obj就是允许放置的设备。
我们所需要的设备有
光线源头(line_head)
水晶(crystal)
传光器(line_transmission)
阻碍物(obstacle)
炸弹(bomb)
时间漏斗(time_funnel)
变色器(colour_changing)
选取框(choice_box)

如果,我建立一个Devicebase类作为这些设备的基类,估计也没有什么不妥,不过这些设备之间有的相同点实在是不多,因此要建立Devicebase类似乎意思不大。我又考虑这些设备应该有的共同点是:
Draw,在给定的x和y的范围内绘制自己的形状和外观
GetFocus,当得到焦点的时候,要在当前设备框的周围绘制出手柄标记
LostFocus,当失去焦点的时候,要在当前设备框的周围撤销手柄标记
所以我打算声明一个接口IDevice,该接口声明了以上的方法。

因此Board类的AddDevice为:IDevice,x,y这样会比较好点,感觉。
然后,我要添加一个新的设备:空白(blank),6*6的表格默认存放的都是空白,该blank当然也实现IDevice接口。

接下来,我们要考虑光,光是不是对象呢?那一定是的。我们需要一个Light类。从游戏的直观角度来讲,line_head需要一个Send方法,其他的设备需要一个Receive方法。
具有Receive方法的设备体现多态,每个设备有自己对光的处理模式:延伸,阻隔和爆炸等。延伸其实就是继续对光线的绘制。所以,我们在设计的时候,如果考虑对光的绘制是由设备来控制的,我感觉就错了。
我的设计是:光由自己绘制,但绘制的控制权由Board负责,设备向Board描述光的方向性。
比如:
line_head向Board发出消息要求从x,y开始沿什么方向绘制什么颜色Light
Board沿方向计算Table中沿途的第一个设备,然后将控制权给Light绘制。
Light绘制完毕后,Board通知第一个遇到的设备接受光线
该设备依据自身的规则计算光线的延伸,并发消息给Board,Board再计算。
如果Board计算出的第一个设备是bomb,则游戏结束


有些设备允许旋转和移动
因此我们要再声明

IRotate接口
ToClockwise  顺时针
ToCounterclockwise  逆时针

IMove接口
ToUp
ToDown
ToLeft
ToRight

我们希望当设备得到焦点的时候,绘制出的句柄可以有明显的提示让用户该设备是不是可以旋转或移动,或都不行。
(所有用具的移动和旋转都需要靠选取框来完成~~选取框移动到没有用具的格子或该用具不可移动和旋转的时候~选取框表示成状态1~~当移动到可移动和旋转的用具时候~选取框表示成状态2~~玩家第一次确认后,就可移动该用具,选取框表示成状态3~玩家第二次确认后,就可旋转该用具,选取框表示成状态4~~玩家第三次确认后,完成对该用具的操作,选取框表示成状态2~~当选取框处于状态1和状态2的时候~可以上下左右的移动~来捕捉用具~~在状态3下,移动用具即移动选取框,选取框的状态应同时带进新的Cell中~~)

选中了以后~先是移动~再是旋转~~

我考虑底盘的每个单元格都应该是一个对象,我们把它声明为Cell对象,该对象是一个容器对象,当Board初始化的时候,每一个Cell都存放的是Blank对象,当Board使用AddDevice方法放入设备时,其实是将设备放入Cell中。
为什么我要这样做呢?我这样考虑的,依据MVC,视图(玩家直接观察的部分)的变化其实是对数据(Board)的操作呈现。Board提供所有对游戏行为的支持,只不过这些行为分为两种
一种是:Board的直接行为,比如提供用户对Cell选择确定等控制
一种是:对设备的控制,这些行为其实是包装了设备的行为。

所以,底盘(Board)需要一个CurrentCell属性,描述当前具有焦点的单元格。底盘实现上下左右的方法(IMove接口),这些方法影响CurrentCell属性。CurrentCell总是返回当前Board有焦点的那个Cell。
当Board执行IMove接口的方法时,会激发单元格焦点改变的事件,该事件会通知单元格中的设备改变绘制手柄(就是那个选取框)。得到焦点的时候绘制手柄,失去焦点的时候消除手柄。

绘制选取框是一个很值得考虑的问题,从效果来说,我们希望每个设备的选取框都不一样,感觉好看点,还有设备的可旋转和可移动也希望选取框有不同的绘制效果,但是也有可能大部分设备的选取框绘制效果一样,如果你认为要写一个DeviceBase来实现选取框的绘制也可以,不过我提供另外的思路。

Cell来实现默认的焦点得失时的选取框的绘制。
首先设备要实现Can系列属性,向它所在的单元格描述当前设备是否可以旋转或者移动等。这个我们可以在IDevice接口中声明CanRotate,CanMove,当Cell得到焦点的时候,它根据它所容纳的设备的Can系列来绘制选取框。如果设备提供了自己的选取框,那Cell将用设备的绘制方法替换Cell的默认,这种方式是我从ASP.Net学来的。这种设计模式,要比继承更灵活有意思。

在LabVIEW中设计交通灯系统的VI程序,可以按照以下步骤进行: ### 实验目的 1. **掌握VI编辑方法** 2. **掌握VI调试方法** 3. **学会定义严格自定义类型变量** 4. **能够正确使用程序运行结构和基本函数** ### 设计思路 1. **初始化状态**: - 初始状态下,所有方向均为红灯。 2. **设计布尔簇**: - 使用布尔簇来表示每个方向的红、黄、绿灯的状态。例如,可以用三个布尔值(红、黄、绿)来表示一个方向的灯状态。 3. **使用While循环**: - 使用While循环来控制整个交通灯系统的循环运行。循环内部将包含条件结构,用于切换不同方向的灯状态。 4. **条件结构**: - 在While循环内部,使用条件结构(Case Structure)来实现不同状态之间的切换。可以根据当前状态选择下一个状态。 5. **状态切换逻辑**: - 南北绿灯 -> 南北黄灯 -> 南北红灯 -> 东西绿灯 -> 东西黄灯 -> 东西红灯,然后回到初始状态。 - 添加一个停止按钮,当按下停止按钮时,While循环终止,程序结束。 ### 实现步骤 1. **创建布尔簇**: - 创建两个布尔簇,分别表示南北方向和东西方向的灯状态。 2. **设置初始状态**: - 将所有方向的灯状态初始化为红灯。 3. **设计While循环**: - 在While循环内,使用一个计数器或状态机来跟踪当前的灯状态。 4. **使用条件结构**: - 根据当前状态,使用条件结构切换到下一个状态,并更新相应的布尔簇值。 5. **添加延时**: - 在每个状态之间添加延时,以模拟实际交通灯的时间间隔。 6. **添加停止按钮**: - 在While循环的条件输入处,添加一个停止按钮,当按钮被按下时,循环终止。 7. **调试程序**: - 运行程序,观察交通灯是否按预期顺序切换。如果发现问题,通过调试工具(如探针、断点等)进行排查和修正。 ### 示例代码片段 ```labview - 初始化部分: - 设置所有方向的灯状态为红灯。 - While循环: - 循环条件:停止按钮未被按下。 - 循环体: - 使用条件结构判断当前状态。 - 更新布尔簇值,切换到下一个状态。 - 添加延时。 - 停止按钮: - 当停止按钮被按下时,退出While循环。 ``` ### 注意事项 - **调试技巧**:使用LabVIEW的探针功能检查信号传递是否正确,使用断点逐步执行程序,观察变量变化。 - **优化建议**:可以考虑使用状态机结构来管理多个状态的切换,使程序更加清晰和易于维护。 希望以上设计思路对你有所帮助!如果有任何具体问题,欢迎继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值