TA的每日心情 | 慵懒 2015-1-8 08:46 |
---|
签到天数: 2 天 连续签到: 1 天 [LV.1]测试小兵
|
2#
楼主 |
发表于 2007-11-16 17:15:44
|
只看该作者
推论式思考 相信曾经接触过电脑语言课程,或是自习过相关书籍的朋友们,都曾曾经听过一个著名的程序,那就是井字游戏。用井字游戏作为讨论AI的入门教材,我个人觉得是最适当的例子。或许有人还不知道井字游戏怎么玩。只要任何一方在三乘三的方格中先先成一线便胜利了。我们在前面谈过的规则导向,在这里也可以派得上用场。
if任何一线已有我方两子&&另外一格仍空//我方即将成一线吗
结果 = 该空格
if任何一线已有敌方两子&&另外一格仍空//防止敌方作成一线
结果 = 该空格
if任何一线已有我方一子&&另外两格仍空//作成两子
结果 = 该空格
有一次我在某本电脑书上,同样地也看到某些以井字游戏为介绍的范例。不同的是,我几乎看不到任何规则导向的影子。但在仔细分析该程序码后,我得到了极大的启发,原来AI是可以不用这么多规则来制作的。它用的方法正是在电脑AI课程中重要的概念:极大极小法。我在这里只说明这法则的概念。继续以井字游戏为例,电脑先在某处下子,接着会以假设的方式,替对方下子,当然,必须假设对方下的是最佳位置,否则一切则毫无意义。在假设对方下子的过程中,自然又需要假设我方的下一步回应,如此一来一往,直到下完整局游戏为止。 底下是节录书中的程序片段:
bestMove(int p, int*v)
{ int i;
int lastTie;
int lastMove;
int subV;
/*First, check for a tie*/
if (isTie()) {
*v=0;
return(0);
};
/*If not a tie, try each potential move*/
for (*v=-1, lastTie=lastMove=-1,i=0;i<9;i++)
{
/*If this isn't a possible, skip it*/
if (board!=0) continue;
/* Make the move. */
lastMove=i;
board=p;
/* Did it win? */
if (hasWon(p)) *v=1;
else{
/*If not, find out how good the other side can do*/
bestMove(-p,&subV);
/* If they can only lose, this is still a win.*/
if (subV==-1) *v=1;
/* Or, if it's a tie, remember it. */
else if (subV==0){
*v=0;
lastTie=i;
};
};
/* Take back the move. */
board=0;
/*If we found a win, return immediately
(can't do any better than that)*/
if (*v==1) return(i);
/*If we didn't find any wins, return a tie move.*/
if (*v==0) return(lastTie);
/*If there weren't even any ties, return a loosing move.*/
else return(lastMove);
};
国外的一些论坛曾举行过256字节的游戏设计比赛。作品非常多,其中有一件作品正巧也是井字游戏。作者用区区两百多行就写了与上述程序演算方式完全相同的作品,可见功力确实了的。另外,我也很希望类似的活动能在国内推展起来。对了,在这样的比赛条件限制下,除了汇编语言外,几乎没有其它的选择了。 .386c
code segment byte public use16
assume cs:code, ds:code
org 100h
tictac proc far
start:
push cs
pop ds
mov ax,0B800h ; 清除屏幕
mov es,ax ;
xor di,di ;
mov cx,7D0h ;
mov ax,0F20h ;
rep stosw ;
xor cx,cx ;
mov dl,5
loc_1:
call printBoard
loc_2:
mov ah,8 ; 等待按键
int 21h
movzx bx,al
sub bl,31h ; 如果不是1..9
jc loc_2 ; 则重新输入
cmp bl,8
ja loc_2
cmp data_1[bx],al
jne loc_2
mov byte ptr data_1[bx],'x'
dec dl
jz short loc_3
mov al,'o'
call bestMove
mov [si],al
call isWin ; 判断是否已取得胜利
jnc loc_1
loc_3:
call printBoard
mov ax,4C00h
int 21h
data_1 db '12'
data_2 db '3456789'
data_3 db 0
tictac endp
printBoard proc near
mov si,offset data_1
mov di,548h
mov cl,3
locloop_4:
movsb
add di,5
movsb
add di,5
movsb
add di,133h
loop locloop_4
retn
printBoard endp
isWin proc near
mov bx,1
mov bp,3
call sub_3 ; 检查横向是否完成
inc bx
inc bx
dec bp
dec bp
call sub_3 ; 检查纵向是否完成
call sub_4 ; 检查斜向是否完成
clc
retn
isWin endp
loc_5:
stc
retn
sub_3 proc near
mov ah,3
mov si,offset data_1
loc_6:
mov di,si
call sub_5
add si,bp
dec ah
jnz loc_6
retn
sub_3 endp
sub_4 proc near
mov di,offset data_1
inc bx
call sub_5
mov di,offset data_2
dec bx
dec bx
call sub_5
retn
sub_4 endp
sub_5 proc near
mov cl,3
locloop_7:
cmp [di],al
jne short loc_ret_8
add di,bx
loop locloop_7
add sp,4
jmp short loc_5
loc_ret_8:
retn
sub_5 endp
bestMove proc near
mov bx,31FEh
mov cl,9
mov di,offset data_1
locloop_9:
cmp [di],bh ; #empty?
jne short loc_12 ; #no, skip
mov [di],al
pusha
call isWin ; #CY: Win
popa ;
jnc short loc_10 ;
mov bl,1
mov si,di
mov [di],bh
retn
loc_10:
pusha
xor al,17h ; good! toggle 'o' / 'x'
call bestMove
mov data_3,bl
popa
mov ah,data_3
neg ah
cmp ah,bl
jle short loc_11
mov bl,ah
mov si,di
loc_11:
mov [di],bh
loc_12:
inc bh
inc di
loop locloop_9
cmp bl,0FEh
jne short loc_ret_13
xor bl,bl
loc_ret_13:
retn
bestMove endp
code ends
end start
7.游戏引擎 小谢
-------------------------------------------------------------------------------
早想写一点游戏设计的文章与大家交流,一是经验的问题,二是公司正在紧张的游戏制作期,实 在抽不出多少时间,一直没有动手,今天忽然头脑发热,写了一段,以后准备陆续写一些游戏创意,策 划,制作,流程管理,和制作工具等方面的文章供大家参考.
我们的游戏设计经验主要是冒险游戏和角色扮演游戏,但我们设计游戏工具时尽量适应其余题 材,不过是否可行未经检验. 写这篇文章的意图一是想为游戏界做点事,抛砖引玉吧,另外是公司正在寻找志同道合的战友, 我写一点文章交一交朋友,许多东西仅仅是我们的经验,不一定很好.参考而已吧
游戏设计工具包括游戏编辑工具和游戏引擎两块;
编辑工具:交互编辑游戏数据,生成游戏引擎所需的数据文件,包括以下几个功能块: 图像编辑,场景编辑,物品编辑,动画编辑,人物编辑,事件编辑等,具体介绍在以后的 文章介绍.
先从游戏引擎说起.
语言:VC5.0
操作系统:WIN95
图像引擎IRECT X 5.0
支持游戏风格:各种类型和视角以及多层次的冒险游戏和角色扮演游戏
整个游戏引擎包括以下功能块:
资源管理:图像库CIMGLIB,声音库CSOUNDLIB,通过编辑工具形成的资源文件来定义,每种资源 包括定义管理和一些操作接口.图像库图"像包括多种格式(BMP,GIF.AVI,FLC等)以及他形成的内存 格式定义,子图定义(每一张图片包括许多小图,需定义它的小图位置,当然可以自动生成),游戏需 要的特殊定义,比如行走,身体性质,中心定位点,触发区,可以根据自己的要求扩充各种性质定义. 图像最好允许图像组合定义.声音库包括WAV和 MID的定义和再现. 资源由IMGLIB.DAT和 SOUNGIMG.DAT定义,调试版本中最好不要将资源打包,而是指向正常的 文件名,发行版本中再打包,这样修改和不同工作人员协调容易一些,否则最好有一个自己的资源 管理器.我们在调试版本中数据文件采用文本描述格式.许多数据可以手工编写而不需要专门的 编辑工具.
资源管理对象还包括内存管理,比如设置时间阀释放长期不用的资源.
声音管理:CSOUND,包括Creat(),Sound(char *fileName...),SetPos(),等,DirectSound有一 些函数,我们要做的是封装简化,减少对外的接口.
窗口系统:接管标准窗口系统,一个完善的游戏引擎最好有一个自己的界面系统,至于简单还是 复杂根据自己情况具体分析,一个具备基本功能的界面系统1000行程序就可以对付下来,需要窗口 系统的原因是一般的图像引擎不支持标准窗口,二是可以便于移植到别的操作系统.在我们的游戏 引擎中,游戏只是窗口系统的一种特殊控件(CWINGMCTR),因此可以实现多窗口游戏等特殊要求.
CWINGMCTR是一种特殊控件,通过他来控制游戏.包括控制和显示.
图像引擎:所使用的图像引擎的管理,我们使用的是DirectX,包括Creat(),CreatSurface(), OutToScr(),Bilt()等对外接口;他不是游戏的重点,我们尽量将图像引擎细节封装起来.
图像管理:这是处理图像的中心,一般处理游戏显示喜欢以某种图像引擎为中心来设计,我觉得 最好设计自己的对象来封装别人的图像引擎,这样不会因某引擎而受限制,移植也比较容易,我们虽 然使用的DIRECT X ,但实际上对外的接口是一种CPICPAGE的界面,他不但包括DIRECT X 的surface, 也包括标准的位图,AVI界面,GIF动画界面,以及自定义的格式,他将各种类型的图像统一起来,对外 使用统一操作,比如DRAWTEXT,BILT,LINE等标准图形图像操作,以及扩充的ALPHA通道,透明度等操 作.为了减少内存的需求,特别是16M高彩,不要将全部图像使用DIRECT X的表面,对一些刷新不多的 图像,比如背景,可以使用标准256色位图,甚至一种GIF表面,需要时再解压,我们还使用一种单色位 图用来从背景中抠图,比如一所场景中一棵巨大的树,只要不是动画,我们可以用单色抠图的形式从 背景中扣除来作为另外一层,这样我们可以大大降低图像的内存需求.因此采用全部手绘(或3D场景), 而不是小图拼贴的场景成为可能.通过各种手段可以节约60%的内存需求.
CPICPAGE可以通过TimeTrace()以及多线程来改写内容,比如AVI的改变.
游戏控制:这部分包括显示和控制,由CGAME->CGAMEPAGE->CGMOBJ对象组成,CGAME是总控对象, 包括许多CGAMEPAGE游戏页,CGAMEPAGE是一个具有连续场景的游戏片断,有点类似于游戏的一关, CGAMEPAGE由一系列CGMOBJ组成,CGMOBJ是游戏的基本对象,由他继承出地图,物体,物品,人物,武器, 动画,触发器,多媒体按钮等特殊
游戏对象,这是一个根据游戏要求不断丰富和改写的部分,对外的 接口是:SendDraw(),Draw(),TimeTrace(),AcceptMsg(),SendNetMsg(),AcceptNetMsg()等,他是通 过CWINGMCTR来调用,每种对象有许多控制参数,对象之间允许通讯,以及有自己的生长死亡发展的 控制,尽量做到对象与外界减少直接接口,通过消息实现交流.
对象分为两类:景色对象和活动对象,
景色对象定义了组成场景的元素,包括背景和前景两层,可以是由整个图片组成或由RPG常用的 图片拼贴法的组成,它的特点只作为背景或前景,活动物是在他们的之间活动,一般定义后不做改变, 也不做控制,由于支持图像界面多格式,所以我们可以方便地使用AVI或 GIF动画作为背景来增加场 景的效果和真实性.景色还包括了行走性质定义,我们采用的是8x8为一单元,每个单元定义了一种 性质,比如平地,草地,障碍物等.
活动对象是在背景和前景之间活动,他们之间有相互的位置关系,前后关系随着位置改变会不断 改变,因此他在所属的CGAMEPAGE中次序是动态的.对象的关系一般是由Y轴定义,由于要支持斜视角和 复杂的地形结构,光靠Y轴是不够的,我们引入了地基线的概念,通过在地基线之上还是之下来判断前 后关系,地基线的定义在图像定义中描述.活动对象有复杂的参数,可以接受外界消息,可以有自己的 各种反应.我们在引擎中使用了一种描述语言来描述他们的反应,比如对鼠标击打,人物经过等产生 参数改变,发声,对话等的回应.描述语言将作为专门的一章来介绍. 游戏显示过程是这样的, 在每次刷新期时窗口的游戏控件调用他所属的游戏页 CGAMEPAGE->SendDraw(); 游戏页将要显示的对象按前后次序送往窗口,同时注明此对象是否改变,窗口分析改写的区 域,调用每个对象的Draw()接口来刷新活动的区域,为了增加速度,并不是显示所有的区域,而是只改 写活动区域,因此我们设计了一个CCLIP的对象来管理刷新定义,它的原理是将表面分为16*16的单元, 最终显示时计算出优化后的多个剪切区域.整个窗口系统和每个游戏控件拥有自己的CCLIP对象.另 外一项增加速度的方案是游戏控件拥有一个比显示窗大两倍的显示页,这样场景滚动时只要将显示 位置改变即可 ,不用刷新所有区域. 游戏控制的过程是这样的:AcceptMsg()来接受各种消息调用脚本来改变自己参数和状态并影响 别的对象,另外每次时钟来时,调用每个对象的TimeTrace()来改变状态,比如动画改变,运动轨迹改变, 观察周围的对象做出反应等.
系统控制模块:对系统的参数做出反应.不同的题材控制不一样,比如即时战略等.只要改写这部 分以及扩充游戏对象,引擎便能支持不同的题材.至于人工智能,智能行走,只是对象的方法,比较简 单,只是需要时间. 游戏控制部分比较复杂,每一种游戏对象都有许多控制的细节,在这篇文章里不做具体描述,以后 再说吧.
最后一个是网络模块:我们正在开发的是国内第一个图形化MUD游戏,网络是它的核心部分,介绍 网络的内容很多,需专门文章.我们使用的不是DirectPlay,使用的是WinSoct,考虑的是UNIX作为服务 器的需求.网络要解决的难点是安全,同步和数据压缩,这里要用到许多技巧. |
|