中国象棋对弈程序

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

中国象棋对弈程序

【摘要】:人机博弈是人工智能研究的经典课题之一。凭借设计优良的算法和计算机的快速运算能力,计算机可以在人机对弈中表现出相当高的“智能”。通常,一款象棋程序的实现可以被分为下棋引擎(人工智能)和外壳(界面及程序辅助)两大部分。本文将介绍如何实现一款中国象棋对弈程序。

【关键词】:中国象棋;人工智能;博弈树;Alpha-Beta搜索;历史启发;界面;多线程;计时器;列表框;MFC。

[Abstract]: Man-machine Game is a classic topic in Artificial Intelligence. Relying on fine-designed algorithms and the fast operation ability, computers can display high "intelligence" in playing chess. Usually, the realization of a chess program can be decomposed into two major parts: the Chess Engine (Artificial Intelligence) and the Shell (User Interface & Program Assist). This paper will introduce how to realize a Chinese Chess program.

[Key words]: Chinese Chess; Artificial Intelligence (AI); Game Tree; Alpha-Beta Search; History Heuristic; User Interface; Multithreaded; Timer; List Box; MFC.

一、前言

我们的目标是实现一款有着一定下棋水平且交互友好的中国象棋人机对弈程序。

该程序功能包括:

*人机对弈;

*盲棋模式;

(注:此功能为创新功能)

*搜索深度设定;

(电脑棋力选择)

*棋子、棋盘样式选择;

*悔棋、还原;

*着法名称显示;

*下棋双方计时;

整个程序的实现可分为两大部分:

一、人工智能部分(计算机下棋引擎)

该部分实现了如何让计算机下中国象棋,其中涉及人机博弈的基本理论及思想,是该程序的核心部分,同时也是本项目研究的重点所在。

二、界面及程序辅助部分

光有下棋引擎尚不能满足人机交互的基本要求,因此我们还需要一个框架(界面)来作为引擎的载体,同时提供一些诸如悔棋,计时之类的附属功能(程序辅助)来为程序增色添彩。

下面分别介绍各部分实现。由于界面及程序辅助部分涉及内容宽泛而又繁琐,因而本文只介绍其中重点部分以及我们在开发过程中曾经遇到过困难的地方。

二、人工智能部分(计算机下棋引擎)

1、概述

程序的基本框架:

从程序的结构上讲,大体上可以将引擎部分划分为四大块:

棋局表示;

着法生成;

搜索算法;

局面评估。

程序的大概的思想是:

首先使用一个数据结构来描述棋局信息,对某一特定的棋局信息由着法生成器生成当前下棋方所有合法的着法并依次存入着法队列。然后通过搜索算法来逐一读取着法并调用局面评估函数对该着法所产生的后继局面进行评估打分,从中选出一个最有可能导致走棋方取胜的着法。在搜索的过程中还可以采用一些辅助手段来提高搜索的效率。其过程如下图所示:

下面将分别介绍各个部分。

2、棋局表示

计算机下棋的前提是要让计算机读懂象棋。所谓读懂,即计算机应该能够清楚地了解到棋盘上的局面(棋盘上棋子的分布情况)以及下棋方所走的每一种着法。因而首先我们需要有一套数据结构来表示棋盘上的局面以及着法。

对于棋盘局面的表示我们采用了最传统的同时也是最为简单的“棋盘数组”。即用一个9*10的数组来存储棋盘上的信息,数组的每个元素存储棋盘上相应位置是何种棋子。这种表

示方法简单易行(缺点是效率不是很高)。按此方法棋盘的初始情形如下所示:BYTE CChessBoard[9][10] = {

R, 0, 0, P, 0, 0, p, 0, 0, r,

H, 0, C, 0, 0, 0, 0, c, 0, h,

E, 0, 0, P, 0, 0, p, 0, 0, e,

A, 0, 0, 0, 0, 0, 0, 0, 0, a,

K, 0, 0, P, 0, 0, p, 0, 0, k,

A, 0, 0, 0, 0, 0, 0, 0, 0, a,

E, 0, 0, P, 0, 0, p, 0, 0, e,

H, 0, C, 0, 0, 0, 0, c, 0, h,

R, 0, 0, P, 0, 0, p, 0, 0, r

};

其中“0”表示无棋子,大写字母表示红方棋子,小写

字母表示黑方棋子(所有这些大小写字母都是用宏定义的整

数)。具体如下:

“R”表示红车;“H”表示红马;“E”表示红相;“A”

表示红仕;“K”表示红帅;“C”表示红炮;“P”表示红兵。

“r”表示黑车;“h”表示黑马;“e”表示黑象;“a”

表示黑士;“k”表示黑将;“c”表示黑炮;“p”表示黑卒。

此外这个数组也表明了我们对棋盘进行了如右图所示

的编号,并约定红方棋子总处于棋盘的下方。

对于着法的表示,我们直接借用棋盘数组的下标来记录着法的起点和目标点。至于是什么棋子在走,以及是否吃子、吃的是什么子,我们在着法结构中并不记录。这些信息由外部读取棋盘上起点、终点的数据获得。着法结构定义如下,其中还包含了对着法的历史得分的记录项,以供后面要讲到的“历史启发”所用。

typedef struct _cchessmove{

POINT ptFrom; // 起点

POINT ptTo; // 目标点

int nScore; // 该走法的历史得分

} CCHESSMOVE ; // 走法结构

有了对棋盘局面和着法的表示之后,程序才能够完成以下操作:

1、生成所有合法着法;

2、执行着法、撤销着法;

3、针对某一局面进行评估。

因而,棋局表示好比是整个程序(计算机下棋引擎部分)的地基,之后所有的操作都将建立在其基础上。

3、着法生成

我们的程序需要让计算机在轮到它走子的时候能够执行一步它认为对它最有利的着法,那前提就是它要有诸多(也可能是唯一)可供选择的着法,提供所有候选着法的“清单”就是我们的着法生成器所要完成的。之后用搜索函数来搜索“清单”,并用局面评估函数来逐一打分,

相关文档
最新文档