第6讲 棋类游戏-井字棋游戏人机对弈
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
《算法分析与设计》 算法分析与设计》
第6讲棋类游戏-井字棋游戏人机对弈
知识点
一、井字棋游戏 人机对弈- 二、井字棋人机对弈-程序说明 人机对弈 三、程序界面采用的技术和方法 界面采用的技术和方法 3.1 棋盘的表示 游戏状态的表征 棋盘的表示和游戏状态的表征 3.2 程序中用到的资源 资源 3.3 游戏的保存 载入 保存和载入 保存 3.4 视图类和主窗口类的联系 3.5 悔棋 3.6 一个功能多个选项的实现 3.7 棋盘绘制 游戏状态的显示 棋盘绘制及游戏状态的显示 3.8 实现玩家下棋子 四、人机对弈的实现 人机对弈的实现 4.1 决策前的处理 4.2 特殊格局 特殊格局的处理 4.3 进攻 ຫໍສະໝຸດ Baidu.4 防守 4.5 和棋 提前判断 和棋的提前判断
//视图类自定义成员变量 //表示游戏的结果,0表示游戏没有结束 BOOL over; //1表示计算机赢,2表示玩家赢,3表示和棋 BOOL man_turn; //是否轮到玩家下棋 BOOL cmptfirst; //是否计算机先下,1表示计算机先下 int Level; //游戏级别(难或易),1为易,2为难 CBitmap m_bmRed; CBitmap m_bmBlack; HCURSOR CurBlack; //红方(计算机)棋子 //黑方(玩家)棋子 //鼠标在客户区时加载的光标
17
补充:菜单命令的映射
菜单命令可以映射到视图类 文档类 主窗口类 视图类、文档类 主窗口类。具体该 视图类 文档类、主窗口类 映射到哪个类,取决于菜单命令响应函数所需要执行的功 菜单命令响应函数所需要执行的功 能是在哪个类里实现的。 能是在哪个类里实现的
18
以下菜单命令在主窗口类 主窗口类中响应: 主窗口类 选项 | 保存游戏 保存游戏:ID_SAVE 选项 | 载入游戏 载入游戏:ID_LOAD 选项 | 悔棋 悔棋:ID_Regret 设置 | 计算机先下 计算机先下:ID_ComputerFirst 设置 | 难度(易):ID_Level 难度( 以下菜单命令在视图类中响应: 选项 | 重新开始 重新开始:ID_Start
7
3.1 棋盘的表示和游戏状态的表征
棋盘的表示: 用3×3的二维数组QP存储棋盘的状态 QP存储棋盘的状态 存储棋盘的状态,数组元素为1 1 - 表示是红方棋子, 表示对应位置上是黑方棋子,为-1表示是红方棋子 表示对应位置上是黑方棋子 为0表示没有棋子 0表示没有棋子。 用3×3的二维数组pre_qp存储上一步 pre_qp存储上一步 存储上一步(指计算机和玩 棋盘状态,以便悔棋。 家各走了一步)棋盘状态 棋盘状态
2
一、井字棋游戏
井字棋游戏,也就是三子棋游戏 井字棋游戏 三子棋游戏。 三子棋游戏 棋盘大小为3×3,在方格内下棋,对弈双方轮流下棋。 只要有一方有3颗棋子连成一条线 行、列及对角线 有一方有3 对角线),则该 有一方有 颗棋子连成一条线(行 列 对角线 方获胜,且游戏结束。 如果所有位置都已经下满棋子,且没有哪一方能赢棋,则 是和棋 和棋。 和棋
6
认识单文档应用程序中的类 单文档应用程序中的类: 单文档应用程序中的类 应用程序类(C***App 应用程序类 C***App):负责初始化应用程序、结束应 用程序。 文档类(C***Doc 文档类 C***Doc):程序中的数据(成员)一般在文档类 中定义,但也可以在其他类中定义(比如本程序就是在 视图类中定义所有的数据)。 视图类(C***View 视图类 C***View):对应于客户区(视图)。 主窗口类(CMainFrame 主窗口类 CMainFrame):对应于整个程序窗口。 CAboutDlg类 CAboutDlg类: “关于”对话框对应的类。
3
说明:三子棋游戏由于规则简单、棋局状态数较少 棋局状态数较少,因此 棋局状态数较少 常用于人工智能 计算机博弈 人工智能、计算机博弈 人工智能 计算机博弈算法演示和讲解中。
4
二、井字棋人机对弈-程序说明
本课件所设计的程序实现了井字棋人机对弈 井字棋人机对弈,具体功能为: 井字棋人机对弈 在程序界面中绘制游戏棋盘 显示游戏状态 绘制游戏棋盘,显示游戏状态 绘制游戏棋盘 显示游戏状态(对弈模式、 难度等级、哪方先下、当前轮到哪方下等等)。 玩家执黑,计算机为红方 计算机为红方。 玩家执黑 计算机为红方 可以保存游戏 载入游戏 保存游戏、载入游戏 悔棋。 保存游戏 载入游戏、可以悔棋 悔棋 可以设置谁先下 设置游戏难度 设置谁先下、设置游戏难度 设置谁先下 设置游戏难度。
5
三、程序界面采用的技术和方法
程序界面具有的特点: 程序界面 单文档应用程序(下一个案例,五子棋,也是单文档应 单文档应用程序 用程序),在视图中绘图。 能保存游戏 保存游戏,能载入游戏 载入游戏。 保存游戏 载入游戏 能悔棋 悔棋(但只能悔一步)。 悔棋 通过一个菜单命令 一个菜单命令来选择先下的两种选项 两种选项:计算机先 一个菜单命令 两种选项 下、玩家先下。 通过一个菜单命令 一个菜单命令来选择两种游戏难度 两种游戏难度:难、易。 一个菜单命令 两种游戏难度
9
自定义函数
在视图类中。
//自定义函数 //OnStart( )是保护型函数,在窗口类中不能调用,所以再定义OnStart2( )函数 void OnStart2( );//启动游戏,调用菜单命令"重新开始"响应函数OnStart( ) void ShowState( ); //显示当前游戏状态 int hard( ); //当选择"难"模式时的决策 BOOL result( ); //判断当前落子后的结果(玩家赢、计算机赢、和棋) void computerdown( ); //计算机下棋
10
3.2 程序中用到的资源
资源有:快捷键 位图 光标 快捷键、位图 光标、 快捷键 位图、光标 对话框、图标 菜单、字符串 图标、菜单 字符串、 对话框 图标 菜单 字符串 工具栏等。 工具栏
11
位图: IDB_BITMAP1:bmBlackNew.bmp位图,对应于黑棋 IDB_BITMAP1 棋子(玩家)。 IDB_BITMAP2:bmRedNew.bmp位图,对应于红棋 IDB_BITMAP2 棋子(计算机)。 菜单(非向导生成的菜单命令): ID_START:重新开始 ID_START ID_SAVE:保存游戏 ID_SAVE ID_LOAD:载入游戏 ID_LOAD ID_REGRET:悔棋 ID_REGRET ID_ComputerFirst:计算机先下 ID_ComputerFirst ID_Level:难度(易) ID_Level
14
通用对话框:MFC提供了5个通用对话框 通用对话框 5个通用对话框,可以直接 使用。
15
游戏的保存 以二进制方式将棋盘及表征游戏状态的变量 保存:以二进制方式将棋盘及表征游戏状态的变量 保存 的值存入到文件中。 的值存入到文件中
void CMainFrame::OnSave( ) //保存游戏棋盘和游戏状态 { CJingZiQiView *pView = (CJingZiQiView*)GetActiveView(); CFileDialog dlg( FALSE, "jzq", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "(*.JZQ)|*.jzq|All Files|*.*||", this ); if( dlg.DoModal()==IDOK ) dlg.GetFileName( ); else return; CString str; CStdioFile file; if( file.Open( dlg.GetFileName( ), CFile::modeCreate | CFile::modeWrite | CFile::typeText ) == 0 ) { AfxMessageBox("Unable to save file!"); return; } file.Write( pView->QP, 9*sizeof(int) ); file.Write( pView->pre_qp, 9*sizeof(int) ); file.Write( &(pView->man_turn), 1 ); file.Write( &(pView->cmptfirst), 1 ); file.Write( &(pView->Level), 1 ); file.Write( &(pView->over), 1 ); file.Close( ); }
13
2) 对于其他类中的数据 其他类中的数据,通常需要响应菜单命令(也可以 其他类中的数据 是命令按钮或其他控件),在菜单命令的响应函数中实 现将数据保存到文件或从文件中载入数据。注意: 打开文件和保存文件需要使用通用对话框 使用通用对话框。 使用通用对话框 可以以二进制方式 文本方式 二进制方式或文本方式 二进制方式 文本方式保存数据。 井字棋采用这种方式实现。 注意事项: 注意事项 对于棋类游戏,如果需要保存棋局,除了要保存当前 当前 棋盘各位置上的棋子外,还需要保存当前轮到哪方下 棋盘各位置上的棋子 当前轮到哪方下 游戏难度等数据。 棋、游戏难度 游戏难度 不管是哪种方法,在保存数据和载入数据时各数据的 各数据的 顺序一定要一致。 顺序一定要一致
//视图类自定义成员变量 //QP[i][j]为1表示该位置上是黑方(玩家)棋子, //为-1表示是红方棋子,为0表示没有棋子 int QP[3][3]; //存储棋盘状态 int pre_qp[3][3]; //存储上一步(指计算机和玩家各走了一步)棋盘状态,以便悔棋
8
其他表示游戏状态 游戏状态的成员变量。 游戏状态
16
游戏的载入 从二进制文件中读入数据到存储棋盘的 载入:从二进制文件中读入数据到存储棋盘的 载入 二维数组及表征游戏状态的变量中。 二维数组及表征游戏状态的变量中
void CMainFrame::OnLoad( ) //载入游戏棋盘和游戏状态 { CJingZiQiView *pView = (CJingZiQiView*)GetActiveView(); CFileDialog dlg( TRUE, "jzq", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "(*.JZQ)|*.jzq|All Files|*.*||", this ); if( dlg.DoModal()==IDOK ) dlg.GetFileName( ); else return; CStdioFile file; if(file.Open(dlg.GetFileName(),CFile::modeRead)==0) { AfxMessageBox("Unable to open a file!"); return; } file.Read( pView->QP, 9*sizeof(int) ); file.Read( pView->pre_qp, 9*sizeof(int) ); file.Read( &(pView->man_turn), 1 ); file.Read( &(pView->cmptfirst), 1 ); file.Read( &(pView->Level), 1 ); file.Read( &(pView->over), 1 ); file.Close( ); Invalidate( ); }
12
3.3 游戏的保存和载入
程序中数据的保存(到文件中)和载入通常有两种方法: 程序中数据的保存(到文件中)和载入 1) 程序中的数据是在文档类中 程序中的数据是在文档类中,则可以通过文档类的串 文档类的串 行化函数Serialize 行化函数Serialize很方便地实现,详见下一个案例- 五子棋游戏。注意: 在串行化函数中添加代码后,通过向导添加的打开、 通过向导添加的打开、 通过向导添加的打开 保存菜单命令就可以实现数据的保存和载入了。 保存菜单命令 另外,需要在资源中修改IDR_MAINFRAME字符 IDR_MAINFRAME字符 串,以便保存时指定扩展名、打开时只打开指定扩 展名的文件。 以二进制方式 二进制方式保存数据。 二进制方式
第6讲棋类游戏-井字棋游戏人机对弈
知识点
一、井字棋游戏 人机对弈- 二、井字棋人机对弈-程序说明 人机对弈 三、程序界面采用的技术和方法 界面采用的技术和方法 3.1 棋盘的表示 游戏状态的表征 棋盘的表示和游戏状态的表征 3.2 程序中用到的资源 资源 3.3 游戏的保存 载入 保存和载入 保存 3.4 视图类和主窗口类的联系 3.5 悔棋 3.6 一个功能多个选项的实现 3.7 棋盘绘制 游戏状态的显示 棋盘绘制及游戏状态的显示 3.8 实现玩家下棋子 四、人机对弈的实现 人机对弈的实现 4.1 决策前的处理 4.2 特殊格局 特殊格局的处理 4.3 进攻 ຫໍສະໝຸດ Baidu.4 防守 4.5 和棋 提前判断 和棋的提前判断
//视图类自定义成员变量 //表示游戏的结果,0表示游戏没有结束 BOOL over; //1表示计算机赢,2表示玩家赢,3表示和棋 BOOL man_turn; //是否轮到玩家下棋 BOOL cmptfirst; //是否计算机先下,1表示计算机先下 int Level; //游戏级别(难或易),1为易,2为难 CBitmap m_bmRed; CBitmap m_bmBlack; HCURSOR CurBlack; //红方(计算机)棋子 //黑方(玩家)棋子 //鼠标在客户区时加载的光标
17
补充:菜单命令的映射
菜单命令可以映射到视图类 文档类 主窗口类 视图类、文档类 主窗口类。具体该 视图类 文档类、主窗口类 映射到哪个类,取决于菜单命令响应函数所需要执行的功 菜单命令响应函数所需要执行的功 能是在哪个类里实现的。 能是在哪个类里实现的
18
以下菜单命令在主窗口类 主窗口类中响应: 主窗口类 选项 | 保存游戏 保存游戏:ID_SAVE 选项 | 载入游戏 载入游戏:ID_LOAD 选项 | 悔棋 悔棋:ID_Regret 设置 | 计算机先下 计算机先下:ID_ComputerFirst 设置 | 难度(易):ID_Level 难度( 以下菜单命令在视图类中响应: 选项 | 重新开始 重新开始:ID_Start
7
3.1 棋盘的表示和游戏状态的表征
棋盘的表示: 用3×3的二维数组QP存储棋盘的状态 QP存储棋盘的状态 存储棋盘的状态,数组元素为1 1 - 表示是红方棋子, 表示对应位置上是黑方棋子,为-1表示是红方棋子 表示对应位置上是黑方棋子 为0表示没有棋子 0表示没有棋子。 用3×3的二维数组pre_qp存储上一步 pre_qp存储上一步 存储上一步(指计算机和玩 棋盘状态,以便悔棋。 家各走了一步)棋盘状态 棋盘状态
2
一、井字棋游戏
井字棋游戏,也就是三子棋游戏 井字棋游戏 三子棋游戏。 三子棋游戏 棋盘大小为3×3,在方格内下棋,对弈双方轮流下棋。 只要有一方有3颗棋子连成一条线 行、列及对角线 有一方有3 对角线),则该 有一方有 颗棋子连成一条线(行 列 对角线 方获胜,且游戏结束。 如果所有位置都已经下满棋子,且没有哪一方能赢棋,则 是和棋 和棋。 和棋
6
认识单文档应用程序中的类 单文档应用程序中的类: 单文档应用程序中的类 应用程序类(C***App 应用程序类 C***App):负责初始化应用程序、结束应 用程序。 文档类(C***Doc 文档类 C***Doc):程序中的数据(成员)一般在文档类 中定义,但也可以在其他类中定义(比如本程序就是在 视图类中定义所有的数据)。 视图类(C***View 视图类 C***View):对应于客户区(视图)。 主窗口类(CMainFrame 主窗口类 CMainFrame):对应于整个程序窗口。 CAboutDlg类 CAboutDlg类: “关于”对话框对应的类。
3
说明:三子棋游戏由于规则简单、棋局状态数较少 棋局状态数较少,因此 棋局状态数较少 常用于人工智能 计算机博弈 人工智能、计算机博弈 人工智能 计算机博弈算法演示和讲解中。
4
二、井字棋人机对弈-程序说明
本课件所设计的程序实现了井字棋人机对弈 井字棋人机对弈,具体功能为: 井字棋人机对弈 在程序界面中绘制游戏棋盘 显示游戏状态 绘制游戏棋盘,显示游戏状态 绘制游戏棋盘 显示游戏状态(对弈模式、 难度等级、哪方先下、当前轮到哪方下等等)。 玩家执黑,计算机为红方 计算机为红方。 玩家执黑 计算机为红方 可以保存游戏 载入游戏 保存游戏、载入游戏 悔棋。 保存游戏 载入游戏、可以悔棋 悔棋 可以设置谁先下 设置游戏难度 设置谁先下、设置游戏难度 设置谁先下 设置游戏难度。
5
三、程序界面采用的技术和方法
程序界面具有的特点: 程序界面 单文档应用程序(下一个案例,五子棋,也是单文档应 单文档应用程序 用程序),在视图中绘图。 能保存游戏 保存游戏,能载入游戏 载入游戏。 保存游戏 载入游戏 能悔棋 悔棋(但只能悔一步)。 悔棋 通过一个菜单命令 一个菜单命令来选择先下的两种选项 两种选项:计算机先 一个菜单命令 两种选项 下、玩家先下。 通过一个菜单命令 一个菜单命令来选择两种游戏难度 两种游戏难度:难、易。 一个菜单命令 两种游戏难度
9
自定义函数
在视图类中。
//自定义函数 //OnStart( )是保护型函数,在窗口类中不能调用,所以再定义OnStart2( )函数 void OnStart2( );//启动游戏,调用菜单命令"重新开始"响应函数OnStart( ) void ShowState( ); //显示当前游戏状态 int hard( ); //当选择"难"模式时的决策 BOOL result( ); //判断当前落子后的结果(玩家赢、计算机赢、和棋) void computerdown( ); //计算机下棋
10
3.2 程序中用到的资源
资源有:快捷键 位图 光标 快捷键、位图 光标、 快捷键 位图、光标 对话框、图标 菜单、字符串 图标、菜单 字符串、 对话框 图标 菜单 字符串 工具栏等。 工具栏
11
位图: IDB_BITMAP1:bmBlackNew.bmp位图,对应于黑棋 IDB_BITMAP1 棋子(玩家)。 IDB_BITMAP2:bmRedNew.bmp位图,对应于红棋 IDB_BITMAP2 棋子(计算机)。 菜单(非向导生成的菜单命令): ID_START:重新开始 ID_START ID_SAVE:保存游戏 ID_SAVE ID_LOAD:载入游戏 ID_LOAD ID_REGRET:悔棋 ID_REGRET ID_ComputerFirst:计算机先下 ID_ComputerFirst ID_Level:难度(易) ID_Level
14
通用对话框:MFC提供了5个通用对话框 通用对话框 5个通用对话框,可以直接 使用。
15
游戏的保存 以二进制方式将棋盘及表征游戏状态的变量 保存:以二进制方式将棋盘及表征游戏状态的变量 保存 的值存入到文件中。 的值存入到文件中
void CMainFrame::OnSave( ) //保存游戏棋盘和游戏状态 { CJingZiQiView *pView = (CJingZiQiView*)GetActiveView(); CFileDialog dlg( FALSE, "jzq", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "(*.JZQ)|*.jzq|All Files|*.*||", this ); if( dlg.DoModal()==IDOK ) dlg.GetFileName( ); else return; CString str; CStdioFile file; if( file.Open( dlg.GetFileName( ), CFile::modeCreate | CFile::modeWrite | CFile::typeText ) == 0 ) { AfxMessageBox("Unable to save file!"); return; } file.Write( pView->QP, 9*sizeof(int) ); file.Write( pView->pre_qp, 9*sizeof(int) ); file.Write( &(pView->man_turn), 1 ); file.Write( &(pView->cmptfirst), 1 ); file.Write( &(pView->Level), 1 ); file.Write( &(pView->over), 1 ); file.Close( ); }
13
2) 对于其他类中的数据 其他类中的数据,通常需要响应菜单命令(也可以 其他类中的数据 是命令按钮或其他控件),在菜单命令的响应函数中实 现将数据保存到文件或从文件中载入数据。注意: 打开文件和保存文件需要使用通用对话框 使用通用对话框。 使用通用对话框 可以以二进制方式 文本方式 二进制方式或文本方式 二进制方式 文本方式保存数据。 井字棋采用这种方式实现。 注意事项: 注意事项 对于棋类游戏,如果需要保存棋局,除了要保存当前 当前 棋盘各位置上的棋子外,还需要保存当前轮到哪方下 棋盘各位置上的棋子 当前轮到哪方下 游戏难度等数据。 棋、游戏难度 游戏难度 不管是哪种方法,在保存数据和载入数据时各数据的 各数据的 顺序一定要一致。 顺序一定要一致
//视图类自定义成员变量 //QP[i][j]为1表示该位置上是黑方(玩家)棋子, //为-1表示是红方棋子,为0表示没有棋子 int QP[3][3]; //存储棋盘状态 int pre_qp[3][3]; //存储上一步(指计算机和玩家各走了一步)棋盘状态,以便悔棋
8
其他表示游戏状态 游戏状态的成员变量。 游戏状态
16
游戏的载入 从二进制文件中读入数据到存储棋盘的 载入:从二进制文件中读入数据到存储棋盘的 载入 二维数组及表征游戏状态的变量中。 二维数组及表征游戏状态的变量中
void CMainFrame::OnLoad( ) //载入游戏棋盘和游戏状态 { CJingZiQiView *pView = (CJingZiQiView*)GetActiveView(); CFileDialog dlg( TRUE, "jzq", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "(*.JZQ)|*.jzq|All Files|*.*||", this ); if( dlg.DoModal()==IDOK ) dlg.GetFileName( ); else return; CStdioFile file; if(file.Open(dlg.GetFileName(),CFile::modeRead)==0) { AfxMessageBox("Unable to open a file!"); return; } file.Read( pView->QP, 9*sizeof(int) ); file.Read( pView->pre_qp, 9*sizeof(int) ); file.Read( &(pView->man_turn), 1 ); file.Read( &(pView->cmptfirst), 1 ); file.Read( &(pView->Level), 1 ); file.Read( &(pView->over), 1 ); file.Close( ); Invalidate( ); }
12
3.3 游戏的保存和载入
程序中数据的保存(到文件中)和载入通常有两种方法: 程序中数据的保存(到文件中)和载入 1) 程序中的数据是在文档类中 程序中的数据是在文档类中,则可以通过文档类的串 文档类的串 行化函数Serialize 行化函数Serialize很方便地实现,详见下一个案例- 五子棋游戏。注意: 在串行化函数中添加代码后,通过向导添加的打开、 通过向导添加的打开、 通过向导添加的打开 保存菜单命令就可以实现数据的保存和载入了。 保存菜单命令 另外,需要在资源中修改IDR_MAINFRAME字符 IDR_MAINFRAME字符 串,以便保存时指定扩展名、打开时只打开指定扩 展名的文件。 以二进制方式 二进制方式保存数据。 二进制方式