这两个星期,要求用flash做一个五子棋,就借了几本书,翻了一遍,大致的熟悉了其脚本的语法,问了同学五子棋大致怎么写。开始动手自己写。
人人模式:
由于棋盘是15*15大小,故开三个一维数组,分别为 arrX(记录落子
点的横向距离) , arrY(记录落子点的纵向距离) , arrXY(记录落子点的状态,如:黑棋为-1,白棋为1),大小均为255。这三个数组用于悔棋。另开一个数组arr(与arrXY一样,也是记录落子点的状态,大小同样为255,初始值全设为0,因为初始状态棋盘无子,0表示此处无子),用来下子的时候判断是否有黑子或者白子,若有则需重新点击空位,无则进行加载棋子。每加载一子就进行扫描判断胜负。大致方法如下:
加载棋子后,以该点为中心:横向,纵向,两条对角线。共四个方向进行搜索判断是否有五子相连状态出现,若有则结束此局,无则继续点击棋盘空位进行加载棋子。
另外一种搜索方法:每加载一子,就以原点为起始点,进行整张棋盘的扫描搜索。
加载后若未赢也未输,可以选择悔棋,利用原先记录X,Y及状态的三个数组进行悔棋。
人人模式部分代码如下:
if(true == canPlay)
{
var black_chess = new BlackChess();
getX = int((e.stageX-100)/20);
getY = int((e.stageY-50)/20);
if(arr[getX][getY] == 0)
{
arrX[chessX++] = getX*20+100;//记录横坐标
arrY[chessY++] = getY*20+50;//记录纵坐标
arrXY[index++] = -1;
//以上用于悔棋
arr[getX][getY] = -1;//黑棋为-1
black_chess.x = getX*20+100;//对要加载的棋子的X和Y,即在棋盘上的位置进行设置
black_chess.y = getY*20+50;
aChessmen.push( black_chess);//用于悔棋
againChessmen.push(black_chess);//用于再来一遍清除棋子
addChild(black_chess);//加载棋子
B_btn.visible = false;
A_btn.visible = true;//加载棋子后对按钮进行隐藏和显示设置
undo_btn.addEventListener(MouseEvent.CLICK, undo);//悔棋的监听
//赢棋
if(winChesses())
{
btn_replay.visible = true;
winchess.x = 200;
winchess.y = 200;//为胜利的文本设置X和Y的距离
win_btn.visible = true;//显示胜利文本
//btn_replay.visible = true;
man_btn.removeEventListener(MouseEvent.CLICK, manbtn_hand);
White_bTn = false;
Black_bTn= false;//赢棋之后将状态设置为false,即不能下棋
undo_btn.removeEventListener(MouseEvent.CLICK, undo)//赢了后不能悔棋
A_btn.removeEventListener(MouseEvent.CLICK,A_btnhand);
B_btn.removeEventListener(MouseEvent.CLICK,B_btnhand);//赢棋后撤销下棋按钮的监听
btn_replay.addEventListener(MouseEvent.CLICK, again);//再来一局的监听
}
}
}
人机模式:人机模式比较复杂的就是怎么判断其空位的分值,然后机器决定进行防守还是攻击。
这里粗略讲解核心部分:
开一个255大小的数组,用来存储棋盘上的每个位置的分值
机器加子之前,原点开始进行搜索,开一个15*15的二维数组,扫描每一个位置,若该位置上有子,则把-1,以及该点的X和Y距离,以对象形式存入开好的数组中(-1表示此位置无价值,机器不能在该位置落子),若无子,则以该点为据点,进行四个方向的搜索,记录人机双方的棋型,并利用棋型评估该位置上对于人机双方的价值大小,从而机器决定是进攻还是防守
人机模式更好的算法,例如运用alpha-beta剪枝,极大值极小值等算法,需要继续深入学习这些算法