{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
其中,(1)棋盘状态数据由一个15×15的二维数组表示。(2)用数字“1”和“2”来表示不同的棋子,黑色棋子用“2”表示,白色棋子用“1”表示。(3)没有棋子的格子用“0”表示。
3.3.2棋盘中下棋的顺序表示
棋局中下棋的顺序也很重要,应该是黑白双方交替下棋。
本程序用t来判断黑白双方下棋顺序,t为“0”时由白方下棋,t为“1”时由黑方下棋,由于五子棋规则中黑棋先手,所以初始值t=1,即玩家执黑先手。每次落棋后,都应改变 t 的值,t 在整个对弈过程中都只能为1或者为0,即在任意时刻,都有一方可以落棋,也只能有一方落棋。
3.3.3具体算法
本系统中较复杂的部分是人机对战部分。下面将简单分析人机对战,双人对战则省略。电脑要选择有利于它的最佳下法,就要能判断哪种形势对它最有利。但往往对一个形势的判断是很难做到准确的,特别是一盘棋刚开始的时候,棋盘的形势不明朗,即使是专家也不能做出准确的判断。为了判断哪种下法最有利,我们往往需要向后面计算几步,看看在走了几步棋之后,局面的形势如何。这被称为“多算胜”,也就是说,谁看得越深远,谁就可以获胜。这种思维方式被用到了计算机上。向后面计算的步数越多,系统开销就越大,本系统只向后计算一步,根据威胁的优先级来选择落棋的最佳点。
轮到电脑下棋时,电脑先向棋盘搜索合法的落棋点,即棋盘的空白点。然后再利用下面的算法先择最佳落棋点。在每个空白点,都有四个方向需要考虑,即—、|、﹨、∕四个方向。以下就用○表示电脑所执的黑棋,用□表示玩家所执的白棋,用×表示棋盘的空白点。在设计的时候,尽可能把所有情况全面考虑,设置为搜索一个最佳落棋点位置的时候,需要保证左右展开后碰壁,之间的空间距离至少要有六格(而不是五子),否则就是死子。
人机对战算法流程是:顺序向下搜索,每次有符合要求的点时,视为最佳落棋点,并在该点落棋,同时将t赋值为1,退出搜索并判断是否有一方获胜,然后等待玩家落棋,再重复这一过程,直到有一方获胜。如图。
5
开始搜索棋盘 是 该点无子 否 搜 索 下 一 点 找出优先级最高的点落子 分出胜负 否 P+=1 是 结束搜索 图 人机对战算法流程图
(1),电脑搜索棋盘里白棋是否有一步获胜的棋,即在同一条线路上有连续五个位置上,有四颗为白棋,另外一颗为空,这时就不用考虑玩家的棋局,直接就可以获胜。能直接获胜的棋型有×○○○○×、□○○○○×,还包括通过四三来形成的活四,包括有○○×○○、○○○×○、○×○○○。
(2),电脑搜索棋盘里黑棋是否有一步获胜的棋,这时就应该让玩家的“活四”变“死四”,这是白棋威胁级别最高的,应立即做出反应。有直接威胁的棋型有□×□□□、×□□□□×、□□□×□、×□□□□×。对于×□□□□×这种棋型,其实玩家已经获胜。
(3),电脑搜索棋盘里白棋是否有可形成活四的棋型,进一步冲四,这时就应该主动进攻,这种棋型包括×○○○××、×○○×○×、×○×○○×。这样的棋只需两步方可获胜,威胁级别仅次于上面两种。
(4),电脑搜索棋盘里黑棋是否有可形成活四的棋型,若有,就有阻止冲四,让玩家的“活三”变死三,这时就体现了电脑的防守策略,这种棋型包括:××□□□×、×□×□□×、×□□×□×。其中××□□□×在封堵后还具有威胁性,所以在电脑没有进攻机会时,也应该考虑这样的棋型的威胁性,因为可以利用这种棋型来造四三来获胜。
(5),电脑搜索棋盘里白棋是否有可形成活三的棋型,这是获胜的过渡棋,在整个棋局中非常重要,这样的棋型越多,白棋造活三的机会就越多,是获胜的关键。这种棋型
6
包括:××○○××、××○×○×,由于需要三步获胜,所以优先级比较低。
表1是获胜情况分析表,优先级是按所需步数和落棋的顺序来决定的,在获胜所需步数相同的情况下,电脑所执的白棋优先级高于黑棋。
表1 获胜情况分析表
棋盘上的情况:
电脑已有任意组活四或已有任意组死四 玩家已有任意组活四或已有任意组死四 电脑已有任意组活三或已有多于一组的死三
玩家已有一组死三和任意组的活二 玩家已有任意组活三或已有多于一组的死三
玩家已有一组死三和任意组的活二
获胜所需步数
一 一 二 三 三 三
优先级 1 2 3 4 5 6
4 系统流程
五子棋的规则如下:(1)棋盘:采用15×15的棋盘。(2)下法玩家一执黑先手,电脑或玩家二执白后手,轮流在棋盘上选择一个无子的交叉点落子。无子的交叉点又被称为空点。(3)输赢判断:黑、白双方有一方的5颗棋子在横、竖或斜方向上连接成一线即为该方赢。(4)对于五子棋可分为禁手和无禁手两类,本游戏采用三三禁手。可用15×15的二维数表示棋盘内各点状态 (空、白子、黑子) ;
五子棋游戏规则简单,在每次玩家或电脑落棋后,都要去判断是否游戏是否分出胜负,如没有,另一方才能继续下棋。一局游戏结束后,可以选择再来一盘,这时将棋盘数据清空,又开始新的棋局。系统流程如图2所示。
7
开始游戏 玩家1下棋 有一方获胜 否 玩家2下棋 否 有一方获胜 是 本局结束 再来一盘 是 清空棋盘 否 游戏结束 图5-2 系统流程图
5 系统功能实现
8
5.1 窗口设计
根据 Windows API 函数来编写应用程序的顺序结构:调用 WinMain 函数开始执行→定义窗口类→初始化窗口类→窗口的实例化→通过消息循环获取消息并将消息发送给消息处理函数做出相应的操作。
我们首先应该创建一个窗口,生成一个窗口主要有两步:定义窗口类和初始化窗口类。 首先用 InitWindowsClass 来定义一个窗口类,窗口类事实上是 struct 结构体,内部有10个分量,他们是用来于初始化窗口类对象而用的。根据函数里声明的各个参数来执行,它在里面定义了窗口类对象、声明了窗口的类对象名称、应用程序实例句柄、消息处理函数名、光标样式和窗口背景等,其它的都设置为初始值。
函数关键语句:BOOL InitWindowsClass(HINSTANCE hInstance)
{ WndClass.hbrBackground=(HBRUSH)(CreateSolidBrush(RGB(240,240,240))); WndClass.hCursor=LoadCursor(NULL,IDC_ARROW); WndClass.hInstance=hInstance; WndClass.lpfnWndProc=WndProc; WndClass.lpszClassName=\; return RegisterClass(&WndClass);}
然后用 InitWindows 函数来初始化窗口类,在窗口类对象的初始化过程中,我们定义了窗口的一些简单一般特征,比如背景颜色呀,光标等等。但是在利用 CreateWindow 创建窗口的时候可以设置更多的细节,比如窗口标题这些。
函数主要参数:
hWnd=CreateWindow(\, \五子棋游戏\,
WS_OVERLAPPEDWINDOW, 0,0, 1024,768, hInstance);
其中,定义窗口类对象名称为\,窗口标题为\五子棋游戏\,窗口风格为WS_OVERLAPPEDWINDOW,说明此窗口是一个层叠式窗口,含有边框、标题栏、系统菜单、最大最小化按钮的窗口。
5.2 棋盘设计
程序的实现上,首先完成界面的设计,在界面的设计上,使用了二维数组的棋盘格式,考虑到五子棋的落子后,是不会再次移动的,所以采用划直线的方法模拟一个棋盘。棋盘大小为560×560,起始坐标为(200,100),每个格子大小为(40,40)。
首先用 GetStockObject 函数创建一个画笔和画刷,用 SelectObject 选择当前使用的画笔和画刷,画笔的作用是画棋盘的边框及格子,画刷的作用是填充棋盘的背景色,先取画笔后我们才能用它来画棋盘。为了增加棋盘的美观,画刷颜色选取灰色,与窗口的银白
9