1:Play入口函数
Server每次产生一个方块后,都会调用该dll的play方法作为入口执行。
因此,实际上只要完成void play()函数的实现即可。
2:必备的api接口
为了完成play()的逻辑,至少需要通过以下几个必备api接口:
l 获取我方当前20*10的matrix的第iRow行iCol列是否含有砖块 //true有 false没有
bool api_getMatrixInfo(uint uiRow, uint uiCol);
l 获取当前到来的block的编号 //返回值: 0-6,由服务器保证
uint api_getCurrBlock();
l 设定如何落下当前的方块
void api_addStepMethod(uint uiRotate, uint uiCol);
l 打日志
void api_log(constchar* fmt, ...); //和printf用法相同
3:样例
|
void play() |
4:扩展的api接口
为了更好地完成play()的逻辑,可以通过以下几个扩展api接口:
l 获取对方当前20*10的matrix的第iRow行iCol列是否含有砖块//true有 false没有
bool api_getMatrixInfoOppo(uint uiRow, uint uiCol);
一般用不着,除非想分析对方的行为
l 获取即将到来的block的编号//返回值: 0-6,由服务器保证
uint api_getNextBlock();
如果你的程序不仅想分析当前将到来的方块,还想分析下一个方块,就需要这个接口
l 设定如何落下当前的方块(高级)
voidapi_addStepMethod(uint uiRotate, uint uiCol, uint uiDown);
原函数是:voidapi_addStepMethod(uint uiRotate, uint uiCol);将当前block旋转iRotate后,置入iCol列,自然下降;
它多了一个uiDown参数。而多了uiDown参数,语义就变成了:将当前block旋转iRotate后,置入iCol列,下降iDown格(不再是自然下降!)
如果你的程序想让方块落下的过程中可以左拐和右拐中转一下,就需要这个接口了。
l 打日志(高级)
void api_log_without_logheader(const char* fmt, ...);
api_log总是会输出一个行的头部,有个别的场景下,你只想输出一个字符不想有头部,就需要这个接口了。
5:关于Matrix
Matrix就是一个20行,10列的容器,所有的方块都要落入到该容器中。涉及Matrix的函数有api_getMatrixInfo和api_getMatrixInfoOppo
注意,C/C++都是自0计数的,因此Matrix最上方的Row=0,最下方Row=19(不是20!!)
Matrix最左侧的Column=0, Matrix最右侧的Column=9(不是10!!)
6:关于Block
Block就是下降的大方块,每个大方块都是由4个小方块组成。
Block一共有7种
每种Block都有4种旋转状态。分别为Rotate = 0/1/2/3
当然,对于有的方块而言,旋转状态是一样的。例如正方块,等。
某Block在Matrix某一列下降,是指该Block的最左侧从Matrix的该列下降。
因此,一个方块往往在col=8,col=9的时候就不能下落的,因此block自身具有宽度。一旦下落,直接判负。
l Block=0: 就是正方形方块,因为像英文字母O,所以也叫BLOCK_O
#define BLOCK_O 0// rotate=0 rotate=1 rotate=2 rotate=3
// |** | |** | |** | |** |
// |** | |** | |** | |** |
// | | | | | | | |
// | | | | | | | |
l Block=1: 就是长竖条,因为像英文字母I,所以也叫BLOCK_I
#define BLOCK_I 1// rotate=0 rotate=1 rotate=2 rotate=3
// |* | |****| |* | |****|
// |* | | | |* | | |
// |* | | | |* | | |
// |* | | | |* | | |
l Block=2: 就是三叉路口状的方块,因为像英文字母T,所以也叫BLOCK_T
#define BLOCK_T 2// rotate=0 rotate=1 rotate=2 rotate=3
// |*** | | * | | * | |* |
// | * | |** | |*** | |** |
// | | | * | | | |* |
// | | | | | | | |
l Block=3: 就是拐棍的方块,因为像英文字母L,所以也叫BLOCK_L
#define BLOCK_L 3// rotate=0 rotate=1 rotate=2 rotate=3
// |* | |*** | |** | | * |
// |* | |* | | * | |*** |
// |** | | | | * | | |
// | | | | | | | |
l Block=4: 就是拐棍的方块(与BLOCK_L对称),因为像英文字母L,所以也叫BLOCK_L
#define BLOCK_J 4// rotate=0 rotate=1 rotate=2 rotate=3
// | * | |* | |** | |*** |
// | * | |*** | |* | | * |
// |** | | | |* | | |
// | | | | | | | |
l Block=5: 因为像英文字母Z,所以也叫BLOCK_Z
#define BLOCK_Z 5// rotate=0 rotate=1 rotate=2 rotate=3
// |** | |* | |** | | * |
// | ** | |** | | ** | |** |
// | | |* | | | |* |
// | | | | | | | |
l Block=6: 因为像英文字母S,所以也叫BLOCK_S
#define BLOCK_S 6// rotate=0 rotate=1 rotate=2 rotate=3
// | ** | |* | | ** | |* |
// |** | |** | |** | |** |
// | | | * | | | | * |
// | | | | | | | |
6:关于Round
Server执行时,最小粒度是Round(轮次)。
每个Round开始时,Server都是产生一个新的Block。
每个Round内,Server调用且只调用一次dll的play方法。
dll的play方法内,只能完成当前容器局面(Matrix)下的决策。当调用api_addStepMethod时,server并不会立即使block下降,而是在play函数退出后统一处理。
7:进攻
Tetris并非是比双方是否能消除最多的行。因为在对战规则中,当一方一次性消除多行时,将会对对方形成“进攻”,即对方增行。(从最下方“顶上去”一些交错的方块)
|
被顶之前 |
被顶之后 |
|
------------ |
------------ |
注意上面的感叹号,就是被顶上去的部分。
这个感叹号也是普通的方块,你大可以后续把它消除掉。
本文介绍Tetris对战中DLL编程的核心概念和技术细节,包括必要的API接口使用、扩展API接口的功能、Matrix和Block的基本操作及游戏的进攻机制。

478

被折叠的 条评论
为什么被折叠?



