使用GM8制作五子棋.docx
- 文档编号:5869041
- 上传时间:2023-01-01
- 格式:DOCX
- 页数:15
- 大小:27.54KB
使用GM8制作五子棋.docx
《使用GM8制作五子棋.docx》由会员分享,可在线阅读,更多相关《使用GM8制作五子棋.docx(15页珍藏版)》请在冰豆网上搜索。
使用GM8制作五子棋
使用GM8制作五子棋
最主要的对象就是:
对象信息:
obj_init
精灵:
<没有精灵>
固体:
false
可见:
true
深度:
0
持久:
false
父对象:
<没有对象>
遮罩:
<与精灵相同>
创建事件:
执行代码:
my_turn=1//我的顺序为1,黑子先手
offset_x=0//可以放置棋子的位置
offset_y=0
min_row=15//目前棋盘上棋子区域最小的行
min_col=15//目前棋盘上棋子区域最小的列
max_row=1//目前棋盘上棋子区域最大的行
max_col=1//目前棋盘上棋子区域最大的列
计时器事件-计时器0:
用于判断放置黑子之后,是否黑子获胜,并通过scr_go(),自动放置白子
执行代码:
if(instance_number(obj_black)>4)//如果黑子数量大于4
{
if(scr_iswin(offset_xdiv32,offset_ydiv32,obj_black))//判断放下的黑子是否能赢
{
instance_create(room_width/2,room_height/2,obj_showinfo)//如果黑子赢,创建显示对象
obj_showinfo.image_index=0
}
}
if(!
instance_exists(obj_showinfo))//如果黑子没有赢
{
scr_go()//启动scr_go(),自动放置白子
alarm[1]=1//启动时钟1事件
}
计时器事件-计时器1:
:
用于判断放置白子之后,是否白子获胜,并将我的顺序设置为1,可以放置黑子
执行代码:
if(instance_number(obj_white)>4)//如果白子数量大于4
{
if(scr_iswin(offset_xdiv32,offset_ydiv32,obj_white))//判断指定位置白子是否能赢
{
instance_create(room_width/2,room_height/2,obj_showinfo)//如果白子赢创建显示对象
obj_showinfo.image_index=1
}
}
my_turn=1//将我的顺序重置为1,以便放置黑子
步事件:
获取鼠标指针所对应的棋盘中的位置
执行代码:
offset_x=(round(mouse_x/32))*32//鼠标指针位置除以32四舍五入之后再乘32
offset_y=(round(mouse_y/32))*32
鼠标事件-全局左键按下:
用于放置黑子
执行代码:
if(offset_x>=32andoffset_y>=32andoffset_x<=480andoffset_y<=480andposition_empty(offset_x,offset_y)and!
instance_exists(obj_showinfo))//如果鼠标指针在棋盘区域,同时并没有分出胜负
{
if(my_turn=1)//如果我的顺序为1,即该玩家下子
{
instance_create(offset_x,offset_y,obj_black)//在指定位置放置黑子
scr_rowcol(offset_x,offset_y)//调用scr_rowcol(),设置目前棋盘上已有棋子区域
my_turn=2//将我的顺序设置为2,即为该电脑下棋
alarm[0]=2//启动时钟事件0
}
}
鼠标事件-全局右键按下:
该事件用于测试,实际用不到,右击棋子,查看当前位置棋子的价值
执行代码:
if(offset_x>=32andoffset_y>=32andoffset_x<=480andoffset_y<=480and!
position_empty(offset_x,offset_y))//如果鼠标在棋盘区域,并且指定位置存在棋子
{
show_message(scr_checked(instance_position(offset_x,offset_y,all)))//判断该位置的价值
}
绘制事件:
用于绘制棋盘,画指针
执行代码:
draw_set_alpha(0.5)//设置透明度
for(i=1;i<16;i+=1)//绘制棋盘网格线
{
draw_line(32,i*32,480,i*32)
draw_line(i*32,32,i*32,480)
}
draw_set_alpha
(1)//设置透明度为不透明
draw_circle(128,128,3,0)//左上点
draw_circle(128,384,3,0)//左下点
draw_circle(384,128,3,0)//右上点
draw_circle(384,384,3,0)//右下点
draw_circle(256,256,3,0)//中心点
if(offset_x>=32andoffset_y>=32andoffset_x<=480andoffset_y<=480)//如果鼠标指针在棋盘内
{
if(my_turn=1)draw_circle(offset_x,offset_y,5,0)//跟随鼠标指针的黑点
else//跟随鼠标指针的白点
{
draw_set_color(c_white)
draw_circle(offset_x,offset_y,5,0)
draw_set_color(c_black)
}
}
draw_text(500,180,"black:
"+string(instance_number(obj_black)))//绘制文本黑子数量
draw_text(500,220,"white:
"+string(instance_number(obj_white)))//绘制文本白子数量
键盘按下事件-R-key键:
游戏重置
执行代码:
room_restart()
除了obj_init之外,还有obj_black与obj_white用于显示黑子与白子,什么也不用做。
另外还有obj_showinfo,用于在游戏结束时显示是玩家胜利还是电脑胜利。
游戏的执行顺序是,游戏启动,当玩家按下鼠标左键,创建黑子,第一个被调用的函数是:
scr_rowcol(),该函数用于设置当前棋盘上的棋子区域的四个值,即最小行最大行最小列最大列。
之后,在对象的时时钟0事件中调用了scr_iswin()函数用于判断黑棋是否获胜,再调用scr_go()用于放置白棋。
之后启动时钟1事件,判断白棋是否获胜重置my_turn变量。
一直重复,直到一方获胜。
scr_iswin()仅判断指定位置的指定棋子是否会获胜,其中也并未引用其他函数。
scr_go()用于电脑放置白色棋子,其中也调用了函数:
scr_rowcol(),用于重置棋盘棋子区域的值。
同时还调用了函数:
scr_checked(),该函数用于获取在某一位置放置某一棋子时的得分情况。
而在函数scr_checked()中,调用了函数scr_move()用于判断能否向某一个方向移动,同时还调用了函数:
scr_gets_oneline()用于获取一行的得分情况。
这样整个过程就明晰了。
几个脚本之间的关系如下:
以上脚本中,
scr_iswin()相对独立,不被其他脚本调用,用于判断是否存在黑白双方有五个子连在一起的情况。
scr_go()用于电脑AI下棋,在整个体系中处于核心位置,其调用scr_checked()用于获取得分情况,调用scr_rowcol()仅用于重置棋盘下子区域大小,便于判断。
scr_checked()则属于二级核心的位置,该脚本为scr_go()服务,同时也需要scr_move()与scr_gets_oneline()为自己服务。
scr_move()与scr_gets_oneline()处于最底层,这两个脚本为scr_checked()提供服务,分别用于判断能否向某个方向移动,和获取一行的得分情况。
介绍完了整个脚本体系。
下面就按顺序来依次说明几个脚本的具体内容。
scr_iswin(),判断游戏是否结束,即有没有黑子或者白子连成一排5个棋子的情况。
vart_x,t_y,start_x,end_x,start_y,end_y,num,i,flag,obj_target;//定义一组变量
t_x=argument0//落下子的位置横坐标
t_y=argument1//落下子的位置纵坐标
obj_target=argument2//落下的子
num=0//初始数量为0
start_x=t_x-4//当前位置向左的第4个位置
start_y=t_y-4//当前位置向上的第4个位置
end_x=t_x+4//当前位置向右的第4个位置
end_y=t_y+4//当前位置向下的第4个位置
for(i=start_x;i<=end_x;i+=1)//从左向右循环
{
if(position_meeting(i*32,t_y*32,obj_target))//如果遇到同样的棋子
{
num+=1//数量加1
if(num==5)returntrue//如果数量等于5,返回true
}
elsenum=0;//如果没遇到则数量置为0
}
for(i=start_y;i<=end_y;i+=1)//从上到下循环
{
if(position_meeting(t_x*32,i*32,obj_target))
{
num+=1
if(num==5)returntrue
}
elsenum=0;
}
flag=min(end_x-start_x,end_y-start_y)//找出横纵坐标中的最小值
for(i=0;i<=flag;i+=1)//开始循环
{
if(position_meeting((start_x+i)*32,(start_y+i)*32,obj_target))//从左上向右下
{
num+=1;
if(num==5)returntrue
}
elsenum=0;
}
for(i=0;i<=flag;i+=1)//开始循环
{
if(position_meeting((start_x+i)*32,(end_y-i)*32,obj_target))//从从左下到右上
{
num+=1;
if(num==5)returntrue
}
elsenum=0;
}
returnfalse//如果都没有等于5,返回false
scr_go,白子(电脑AI所执棋子)自动下棋。
vari,j,temp_obj,ai_score,player_score,index,my_col,my_row,max_score,temp,temp_list,my_list;
index=0;//索引为0
my_list=ds_list_create()//创建一个列表用于存放变量
for(i=min_row;i<=max_row;i+=1)//从行开始循环
{
for(j=min_col;j<=max_col;j+=1)//在列中循环
{
if(position_empty(j*32,i*32))//如果当前位置为空
{
temp_obj=instance_create(j*32,i*32,obj_white)//先创建一个白棋子
temp_obj.visible=0//白棋子不可见
ai_score=scr_checked(temp_obj)//检测当前放子之后的AI得分
with(temp_obj)//销毁创建的白棋子
{
instance_destroy()
}
temp_obj=instance_create(j*32,i*32,obj_black)//再创建一个黑棋子
temp_obj.visible=0//黑棋子不可见
player_score=scr_checked(temp_obj)//检测放黑子之后玩家得分
with(temp_obj)//销毁黑棋子
{
instance_destroy()
}
ds_list_add(my_list,ai_score+player_score)//将AI得分与玩家得分之和添加到列表
my_col[index]=j//将列位置存到数组
my_row[index]=i//将行位置存以数组
index+=1//索引增加1
}
}
}
max_score=0//将最高分置为0
for(i=0;i { temp=ds_list_find_value(my_list,i) if(temp>max_score)max_score=temp//获取最高得分 } temp_list=ds_list_create()//再创建一个临时列表 for(i=0;i { temp=ds_list_find_value(my_list,i)//找出指定位置的值 if(temp=max_score)ds_list_add(temp_list,i)//将所有最大分值位置添加到临时列表 } temp=ds_list_size(temp_list)//获取列表长度 temp=irandom_range(0,temp-1)//随机取一个位置 index=ds_list_find_value(temp_list,temp)//找出该随机位置的值 instance_create(my_col[index]*32,my_row[index]*32,obj_white)//在该随机位置创建白棋子 obj_init.offset_x=my_col[index]*32//重置offset_x obj_init.offset_y=my_row[index]*32//重置offset_y scr_rowcol(my_col[index]*32,my_row[index]*32)//调用scr_rowcol定义可下子区域 scr_rowcol()重新定义可下子区域(最大最小行列) if((argument1div32-2) if(min_row<1)min_row=1//最小行超出边界 if((argument0div32-2) if(min_col<1)min_col=1//最小列超出边界 if((argument1div32+2)>max_row)max_row=argument1div32+2//获取最大行 if(max_row>15)max_row=15//最大行超出边界 if((argument0div32+2)>max_col)max_col=argument0div32+2//获取最大列 if(max_col>15)max_col=15//最大列超出边界 scr_checked(),检测得分情况 vart_x,t_y,obj_target,i,j,num,state1,state2,temp,temp_s; t_x=argument0.x//获取放置棋子横坐标 t_y=argument0.y//获取放置棋子纵坐标 obj_target=argument0.object_index//获取实例的对象索引 num=0//数量等于0 i=0 j=0 //水平向左检测 while(true) { i-=1; temp=scr_move(t_x,t_y,i,0,obj_target)//调用move函数,当前位置向左移动纵坐标不变横坐标每次减1 if(temp=1)num+=1//如果返回结果为1(移动位置与目标对象相同)则增加1 elsebreak;//如果没有返回1则跳出循环 } if(temp=0)//如果temp=0(移动到位置为空) { if(t_xdiv32+i>0)state1="l"//如果未碰到边界返回状态1为l elsestate1="d"//如果碰到边界返回状态1为d } elsestate1="d"//如果不为0则状态1为d //水平向右检测 i=0 while(true) { i+=1; temp=scr_move(t_x,t_y,i,0,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_xdiv32+i<16)state2="l" elsestate2="d" } elsestate2="d" //返回结果 num+=1 temp_s[0]=scr_gets_oneline(state1+string(num)+state2);//调用scr_gets_oneline获取水平一行的得分 //垂直向上检测 i=0 num=0 while(true) { i-=1; temp=scr_move(t_x,t_y,0,i,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_ydiv32+i>0)state1="l" elsestate1="d" } elsestate1="d" //垂直向下检测 i=0 while(true) { i+=1; temp=scr_move(t_x,t_y,0,i,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_ydiv32+i<16)state2="l" elsestate2="d" } elsestate2="d" //返回结果 num+=1 temp_s[1]=scr_gets_oneline(state1+string(num)+state2)获取垂直方向的得分 //斜向左上角检测 i=0 num=0 while(true) { i-=1; temp=scr_move(t_x,t_y,i,i,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_ydiv32+i>0andt_xdiv32+i>0)state1="l" elsestate1="d" } elsestate1="d" //斜向右下角检测 i=0 while(true) { i+=1; temp=scr_move(t_x,t_y,i,i,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_ydiv32+i<16andt_xdiv32+i<16)state2="l" elsestate2="d" } elsestate2="d" //返回结果 num+=1 temp_s[2]=scr_gets_oneline(state1+string(num)+state2)//获取左上右下得分 //斜向左下角检测 i=0 j=0 num=0 while(true) { i-=1; j+=1 temp=scr_move(t_x,t_y,i,j,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_xdiv32+i>0andt_ydiv32+i<15)state1="l" elsestate1="d" } elsestate1="d" //斜向右上角检测 i=0 j=0 while(true) { i+=1; j-=1; temp=scr_move(t_x,t_y,i,j,obj_target) if(temp=1)num+=1 elsebreak; } if(temp=0) { if(t_xdiv32+i<16andt_ydiv32+j>0)state2="l" elsestate2="d" } elsestate2="d" //返回结果 num+=1 temp_s[3]=scr_gets_oneline(state1+string(num)+state2)//获取左下右上得分 return(temp_s[0]+temp_s[1]+temp_s[2]+temp_s[3])//返回4个方向最终结果得分 scr_gets_oneline()获取一行得分情况 varnum; num=real(string_char_at(argument0,2))//获取中间的值(多少个) if(num>4)return100000//如果有5子相连返回100000 elseif(num=1)return0//如果仅有1个返回0 else { if(string_count("d",argument0)=2)return0//如果字串中有两个d两头被堵 elseif(string_count("d",argument0)=1)//如果一头被堵
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 使用 GM8 制作 五子棋
![提示](https://static.bdocx.com/images/bang_tan.gif)