井字棋课程设计报告
数据结构课程设计报告---井字棋游戏

课程设计报告课程设计名称:数据结构课程设计题目:井字棋游戏年级:专业:姓名:指导老师:完成时间:目录1. 课程设计任务 (3)2. 系统设计 (3)2.1设计目标 (3)2.2 模块划分 (3)2.3 设计思想 (3)3. 算法描述 (4)4. 测试结果 (12)5. 分析与探讨 (13)6、总结 (13)7. 参考文献 (13)附录1 课程设计人员任务安排 (14)附录2 考核评定 (15)附录3 程序源代码 (16)1、课程设计任务设计井字棋游戏,可以实现人机互动下棋,棋盘界面友好,操作方便,系统自动判别胜利失败或平局,游戏结束,返回初始界面。
2、系统设计1.设计目标:设计出棋盘界面,实现人机互动下棋,显示对局结果。
设计思想:首先玩家下棋,打印棋盘,来显示玩家下棋的位置然后将玩家下完的棋盘数组传给咱们的胜负判断函数进行判断(电脑下棋同理),ret变量接收返回来的值,如果是字符 C 则游戏继续,如果其他字符跳出循环,来进行相应的判断,判断玩家的胜负或者平局。
2.模块划分:开始游戏棋盘初始化人机博弈胜负判断3.设计思想开始界面玩家可以选择开始游戏或者退出游戏,如果选择进行游戏则开始棋盘初始化,棋盘打印函数输出一个空白棋盘,棋子的摆放利用二维数组,机器人的落子由srand函数和rand函数来输出随机数,利用while的循环函数来判断落子位置是否已经被棋子占据。
胜负判断设置iswin函数以及isfull函数,,使用了两个 for 循环,五个 if 判断语句,井字棋的输赢是看每一行是否有三个相同的棋子或者两条对角线线上是否有三个相同的棋子。
3、算法描述1.函数调用模块:game函数是核心,里面概括了棋盘打印,下棋方法,电脑下棋方法,以及胜负判断条件。
void game(){char ret = 0;//创建棋盘char board[ROW][COL] = { 0 };//初始化棋盘Initboard(board, ROW, COL);//打印棋盘Displayboard(board, ROW, COL);while (1){//玩家下棋Playermove(board, ROW, COL);Displayboard(board, ROW, COL);//判断玩家赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}//电脑下棋Computermove(board, ROW, COL);Displayboard(board, ROW, COL);//判断电脑赢ret = IsWin(board, ROW, COL);if (ret != 'C')break;}}if (ret == '*'){printf("你赢啦!\n");}else if (ret == '#'){printf("你输啦!真笨\n");}else{printf("平局\n");}}void menu(){printf("********************************\n");printf("********* 1.开始游戏 *********\n");printf("********* 0.退出游戏 *********\n");printf("********************************\n"); }void test(){int input = 0;srand((unsigned int)time(NULL));do{menu();printf("请选择: ");scanf("%d",&input);switch(input)case 1:printf("井字棋开始了!\n");game();break;case 0:printf("已退出游戏!\n");break;default:printf("选择错误!请重新选择!\n");break;}} while (input);}int main(){test();return 0;}2.棋盘初始化:使用二维数组的数据结构来建立一个棋盘void Initboard(char board[ROW][COL], int row, int col) //初始化棋盘{for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){board[i][j] = ' ';}}}3.棋盘打印函数:构建一个简单的3*3棋盘轮廓void Displayboard(char board[ROW][COL], int row, int col) //打印棋盘{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){printf(" %c ", board[i][j]);if (j < col - 1)printf("|");}printf("\n");if (i < col - 1){for (j = 0; j < col; j++){printf("---");if (j < col - 1){printf("|");}}}printf("\n");}4.游戏进行中:(玩家下棋)void Playermove(char board[ROW][COL], int row, int col) //玩家下棋{int x = 0;int y = 0;printf("请玩家下子!\n");while (1){printf("请输入坐标:");//判断x,y坐标的合法性scanf("%d%d",&x,&y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (board[x - 1][y - 1] == ' '){board[x - 1][y - 1] = '*';break;}else{printf("该坐标已被占用");}}else{printf("输入坐标非法,请重新输入!\n");}}}5.游戏进行中:(电脑下棋rand函数提供随机值)void Computermove(char board[ROW][COL], int row, int col) {int x = 0;int y = 0;printf("轮到电脑走!\n");while (1){x = rand() % row;y = rand() % col;if (board[x][y] == ' '){board[x][y] = '#';break;}}}6.对局结果判断函数://返回1满了//返回2没满int IsFull(char board[ROW][COL], int row, int col){int i = 0;int j = 0;for (i = 0; i < row; i++){for (j = 0; j < col; j++){if (board[i][j] == ' '){return 0;//没满}}}return 1;//满了}char IsWin(char board[ROW][COL], int row, int col){int i = 0;for (i = 0; i < row; i++){//判断一行上是否有三个相同的if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' '){return board[i][1];}}for (i = 0; i < col; i++){//判断一列上是否有三个相同的if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[0][i] != ' '){return board[1][i];}}//两条对角线if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' '){return board[1][1];}if (board[2][0] == board[1][1] && board[1][1] == board[0][2] && board[1][1] != ' '){return board[1][1];}if (1 == IsFull(board, ROW, COL)){return 'Q';}return 'C';}7.接受返回值并输出结果:while (1){//玩家下棋Playermove(board, ROW, COL);Displayboard(board, ROW, COL);//判断玩家赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}//电脑下棋Computermove(board, ROW, COL);Displayboard(board, ROW, COL);//判断电脑赢ret = IsWin(board, ROW, COL);if (ret != 'C'){break;}}if (ret == '*'){printf("You Win!\n");}else if (ret == '#'){printf("You Lose!\n");}else{printf("No One Win!\n");}}8.头文件参考网上教程设置宏#include <stdio.h>#include <stdlib.h>#include <time.h>#define ROW 3#define COL 3void Initboard(char board[ROW][COL], int row, int col); void Displayboard(char board[ROW][COL], int row, int col);void Playermove(char board[ROW][COL], int row, int col); void Computermove(char board[ROW][COL],int row, int col); //1.玩家赢 "*"//2.电脑赢 "#"//3.平局了 "Q"//4.继续 "C"char IsWin(char board[ROW][COL], int row, int col);4、测试结果测试环境:vs2010测试用例:玩家输入坐标:(2,1)(2,2)(1,1)(1,2)测试结果:玩家失败电脑获胜5、分析与探讨在人机博弈的过程中,电脑只能随机确定棋子落位,无法自主将棋子放在最优位置,若要实现电脑的落子智能化,还需对于电脑下棋的过程中增添进一步的判断。
幼儿园小班井字棋游戏教案及反思

幼儿园小班井字棋游戏教案及反思教案标题:幼儿园小班井字棋游戏教案及反思教学目标:1. 帮助幼儿了解井字棋游戏规则,并能正确操作棋子。
2. 培养幼儿的逻辑思维能力和决策能力。
3. 提升幼儿的合作与竞争意识。
教学准备:1. 井字棋游戏棋盘和棋子。
2. 幼儿园小班学生的座位布置成游戏桌。
3. 图片或视频展示井字棋游戏规则。
4. 准备奖品作为激励。
5. 记录幼儿游戏过程的观察表格。
教学步骤:引入活动:1. 展示井字棋游戏图片或视频,引起幼儿的兴趣。
2. 向幼儿介绍井字棋游戏的规则和目标。
游戏规则讲解:1. 将幼儿分成小组,每组两人。
2. 解释游戏棋盘的规则和棋子的使用方法。
3. 演示一局井字棋游戏,让幼儿理解游戏过程。
实践操作:1. 让每个小组选择一个代表开始游戏。
2. 每位幼儿轮流在棋盘上放置自己的棋子,直到有一方完成三个连成一线。
3. 引导幼儿逐渐独立思考和决策。
游戏总结:1. 让每个小组分享他们的游戏经验和策略。
2. 引导幼儿思考游戏中的胜利和失败,以及如何从中学习。
反思:1. 观察幼儿在游戏中的表现,记录他们的参与度、合作和竞争意识等方面的观察结果。
2. 根据观察结果,分析幼儿的优势和改进空间,并提供相应的指导和建议。
拓展活动:1. 鼓励幼儿设计自己的井字棋游戏规则。
2. 组织井字棋比赛,让幼儿展示他们的技巧和策略。
教案反思:这个教案在引入活动部分通过展示图片或视频,成功引起了幼儿的兴趣。
游戏规则讲解部分的演示也有助于幼儿理解游戏过程。
在实践操作中,幼儿有机会独立思考和决策,培养了他们的逻辑思维能力。
游戏总结部分的分享和思考有助于幼儿从游戏中学习并提升自己。
在反思部分,观察和记录幼儿的表现是很重要的,可以帮助教师了解幼儿的发展情况并提供个性化的指导。
总体来说,这个教案在培养幼儿的逻辑思维能力、决策能力和合作与竞争意识方面有很好的效果。
通过拓展活动的设计,还可以进一步激发幼儿的创造力和想象力。
井字棋实验报告

井字棋实验报告篇一:井字棋实验报告课程:班别小组成员人工智能原理及其应用12商本学号及姓名指导老师实验02井字棋1、总体要求:1.1总体功能要求:利用不同的方法,实现人机对战过程中呈现出不同程度的智能特征:(1)利用极大极小算法、α-β剪枝来提高算法的效率。
(2)使用高级语言,编写一个智能井字棋游戏。
(3)结合极大极小算法的使用方法和α-β剪枝,让机器与人对弈时不但有智能的特征,而且计算的效率也比较高。
1.2.开发平台要求:开发者开发的软件必须能够在不同系统的电脑上正常运行,因此开发平台为:开发环境:JDK1.6开发工具和技术体系:为了此游戏能够很好的在不同系统中运行,因选择javaee进行开发,利用eclipse1.3项目管理要求:(1)项目程序编写过程中要适当的写一些注释,以便下次作业时能够快速的上手和以后的修改:(2)项目程序要保存在一个固定的工作区间;(3)确保代码不要太多冗余2、需求分析:2.1软件的用户需求:井字棋游戏的用户希望游戏除了有一般的功能之外,还可以通过极大极小算法、α-β剪枝等方法是的井字棋游戏能够拥有智能特征,并是的电脑在人机对弈的过程中因玩家的难度选择而体现不同程度的智能状况。
2.2软件的功能需求:本游戏需要实现功能有:(1)游戏的重新设置(2)游戏统计(如:人赢的次数、电脑赢的次数等)(3)游戏的退出(4)不同智能程度下(脑残、懵懂、正常、智能),人机对弈(5)既可以选择难度,也可以选择谁走第一步(人or电脑) 2.3软件的性能需求:井字棋游戏需要以图形界面的形式表现出来,通过点击图标就可以进入游戏;在游戏进行时,人机对弈时电脑能够快速的反应并根据人的上一步动作作出,通过选择“脑残、懵懂、正常、智能”难度选择,电脑以不同程度的智能与人进行游戏对弈。
2.4 运行环境:能够运行java程序的环境(装有jdk 或者jre)2.5 用户界面设计:用gridlayout进行用户界面的设计把界面中分为不同的模块。
井字棋游戏课程设计总结报告文件

Xx学院
计算机信息学院《C语言课程设计(短一)》
指
导
书
年
附件二封面格式
学院
C语言课程设计总结报告
题目井字棋
指导教师
院系计算机与信息工程学院
专业计算机科学与技术
班级
学号
姓名
成绩
xx年xx月xx日
附件三目录格式
目录
第一章系统功能说明 (1)
第二章使用说明 (2)
2.1 安装手册 (3)
2.2 使用手册 (4)
第三章程序结构 (5)
3.1 程序结构说明 (6)
3.2 重要数据说明 (7)
3.3 函数清单 (8)
第四章系统设计难点及其解决方法 (9)
第五章不足之处 (10)
第一章系统功能说明
井字游戏的游戏界面是一个3*3的格子,系统提示玩家输入棋子的坐标来表示要下的棋子的位置,如果玩家输入的坐标所在位置已经有棋子或者该坐标已经超出了游戏坐标的范围,就提示玩家重新输入坐标,。
当有三个棋子在一条直线上的时候就结束游戏,并输出哪个玩家赢了。
c井字棋课课程设计

c 井字棋课课程设计一、教学目标本节课旨在通过学习井字棋游戏的设计与实现,让学生掌握以下知识目标:理解井字棋的规则;掌握Python编程基础,如条件语句、循环语句等。
在技能目标方面,学生能够运用Python编程实现井字棋游戏,提高编程能力。
在情感态度价值观目标方面,学生通过小组合作完成游戏设计,培养团队协作精神和问题解决能力。
二、教学内容本节课的教学内容主要包括井字棋游戏的规则介绍、Python编程基础以及井字棋游戏的实现。
首先,介绍井字棋的规则,让学生了解游戏的基本玩法。
其次,教授Python编程基础,包括条件语句、循环语句等,为学生实现井字棋游戏打下基础。
最后,指导学生运用所学的Python编程知识,分组设计并实现井字棋游戏。
三、教学方法为了提高学生的学习兴趣和主动性,本节课采用讲授法、讨论法、案例分析法和实验法等多种教学方法。
在讲授井字棋规则时,采用生动的语言和实例进行讲解,让学生更容易理解和接受。
在教授Python编程基础时,通过案例分析和实验操作,让学生在实践中掌握编程知识。
在设计井字棋游戏环节,鼓励学生分组讨论、合作解决问题,培养团队协作精神。
四、教学资源为了支持教学内容和教学方法的实施,丰富学生的学习体验,本节课准备以下教学资源:教材《Python编程:从入门到实践》、参考书《Python核心编程》、多媒体资料(井字棋游戏教学视频、编程实例演示等)、实验设备(计算机、投影仪等)。
这些教学资源将有助于学生更好地掌握井字棋游戏的设计与实现,提高编程能力。
五、教学评估本节课的教学评估将采用多元化评价方式,全面客观地评价学生的学习成果。
评估主要包括以下几个方面:1.平时表现:观察学生在课堂上的参与程度、提问回答、小组讨论等,以了解学生的学习态度和实际操作能力。
2.作业:布置相关的编程练习,要求学生在规定时间内完成,以检验学生对井字棋游戏设计和Python编程知识的掌握程度。
3.考试:设置期末考试,包括选择题、填空题和编程题,全面测试学生对本节课知识点的理解和应用能力。
井字棋小游戏课程设计

井字棋小游戏课程设计一、课程目标知识目标:1. 学生能理解井字棋的规则和基本策略,掌握游戏的胜负判断方法。
2. 学生能运用所学知识,设计并实现一个简单的井字棋游戏。
技能目标:1. 学生通过编程实践,提高逻辑思维和问题解决能力。
2. 学生学会使用所学编程语言进行程序设计和调试。
情感态度价值观目标:1. 培养学生对编程的兴趣和热情,增强学习计算机科学的自信心。
2. 培养学生合作学习的意识,提高团队协作能力和沟通能力。
3. 培养学生勇于尝试、克服困难的精神,形成积极向上的学习态度。
课程性质:本课程为信息技术课程,以实践操作为主,结合理论知识,培养学生的编程兴趣和基本技能。
学生特点:五年级学生,对新鲜事物充满好奇心,具备一定的计算机操作基础,但编程经验有限。
教学要求:结合学生特点,注重实践操作,激发学生兴趣,引导学生通过合作探究,培养编程思维和实际操作能力。
将课程目标分解为具体的学习成果,以便后续教学设计和评估。
二、教学内容1. 井字棋游戏规则及策略分析:介绍井字棋的基本规则,引导学生分析游戏策略,理解游戏胜负判断方法。
2. 编程语言基础:回顾所学的编程语言基础知识,如变量、数据类型、条件语句和循环语句等,为后续编程实践打下基础。
3. 井字棋游戏设计:讲解如何使用编程语言设计并实现井字棋游戏,包括游戏界面设计、玩家输入处理、棋盘状态更新等。
4. 游戏测试与优化:教授学生如何测试和调试程序,发现并修复游戏中的问题,提高游戏的稳定性和可玩性。
教学内容安排和进度:第一课时:井字棋游戏规则及策略分析,回顾编程语言基础知识。
第二课时:设计井字棋游戏框架,实现游戏界面和基本功能。
第三课时:完善井字棋游戏功能,测试与优化游戏。
教材章节关联:本教学内容与教材中关于编程实践和应用的相关章节相联系,如《计算机科学》第五章“程序设计基础”、《信息技术》第三章“计算机编程初步”等。
教学内容列举:1. 井字棋规则及策略2. 编程语言基础知识3. 游戏设计原理4. 编程实现井字棋游戏5. 游戏测试与优化方法三、教学方法本课程采用以下教学方法,旨在激发学生的学习兴趣,提高学生的主动性和实践能力:1. 讲授法:教师通过生动的语言和示例,讲解井字棋游戏规则、策略分析以及编程基础知识。
井字棋实验报告

井字棋实验报告篇一:井字棋实验报告课程:班别小组成员人工智能原理及其应用12商本学号及姓名指导老师实验02井字棋1、总体要求:1.1总体功能要求:利用不同的方法,实现人机对战过程中呈现出不同程度的智能特征:(1)利用极大极小算法、α-β剪枝来提高算法的效率。
(2)使用高级语言,编写一个智能井字棋游戏。
(3)结合极大极小算法的使用方法和α-β剪枝,让机器与人对弈时不但有智能的特征,而且计算的效率也比较高。
1.2.开发平台要求:开发者开发的软件必须能够在不同系统的电脑上正常运行,因此开发平台为:开发环境:JDK1.6开发工具和技术体系:为了此游戏能够很好的在不同系统中运行,因选择javaee进行开发,利用eclipse1.3项目管理要求:(1)项目程序编写过程中要适当的写一些注释,以便下次作业时能够快速的上手和以后的修改:(2)项目程序要保存在一个固定的工作区间;(3)确保代码不要太多冗余2、需求分析:2.1软件的用户需求:井字棋游戏的用户希望游戏除了有一般的功能之外,还可以通过极大极小算法、α-β剪枝等方法是的井字棋游戏能够拥有智能特征,并是的电脑在人机对弈的过程中因玩家的难度选择而体现不同程度的智能状况。
2.2软件的功能需求:本游戏需要实现功能有:(1)游戏的重新设置(2)游戏统计(如:人赢的次数、电脑赢的次数等)(3)游戏的退出(4)不同智能程度下(脑残、懵懂、正常、智能),人机对弈(5)既可以选择难度,也可以选择谁走第一步(人or电脑) 2.3软件的性能需求:井字棋游戏需要以图形界面的形式表现出来,通过点击图标就可以进入游戏;在游戏进行时,人机对弈时电脑能够快速的反应并根据人的上一步动作作出,通过选择“脑残、懵懂、正常、智能”难度选择,电脑以不同程度的智能与人进行游戏对弈。
2.4 运行环境:能够运行java程序的环境(装有jdk 或者jre)2.5 用户界面设计:用gridlayout进行用户界面的设计把界面中分为不同的模块。
c语言井字棋课程设计

c语言井字棋课程设计一、课程目标知识目标:1. 理解C语言基本语法结构,掌握变量定义、数据类型、运算符和表达式等基础知识。
2. 学习使用C语言实现数组操作,掌握二维数组的使用方法。
3. 掌握C语言控制结构,如顺序结构、选择结构(if-else)、循环结构(for、while)等,并能运用到实际编程中。
技能目标:1. 培养学生运用C语言解决问题的能力,学会分析问题、设计算法、编写代码、调试程序。
2. 培养学生团队合作意识,学会在团队中分工协作,共同完成项目。
3. 提高学生逻辑思维能力,学会通过编程解决实际问题。
情感态度价值观目标:1. 培养学生积极的学习态度,激发学生对编程的兴趣和热情。
2. 培养学生面对问题敢于挑战、勇于克服困难的精神,增强自信心。
3. 培养学生遵守编程规范,养成良好的编程习惯。
本课程针对初中年级学生,结合C语言学科特点,注重培养学生的编程兴趣和实际动手能力。
课程内容以井字棋游戏为载体,引导学生学习C语言基础知识,掌握编程技巧,同时强调团队合作和逻辑思维能力的培养。
通过本课程的学习,使学生能够在实践中巩固所学知识,提高编程技能,培养积极向上的情感态度。
二、教学内容1. C语言基础知识回顾:变量定义、数据类型、运算符和表达式。
2. 数组概念及使用:一维数组、二维数组,重点掌握二维数组在井字棋游戏中的应用。
3. 控制结构:顺序结构、选择结构(if-else)、循环结构(for、while),结合井字棋游戏逻辑进行讲解。
4. 函数定义与调用:介绍函数的概念,编写并调用函数完成井字棋游戏功能模块。
5. 井字棋游戏设计:a. 游戏界面设计:使用二维数组表示棋盘,设计美观易用的游戏界面。
b. 玩家输入与输出:实现玩家输入落子位置,并在棋盘上显示落子。
c. 判断胜负:编写函数判断当前棋局是否分出胜负,并输出结果。
d. 人工智能对手:引入简单的算法,实现电脑自动落子,与玩家对弈。
6. 项目实践:分组进行项目实践,每组完成一个完整的井字棋游戏。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
软件工程课程设计报告题目:井字棋游戏班级:2013软件工程学号:*****************姓名:***二○一四年十二月一日课程设计题目说明书第一章可行性研究1.1引言1.1.1可行性研究目的在课程设计项目中,井字棋游戏设计作为初学者的我们来说,是个比较适合和有研究意义的题目。
“井字棋”游戏(又叫“三子棋”),或是一字棋,是一款十分经典的益智小游戏,想必很多玩家都有玩过。
“井字棋”的棋盘很简单,是一个3×3的格子,很像中国文字中的“井”字,所以得名“井字棋”。
“井字棋”游戏的规则与“五子棋”十分类似,“五子棋”的规则是一方首先五子连成一线就胜利;“井字棋”是一方首先三子连成一线就胜利。
虽然这只是个很简单的小游戏,但作为初学者的我们认识项目设计的技巧与结构及其概念的理解,封装性、继承派生、多肽的理解及实现,是比较好的课题。
对我们以后的大型程序的设计奠定了基础。
所以作为我们这次的课程设计项目来说,我们认为是个很好的、有可研究性的设计项目。
1.1.2背景(说明井字棋设计背景,开发目的等)对于21世纪的人们来说,游戏日益成为我们生活中必不可少的休闲娱乐工具。
为了满足人们的需要,现在越来越多的人们把游戏作为一种商品对待,就比如中国,像盛大、网易、滕讯等大型的游戏开发公司更把游戏的研究看作是一棵摇钱树,所以游戏程序设计人员在未来是不可多得的人才。
对于学软件工程的我们来说,一个优秀的程序员也许是我们学习的优秀目标,所以在出始阶段我们就注重项目设计的理念,而且喜欢游戏的我们更希望自己在将来能够做出一个自己很满意且适合市场的游戏来,所以我们这次以这个为题目就是想熟悉游戏编程的最基础的设计思想和实现手段的了解,为我们以后打下基础。
虽然井字棋是个很简单的小游戏,基本上人们都不玩了,但是作为一种我们的设计项目,我们都觉得是个很好的且适合的项目。
1.2可行性研究的前提1.2.1要求(说明井字棋的预期要求)功能:屏幕输出棋盘和棋子(可用特殊符号代替);实现:用户与电脑下棋(可选)功能和修改。
难点:判断输赢的算法及简单的人工智能实现。
1.2.2目标首先:能做出棋盘的基本样式。
最后:能实现玩家与电脑的对弈,最好能做到电脑的智能化。
1.2.3评价尺度第一:实现电脑的智能化;第二:做到界面美观易懂;第三:达到娱乐的最低水平。
第二章需求分析2.1 任务概述该软件的设计主要是实现简单的三字棋,能做到玩家与玩家之间的对弈或者玩家与电脑之间的对弈,可考虑怎样实现电脑的智能化。
其次,从程序的设计过程中理解实现程序的方法和理念,学会怎么样做到面向对象设计,理解面向对象的概念及结构的封装性和实用性,能为以后的设计奠定一些良好的基础。
2.2对性能的规定此节说明软件的性能要求:精度:本程序中按照系统给出的提示,输入数字,实现程序的功能。
应该注意,输入的一定只能是数字,若输入字母或其他,则出错。
时间特性:由于本程序并不是很庞大,故响应时间短,显示结果迅速。
故障处理要求:只有在非法输入是,出现死循环,此时应该退出程序,重新输入。
运行环境规定运行的软件环境:windows 7、windowsXP、运行该软件所需要的硬设备:PC机一台。
第三章概要设计3.1 总体设计3.1.1 基本设计概念和处理流程人机对弈的难点在于当人走一步棋之后,计算机如何走下一步,即计算机如何找出最合适的位置去走棋。
这就需要一定的算法,或者叫做计算机的AI。
对于井字棋、五子棋等两方较量的游戏来说,Minimax算法(极小极大算法)是最基本也是最常用的。
算法的原理不在这里解释了,我们直接看该算法在井字棋中的应用。
井字棋中,假设使用“X”的是人,使用“O”的是计算机。
“X”方先走,设定X方的最大利益为正无穷(程序使用常量+INFINITY表示),O方的最大利益为负无穷(程序中使用-INFINITY表示),即X方和O方走的每步棋都要力图使自己的利益最大化,而使对方的利益最小化。
这样我们称X方为MAX(因为他总是追求更大的值),O方为MIN(它总是追求更小的值),各自都为争取自己的最大获益而努力。
现在举例说明,比如图4所示的棋局树:图1棋局形成的树X方先走,有三种选择,如图4中第二层所示。
假设X方选择最左边的走法,那么O方接下来将有5种走法,O方会选择最小化的走法,即值为-1的走法,因为它的最大利益是负无穷;同理,X方的另外两种走法会分别得到O方的最小值1和-2。
这样,对于X方来说,三种走法会导致O方最小化值分别为-1、1、-2,X方的最佳策略则是选择其中最大的,即第二层中间的走法,因为它的最大利益是正无穷,这就是极小极大算法的体现——X方的选择总是极大化,O方的选择总是极小化。
对于其中那些值的是如何计算的,我们举例说明,比如对于第三层最左边的棋局,在这种状态下,如果把棋局空白处都填上X,则X共有6中3连子情况,即获胜情况;如果把空白处都填上O,则O共有5种3连子情况,所以结果是二者相减等于1。
在具体走起过程中,MAX面对MIN最大获利中的最小值时,会选择其中最大的,比如图4第二层小括号内的值都是第三层中能使MIN最大获利的最小值,这时候MAX选择其中最大的,这对MAX最为有利,所以MAX方选择图4第二层中间的走法最好。
同样道理,MIN也会一样,选择对自己最有利的,即MAX 有可能获得的最大值。
这时候,MIN在走棋时会考虑MAX方占据哪个位置对MAX最有利,然后MIN把这个位置先占了。
有点难理解,其实就是抢先把对对手有利的位置抢占了。
简单说,X方或者MAX方的走棋时由人来控制的,我们不仔细说了。
对于O方或者MIN方,它走棋时要考虑哪个位置对X方最有利,然后把该位置占据,即O的最佳走棋就是X的最佳走棋。
所以O在走棋之前,先站在X的角度寻找最佳走棋位置。
后文中minimax方法就是站在X角度来考虑极小极大算法,找到X的最佳走棋位置,然后由O方来占据该位置。
2、极小极大算法整个算法包括如下几个部分:首先要有一个评估方法gameState,对每走一步棋后的棋局进行评估,估值为WIN常量说明X方,即MAX方获胜;估值为LOSE则O方,即MIN方获胜;估值DRAW为平局;估值为INPROGRESS,说明棋未走完;估值为DOUBLE_LINK,说明棋局中有两连子情况然后用一个minimax方法寻找在当前棋局状态下X方的最佳位置,X方的最佳位置就是当X走该位置后,O方所有走法中最小值里的最大值,比如图4中第二层X 的位置选择。
当找到该位置后,由O方来抢先占据该位置。
最后用两个递归方法min和max来遍历所有的棋局。
min方法负责找出O 方的最小值,比如图1第二层最左边的棋局会导致5中O方的走法,min方法就是找出这5种走法中的最小值。
同理,max方法负责找出X方的最大值,比如图1第二层三种棋局中的中间棋局。
3.1.2功能需求与程序的关系1.计算机为一方,人为一方,交替下棋,谁先连成一条直线谁胜;允许人选择先下还是后下。
2.界面要求:初始状态——显示棋盘,并显示玩家的操作键;游戏进行状态——动态显示棋盘不同玩家的棋子用不同符号显示,屏幕上显示当前玩家号,结束时显示赢家号。
3.提示计算机自动下棋的规则:计算机下时,应考虑所有空位,并按行、列、对角线计算每个空位的分值,若在某行(列、对角线)上,(设计算机画X,人画O)已有XX 加50分已有OO 加25分已有X空加10分已有O空加8分都是空加4分然后选分值最高的位置画X。
3.2 系统出错处理设计(1)违规输入字符,程序可能会出现死循环或者直接结束程序。
(2)规则里面所定义的若有错误输入,则会根据程序的提示重新输入。
3.3 性能1.程序耗费电脑内存和CPU开销很小。
2.玩家与电脑对战时AL的智能很高。
3.可以选择电脑难度,适合各种水平的玩家。
4.游戏界面比较美观,亲近,方便大众接受。
3.4 程序设计:// 按钮的监听事件private class JBClick implements ActionListener {// 当单击按钮时public void actionPerformed(ActionEvent e) {for (int i = 0; i < 9; i++) {if (e.getSource() == jb[i]) { jb[i].setText("X"); // 被单击的按钮走“X”jb[i].setEnabled(false); //置为不可用}}int gamestate = gameState(jb); // 获取棋盘状态// 如果棋局未结束,则计算机走下一步if (!(gamestate == WIN || gamestate == LOSE || gamestate == DRAW)) { int nextpos = getNextMove(jb); // 获取下一步走棋位置jb[nextpos].setText("O"); // 走棋“O”jb[nextpos].setEnabled(false);gamestate = gameState(jb); // 获取最新的棋盘状态}// 输出棋局胜负switch (gamestate) {case WIN:JOptionPane.showMessageDialog(null, "X方获胜", "提示",JOptionPane.DEFAULT_OPTION);break;case LOSE:JOptionPane.showMessageDialog(null, "O方获胜", "提示",JOptionPane.DEFAULT_OPTION);break;case DRAW:JOptionPane.showMessageDialog(null, "平局", "提示",JOptionPane.DEFAULT_OPTION);break;}// 如果结束,则提示if (gamestate == WIN || gamestate == LOSE || gamestate == DRAW) { int over = JOptionPane.showConfirmDialog(null, "是否再来一局?", "提示",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);if (over == JOptionPane.YES_OPTION) {// 再来一局for (int i = 0; i < 9; i++) {jb[i].setText(" ");jb[i].setEnabled(true);}} else {System.exit(0); // 退出游戏}}}}然后,获取棋局状态的方法加入寻找两连子的代码,如下:// 获取棋盘当前状态public int gameState(JButton[] jb) {int result = INPROGRESS;boolean isFull = true;// 判断棋盘是否已满for (int pos = 0; pos < 9; pos++) {char chess = jb[pos].getText().charAt(0);if (empty == chess) {isFull = false;}}// 寻找三连子情况for (int[] status : WIN_STATUS) {// 遍历8中棋局获胜状态// 得到某个获胜棋局状态的第一个索引的字符char chess = jb[status[0]].getText().charAt(0);// 如果为空,说明此处未下棋子,跳出循环,找下一个状态if (chess == empty) {continue;}int i;for (i = 1; i < status.length; i++) {// 查看其余两个字符if (jb[status[i]].getText().charAt(0) != chess) { // 不与第一个索引字符一致break; // 表明未三子连线,跳出}}if (i == status.length) { // 三子连线result = chess == 'X' ? WIN : LOSE;break;}}// 寻找两连子情况if (result != WIN & result != LOSE) {if (isFull) {result = DRAW; //不输不赢且棋盘满则为平} else {int[] finds = new int[2];// 存放X或O的两连子情况for (int[] status : WIN_STA TUS) {char chess = empty;boolean hasEmpty = false;int count = 0; // 计数for (int i = 0; i < status.length; i++) {if (jb[status[i]].getText().charAt(0) == empty) {hasEmpty = true; // 该处没有棋子} else {if (chess == empty) { // 有棋子chess = jb[status[i]].getText().charAt(0);}if (jb[status[i]].getText().charAt(0) == chess) {count++; //且棋子相同则加1}}}if (hasEmpty && count > 1) {if (chess == 'X') {finds[0]++;} else {finds[1]++;}}}// 两连子情况if (finds[1] > 0) { // O的两连子result = -DOUBLE_LINK;} else if (finds[0] > 0) { // X的两连子result = DOUBLE_LINK;}}}return result; // 记录了胜负平或者两连子情况}O方走棋时,要得到走棋位置,我们用一个方法来获取该位置,如下:public int getNextMove(JButton[] board) {int nextPos = minimax(board, 3);return nextPos;}上面方法中调用了极小极大算法minimax,如下://以'X'的角度来考虑的极小极大算法public int minimax(JButton[] board, int depth) {int[] bestMoves = new int[9];//存放最佳走棋位置int index = 0;int bestValue = -INFINITY;// 搜索所有空位,试探填上X,然后选其中最小值的for (int pos = 0; pos < 9; pos++) {if (board[pos].getText().charAt(0) == empty) {board[pos].setText("X");int value = min(board, depth);// 得到最小值if (value > bestValue) {// 选择最小值里最大的bestValue = value;index = 0;bestMoves[index] = pos;} else if (value == bestValue) {index++;bestMoves[index] = pos;}board[pos].setText(" ");}}return bestMoves[index];}最后,两个递归方法min和max如下://对于'O',估值越小对其越有利public int min(JButton[] board, int depth) {int evalValue = gameState(board);boolean isGameOver = (evalValue == WIN || evalValue == LOSE || evalValue ==DRAW);if (depth == 0 || isGameOver) {return evalValue;}int bestValue = INFINITY;for (int pos = 0; pos < 9; pos++) {if (board[pos].getText().charAt(0) == empty) {board[pos].setText("O");// 选择最小值bestValue = Math.min(bestValue, max(board, depth - 1));board[pos].setText(" ");}}return evalValue;}//对于'X',估值越大对其越有利public int max(JButton[] board, int depth) {int evalValue = gameState(board);boolean isGameOver = (evalValue == WIN || evalValue == LOSE || evalValue == DRAW);if (depth == 0 || isGameOver) {return evalValue;}int bestValue = -INFINITY;for (int pos = 0; pos < 9; pos++) {if (board[pos].getText().charAt(0) == empty) {board[pos].setText("X");// 选择最大值bestValue = Math.max(bestV alue, min(board, depth - 1))board[pos].setText(" ");}}return evalValue;}第五章测试分析本程序的功能非常明显:#字棋。