课设指导书1-21点双人对战与人机对战.docx
19页《C/C++语言课程设计》指导书一、 课程设计概要课题名称:21点双人对战和人机对战二、 课题背景概述21点扑克是牌类游戏中的比较基础游戏,其基本打法为双人共玩一副洗好的52张牌(大小王拿走),采用回合制比每回合输赢,直至打完一副牌算总积分决出胜负每回合双方轮流拿牌,每人牌数2-5张,每回合拿牌结束时统计两人手上牌的总点数,并裁决本回I合输赢如果轮到一方拿牌而放弃,则本回I合此人不能再拿牌;如果手上牌的点数超过21点,则算爆如果双方都没爆,则点数较高者获胜;如果-方爆另一方没爆,则没爆者获胜;如果双方都爆,则爆的少的人(点数超过21点较少者)获胜牌点计算方式:牌面10、J、Q、K均算10点;牌面2-9的点数同数字;花牌A既可以当1点用,也可以当11点用,具体当什么用,由持有花牌者按有利于自己的策略决定,但是计算机裁决程序总是会按最有利于持花牌者的算法自动进行点数计算三、 课程设计目标1、 课题实现的功能目标渐进开发实现21点双人对战和人机对战,并最终实现其类封装和面向对象程序设计2、 知识应用能力的培养目标通过项目开发、调试、完善的过程,渐进地理解、正误、巩固和掌握基本数据类型的使用和转换、顺序-分支-循环的组合应用、变量声明和引用、函数的定义/声明/调用、数组和指针使用、结构体和类的使用等语法知识,熟练掌握常用测试和调试技术手段,达到理论联系实践、融会贯通的目的。
3、 数学建模能力的培养目标随机数产生无重复无遗漏牌张、随机插牌、A牌的用法、计算胜率(在最后的人机对战要用)都涉及一定数学建模和算法设计应用能力,因此在无形中也锻炼了这种能力4、 软件工程方法论培养目标从项目开发过程体会、理解和自觉应用程序设计和测试的思路及方法理解和应用ADT概念和面向对象程序设计思想的由顶向下设计方法,从顶层抽象设计开始,通过过程抽象和数据抽象,逐层分解、渐进推进程序设计实现和测试改进,理顺程序设计和测试完善的思路5、 思维的周密性、趣味性和想象力游戏开发需要考虑各种可能的情况,如果思维不缜密有遗漏、或者逻辑不清晰,就会出现预想不到的情况同时游戏开发又充满了趣味性和需要发挥想象力(数学算法的想象和与生活案例类比、界面美观和易操作性的想象和优化等),学习兴趣是最好的老师和动力,然而要达到理想的效果,只有更好,没有最好,这种挑战和追求完美的精神也是学习动力之-O三、设计内容与步骤概要实验三基于类的21点人机对战一、 实验目的1、 实现用程序自动决策代替一个玩家2、 熟练掌握继承的用法,由父类派生子类3、 使用流程图或伪代码等方法进行人类优化决策的算法描述4、 初步了解不确定性人工智能:基于概率的胜率决策二、 实验内容与步骤1、 从CBlackjack派生出新类CAI21类,该类将实现21点人机对战的全部功能。
2、 遗传和变异的考虑:继承哪些成员,新增哪些成员?本步骤仅给出提示,请阅读以下分析后,结合继承的知识,自行具体实现人机对战,即玩家不是两个人,而是一个玩家是人,一个玩家是计算机程序替代了人类玩家人机对战要求机器能够模拟人的思维方式,很有点人工智能的味道,听起来很玄乎然而就21点扑克游戏实现人机对战,其关键线索很明确:•模拟替代人类的过程函数是什么?•这个函数要实现什么功能?•这个功能需要的核心算法是什么?整个21点双人对战,大的过程主要是两个:首先是程序自动模拟洗牌,然后进入回合循环比赛而在每一个回合中,又分为发牌函数(机器自动先给每个玩家发两张牌)、在一个拿牌循环中两个人各执行一次拿牌函数(机器判断某玩家是否有继续要牌权,若有要牌权则给提示、两人轮流决定要不要继续拿下一张牌、拿牌和亮牌)、比牌函数(机器在回合结束时,也即两人均无要牌权时,自动计算两人点数并裁判本回合输赢)升级为21点人机对战,从过程看,洗牌、自动发牌、比牌这些都仍然是计算机程序自动实现的,没什么变化,真正有变化的只有拿牌函数,双人对战的拿牌函数只有一个(两个人都是人类玩家,玩法是一•样的),而人机对战的拿牌函数应该有两个(人类的拿牌函数和机器的拿牌函数),其中人类玩家的拿牌函数也没有变化,只是要新增一个机器拿牌函数,并且可以复制一个人类拿牌函数后在此基础上改成机器拿牌函数。
由上述分析,我们就应该知道如何继承了,CAI21类基本上需要继承CBlackJack类的那些函数和成员变量?继承下来的不需要再重复写代码了在继承的基础上再变异、添加自己的新函数在继承的基础上再变异、添加自己的新函数由此,就能生成新的CAI21框架3、 自动玩家的能力分析玩家1现在变成了机器自动玩家(简称为Auto玩家)而玩家2现在还是人类玩家(简称为Man玩家)先来看一下Auto的能力1)Auto会记牌,可以记住双方打过的所有的牌,这个能力很重要,不是每个人都能记住每张牌的记住所有打过的牌,意味着也就知道还有哪些牌没打出来2)由于Auto具备完美的记牌能力,所以他会算如果拿牌的话,拿到每种牌的可能性有多大一共有13种牌,每种总数是4张假设我们按这13种将已经打过的牌分类进行统计,那么就可以得到一个己经打过的牌张个数数组intiOutCardCnt[13];如果用4减去iOutCardCnt数组中的每个元素,就可以得到剩余牌张数组int iRemainCardCnt[13]o拿到第i种牌的可能性(概率)为P[i] = iRmainCardCnt[i] /剩余牌总数,P数组应该是一个整型数组还是浮点数组?。
4、 自动玩家的决策逻辑(是否拿下一张牌的决策算法描述)自动玩家的决策逻辑,可以分为必须拿牌和必须不拿牌的确定性逻辑,和依据如果拿牌是否会爆的可能性(拿牌后爆的概率)大小来决定是否拿牌的不确定性推理,两种情况1) 必须拿牌和必须不拿牌的情况•如果已经无牌可拿,则肯定不再拿牌•如果自己已经爆了或者正好拿到21点满分,或者对方已经爆了,则肯定不再拿牌•都未爆,且当前自己牌点落后于对方,则无论如何都必须拿牌(2) 都未爆,且当前自己牌点领先或持平于对方,依据爆的概率大小决定是否拿牌•统计13种牌的剩余张数int iRemainCnt[13] = {0};换算成13种牌可能出现的概率数组float p[13],其中p[i]=(float)iRemainCnt[i] /剩余牌总数,思考一下为何要强制类型转换?•假设拿到下一张是这13种牌的第i种牌,计算拿牌后的点数并判断是否会爆(拿牌后若点数大于21即爆),得到bool bOverflow[13]数组,其中bOverflow[i佣于标记假如拿到第i种牌,是否会爆•计算拿牌后爆的条件概率和总概率拿到第i种牌的爆牌条件概率=bOverflow[i] * p[i]爆牌总概率percent = 13种爆牌条件概率之和•依据爆率大小决定是否拿牌若爆率percent < ().5则拿牌,否则不拿牌(3)上述是否拿牌的决策算法,可以提炼为以下流程图表示:计算拿牌后爆的概率否不拿牌否编程实现机器人(自动玩家)自动判断是否拿牌的函数IfTakeCard5、 改写和添加必要的函数,并形成程序柩架,用循环实现双人对战和人机对战的游戏选择和游戏过程。
6、 基于本实验内容具有一定复杂度,提供程序框架,在算法部分提供提示,请同学们按照提示和函数设计说明填写完成具体实现代码,并可对类和函数的封装、框架代码和算法等做适当的调整与优化附件三当堂验收打分表打分说明:较好全勾,中等半钩,很乱或很差打叉班号: 学号: 姓名:验收项序号功能完成项完成情况1游戏设计界面设计的清晰美观利易操作性2CAI21是否主要由CBlackJack类继承而来3机器自动拿牌函数是否完成和通过功能测试4是否实现人机对战打完一个回合无错误5是否实现人机对战打完一副牌无显著错误6是否可以循环游戏无bug7成员函数使用参数和成员变量的取舍是否合理8程序代码格式规范性和可读性9程序编译错误和功能错误的调试能力10抽查三行代码请加以说明代码意图(抽查自己编写或改写部分,提供的原样框架代码不查,请根据框架代码打印对照)课题分为三个实验阶段渐次进行,每个阶段8学时,逐渐优化实验一实现21点双人对战的主要功能;实验二在实验一基础上进行控制台游戏项目整体规划,将21点双人对战封装成整个游戏项目的一个类CB lack Jack;实验三在实验二基础上,由CBlackJack派生出人机对战类CAI21,实现机器玩家自动记牌、分析是否有必要继续拿牌(如己稳操胜券则无需再拿下一张牌)、算拿到下张牌是什么牌的可能性(概率),进而决定是否继续拿牌,即机器玩家取代了一个人类玩家的所有思维过程和行为。
最后需要设计一个菜单,在程序启动时,用户可以选择玩双人对战21点还是人机对战21点实验一 21点双人对战的初步设计一、 实验目的1、 通过双人21点打牌游戏的编程,熟练掌握Visual C++ 6.0或VS2010等开发环境(可以使用自己习惯用的平台,不过机房台式机只能安装6.0和2010,其他版本开发平台需要自己带笔记本去)、Win32控制台项目的新建项目、新建文件、软件编译、生成、执行的过程2、 熟练掌握常见编译错误及功能性错误的常用调试方法3、 巩固和复习C/C++语言基木语法内容(1) 输入输出语句(2) 循环、分支语句(3) 变量和函数的定义和使用(4) 数组和字符数组、字符串操作、指针二、 实验内容1、 建立一个Win32控制台项目,并向项目添加新建的C++源文件,项目名和文件名都为Blackjack,使用include向源文件添加支持标准C和C++输入输出操作的包含头文件2、 为实现黑杰克(21点)扑克游戏编程,首先阅读理解以下简化版的21点游戏规则:(1) 两个人(以下我们称为甲乙,英文名为player 1和player2)共玩一副扑克牌(大小王拿掉不要),剩下的是桃心梅方4种花色,每种13张牌,一共52张牌,每种花色的13张牌分别是2~10的小点数牌和J、Q、K、A四种花牌,玩前先随机洗牌;(2) 进行一轮要牌过程(本回合开始):甲乙分别循环要牌比大小(甲乙双方在要牌过程中都知道对方是什么牌),每次都是先甲要牌,然后轮到乙要牌。
在每次要牌时,甲或乙都可以根据自己手上牌决定这次要还是不要,但如果这次没要,下次就不能再要了甲乙的要牌的总数量在2-5之间,即每人最少必须要2张牌,最多不得超过5张牌3) 甲乙比牌点:算自己手上牌的总分,总分超过21点算“爆”,输了;如果两个人都“爆”,则爆的少的人赢(总分-21小的人赢);都没爆的情况下,谁的总分高谁赢4) 牌点的算法:2〜10的牌按牌面算分,即2牌一张就是2分;花牌J、Q、K每张算10分;花牌A是一个变数,既可以当1分算,也可以当11分算,按照最有利玩家的算法算(即在不爆的情况下点数最大为原则)(5) 比完一次(本回合结束),对本次输赢情况记录,在剩下的牌中继续要牌和比点,即每人手上牌清零,然后返回(2)进入下一回合要牌比点6) 当已经没有剩余牌(52张牌已经被两玩家拿光)的时候游戏结束,统计各回合赢情况并。





