目 录
摘要 1
ABSTRACT 2
1绪论 3
1.1 课题研究背景 3
1.2 国内外研究现状 5
1.3 主要研究内容及方法 6
1.4 论文组织结构 6
2 相关研究工作技术概述 7
2.1 人工智能 7
2.2 博弈论 9
2.2.1 基本定义 9
2.2.2 应用与影响 10
2.3 棋类游戏介绍 11
3 算法设计 12
3.1 五子棋相关技术介绍 12
3.2 棋类游戏基础算法概述 13
3.2.1 盲目搜索算法 13
3.2.2 极大极小算法 14
3.2.3 ALPHA-BETA剪枝算法 16
3.3 五子棋算法设计 18
4 系统设计与实现 25
4.1 总体程序框架 25
4.2 程序界面设计 28
4.2.1 计算机图形学概述 28
4.2.2 界面设计与人机交互 31
4.3 读档功能 36
4.4 悔棋功能 37
4.5 测试 38
5 总结和未来展望 39
参考文献 40
在搜索方面,在极大与极小值计算的基础上经过改进而得到的Alpha-Beta剪枝计算,具有非常广阔的应用。不过,由于使用Alpha-Beta剪枝计算的搜索深度进一步提升,此计算法所耗费的时间和硬件资源也呈指数式上升,这样造成了检索节点较多且检索时限较长的弊端。这些缺陷,在普通计算机中会影响搜寻深度的提高,会影响搜寻效果和博弈水平.
在估值方面,五子棋主要采用基于模型的估值方式。这种估值方式优点在于简单直接,拥有较高的准确性,劣势在于对于棋型的划分与其价值的设定通常根据经验获得且需要通过手动操作进行调整,存在着不稳定性。
1.3主要研究内容及方法
本课题主要的研究内容是通过C++开发一个能够实现计算机与玩家对弈的五子棋游戏程序,并在后期通过玩家对其进行测试,最终对五子棋游戏软件对弈算法的性能进行评估。具体如下:
#undef UNICODE
#include "stdafx.h"
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <string.h>
#define W 640
#define H 640
#define WIDTH 25
#define NUM 15
//两边无棋子系列
#define NONE1 0
#define NONE2 10
#define NONE3 3000
#define NONE4 10000//必胜
#define NONE5 100000//必胜
//两边都有棋子系列
#define BOTH1 0
#define BOTH2 3
#define BOTH3 100
#define BOTH4 500
#define BOTH5 100000
#define SIDE1 0
#define SIDE2 5
#define SIDE3 500
#define SIDE4 1000//胜利
#define SIDE5 100000
struct {
int type;
int success;
}mSuccess;//成功信息
enum {
GAME_MENU,
GAME_RUN
}g_GameDraw;//界面绘制状态
enum {
GAME_MENU1,
GAME_RUN1,
GAME_SUCCESS
}g_GameState;//逻辑处理
struct
{
int x;
int y;
int w;
int h;
bool draw;
}rect[3];
int round = 1;//初始化回合数
int mx, my;
int IsMousePaint = true;
int Chess[NUM][NUM] = { 0 };
int person = 1;
int Success;
int Back[NUM][NUM] = { 0 };
void AIPlay(int* x, int* y);//电脑下棋
bool Judge(int x, int y);//判断是否胜利
void draw_Chess(int, int, int);//画棋子
void drawAllChess(int x, int y);//绘制所有棋子
void drawBoard(int x, int y);//画棋盘
int GetType(int Num, int type);//获取类型分数
int GetScore(int x, int y, int type);//
void OnPaint();
int WndProc(MOUSEMSG);
//void playChess(int,int,int);//函数声明
char* str[] = { "新游戏", "读档开始", "退出" };//初始界面指示
int main(int argc, char* argv[])
{
initgraph(640, 480);//初始界面
MOUSEMSG m; // 定义鼠标消息
g_GameDraw = GAME_MENU;
g_GameState = GAME_MENU1;
rect[0].draw = false;
rect[1].draw = false;
rect[2].draw = false;//键变色
while (true)
{
// 获取一条鼠标消息
while (MouseHit())
{
m = GetMouseMsg();
WndProc(m);
}
}
// 关闭图形窗口
closegraph();
return 0;
}
//消息处理程序
int WndProc(MOUSEMSG m)
{
HWND hWnd = GetHWnd();
switch (g_GameState)//逻辑处理
{
case GAME_MENU1:
switch (m.uMsg)
{
case WM_MOUSEMOVE:
//处理鼠标移动
if (m.x >= rect[0].x && m.x <= rect[0].w && m.y >= rect[0].y && m.y <= rect[0].h)
{
//响应
rect[0].draw = true;
}
else
rect[0].draw = false;
if (m.x >= rect[1].x && m.x <= rect[1].w && m.y >= rect[1].y && m.y <= rect[1].h)
{
//响应
rect[1].draw = true;
}
else
rect[1].draw = false;
if (m.x >= rect[2].x && m.x <= rect[2].w && m.y >= rect[2].y && m.y <= rect[2].h)
{
//响应
rect[2].draw = true;
}
else
rect[2].draw = false;
break;
case WM_LBUTTONUP:
//鼠标按下弹起
if (m.x >= rect[0].x && m.x <= rect[0].w && m.y >= rect[0].y && m.y <= rect[0].h)
{
//响应
g_GameDraw = GAME_RUN;//进入游戏界面的绘制
g_GameState = GAME_RUN1;//进入游戏界面的逻辑处理
rect[0].draw = false;
rect[1].draw = false;
rect[2].draw = false;//键变色
}
else if (m.x >= rect[1].x && m.x <= rect[1].w && m.y >= rect[1].y && m.y <= rect[1].h)
{
rect[0].draw = false;
rect[1].draw = false;
rect[2].draw = false;//键变色
FILE* fp;
fp = fopen("recode.txt", "r");
if (fp == NULL)
{
MessageBox(hWnd, "存档文件不存在", "提示", MB_OK);
}
int i, j;
for (i = 0;i < NUM;i++)
for (j = 0;j < NUM;j++)
fscanf(fp, "%d\t", &Chess[i][j]);
fscanf(fp, " %d", &round);
fclose(fp);
g_GameDraw = GAME_RUN;
g_GameState = GAME_RUN1;
}
else if (m.x >= rect[2].x && m.x <= rect[2].w && m.y >= rect[2].y && m.y <= rect[2].h)
{
closegraph();
exit(0);//退出
}
break;//只处理鼠标移动信息和鼠标按下弹起信息
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
//
break;
default:
break;
}
break;
case GAME_RUN1:
int xId, yId;
if (person == 2)
{
//电脑
AIPlay(&xId, &yId);
Chess[xId][yId] = 2;
if (Judge(xId, yId))//如果成功
{
g_GameState = GAME_SUCCESS;
}
person = 1;
break;