数据结构课程设计实验报告-

仲 恺 农 业 工 程 学 院

课 程 设 计 报 告

课程名称   数据结构    

院(系)计算机科学与工程

专    业计算机科学与技术

班    级  计算机102班 

学    号   

姓    名       

指导老师    

目    录

题目

(一)     需求和规格说明:问题描述,即题目要解决的问题是什么

(二)     算法设计(包括程序流程图,如函数功能、入口及出口参数说明,函数调用关系描述等)

(三)      详细设计(源程序清单,要包括足够的注释)

(四)      调试分析(包括调试数据与调试结果)

(五)      课程设计总结(包括程序中遇到的问题及解决方案,以及课程设计收获)

题目

     斗地主游戏(简单版)

(一) 需求和规格说明:问题描述,即题目要解决的问题是什么

系统基本要求:

具备基本的界面形式及操作功能

具备基本的AI能力

解决问题:

(1)   以MFC作为程序框架

(2)   图片以位图的形式出现,并进行基本的界面操作

(3)   以链表及广义表等形式(C++封装好的),进行数据的操作

(4)   设计了简单的AI函数,用以对游戏的进行,判断等

(二) 算法设计(包括程序流程图,如函数功能、入口及出口参数说明,函数调用关系描述等)

(三) 详细设计(源程序清单,要包括足够的注释)

斗地主游戏(简单版)源程序(部分)如下:

注:由于具体框架为程序自主产生,在这里不再出现,只列出View类函数,程序中绿色程序代码为实验中出错的部分或者验证部分

// 试验品View.cpp : C试验品View 类的实现

//

#include "stdafx.h"

#include "试验品.h"

#include "试验品Doc.h"

#include "试验品View.h"

#include"algorithm"

#include"Ctime"

#include"vector"

#ifdef _DEBUG

#define new DEBUG_NEW

#endif

// C试验品View

IMPLEMENT_DYNCREATE(C试验品View, CView)

BEGIN_MESSAGE_MAP(C试验品View, CView)

     // 标准打印命令

     ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)

     ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)

     ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)

     ON_WM_LBUTTONDOWN()

     ON_WM_CREATE()

     ON_BN_CLICKED(IDB_BUTTON1,OnButton1Clicked)

     ON_BN_CLICKED(IDB_BUTTON2,OnButton2Clicked)

END_MESSAGE_MAP()

// C试验品View 构造/析构

C试验品View::C试验品View()

: m_point(0)

, width(0)

, height(0)

, x_machine(0)

, current_player(0)

{

     // TODO: 在此处添加构造代码

   

     for(int j=0;j<20;j++)

     {

         m_key[j]=j+1;

     }

     for(int i=3;i<16;i++)

     {

         for(int j=0;j<4;j++)

              vec.push_back(i);

     }

     vec.push_back(53);

     vec.push_back(54);

     srand(time(0));

     random_shuffle(vec.begin(),vec.end());

     vec1.assign(vec.begin(),vec.begin()+17);

     vec2.assign(vec.begin()+17,vec.begin()+34);

     vec_game.assign(vec.begin()+34,vec.end());

     std::sort(vec1.begin(),vec1.end());

     std::sort(vec2.begin(),vec2.end());

     std::sort(vec_game.begin(),vec_game.end());

    

     v1=vec1;

     v2=vec2;

     v_game=vec_game;

}

C试验品View::~C试验品View()

{

}

BOOL C试验品View::PreCreateWindow(CREATESTRUCT& cs)

{

     // TODO: 在此处通过修改

     //  CREATESTRUCT cs 来修改窗口类或样式

     return CView::PreCreateWindow(cs);

}

//左键点击

void C试验品View::OnLButtonDown(UINT nFlags,CPoint point) {

     m_point=point;

    

     InvalidateRect(FALSE);//传递窗口重绘的消息该OnDraw()

     CView::OnLButtonDown(nFlags,point);

}

// C试验品View 绘制

void C试验品View::OnDraw(CDC* pDC)

{

     C试验品Doc* pDoc = GetDocument();

     ASSERT_VALID(pDoc);

     if (!pDoc)

         return;

     CRect rcWksMng;

     this->GetWindowRect(rcWksMng);

     height=rcWksMng.bottom-rcWksMng.top;//得到当前窗口大小,当时为什么位图大小无法改变

     width=rcWksMng.right-rcWksMng.left;

     CDC MemDC;

     MemDC.CreateCompatibleDC(NULL);

     MemDC.SelectObject(pDoc->m_Beijing);

pDC->StretchBlt(0,0,width,height,&MemDC,0,0,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

//按照第一二参数为原点坐标,第三四为变化后的宽高,第四为文件句柄指针,后面是原来的  

//在OnDraw中可以直接用pDC,但是在其他呢??

     MemDC.SelectObject(pDoc->m_Bitmap);

     int width0=width/25;

     int height0=height/25;

     pDC->SetStretchBltMode(COLORONCOLOR);//防止失色

     for(int i=0;i

     {

         pDC->StretchBlt(width0,height-7*height0-i*height0,3*width0,3*height0,&MemDC,0,0,

pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

     }

   

     for(int i=0;i

     {

         pDC->StretchBlt(width-4*width0,height-7*height0-i*height0,3*width0,3*height0,&MemDC,0,0,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

     }  

     int t=0,i=0,j=0,k=0;;

     std::vector B_m;

//CBitmap 数组为什么无法相互赋值,而list,vector类型的确需要指针呢

     for(std::vector::reverse_iterator riter=vec_game.rbegin();riter!=vec_game.rend();riter++)

     {//游戏方牌组所对应的CBitmap值

         if(*riter<16)

         {

              if(t==*riter)

                   ++i;

              else

                   i=0;

              j=*riter-3+i*13;

         }

         else

         {

              j=*riter-1;

         }

  

    B_m.push_back((pDoc->m)+j);

         t=*riter;

     }

     int p=JudgeRect(m_point);

     if(p!=-1)//点击桌面的牌牌时,促使弹起

     {

         for(i=0;i

         {

              MemDC.SelectObject(*(B_m[i]));

              if(m_np[i]!=1)//不要写==0,因为原来m_np[i]没有赋值为随意不为零的数

                   pDC->StretchBlt(2*width0+i*width0,height-3*height0,3*width0,3*height0,&MemDC,0,0

,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

              else

                   pDC->StretchBlt(2*width0+i*width0,height-4*height0,3*width0,3*height0,&MemDC,0,0

,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

         }

     }

     else

     {

         for(i=0;i

         {

              MemDC.SelectObject(*(B_m[i]));

             pDC->StretchBlt(2*width0+i*width0,height-3*height0,3*width0,3*height0,&MemDC,0,0

,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

             if(i!=B_m.size()-1)

             {

                   CRectr(2*width0+i*width0,height-3*height0,2*width0+(i+1)*width0

,height-3*height0+pDoc->m_nHeight);

                  rect[i]=r;

             }

             else

             {

                  CRectr(2*width0+i*width0,height-3*height0,2*width0+i*width0+pDoc->m_nWidth

,height-3*height0+pDoc->m_nHeight);

                  rect[i]=r;

             }

         }

         for(i=0;i<20;i++)

         {

              m_np[i]=0;

         }

     }

    

     //表示出所出的牌到桌面上

     t=0,i=0,j=0,k=0;;

     std::vector BB_m;

//CBitmap 数组为什么无法相互赋值,而list,vector类型的确需要指针呢

     for(std::vector::reverse_iterator riter=vec_chu.rbegin();riter!=vec_chu.rend();riter++)

     {//游戏方所出得牌组所对应的CBitmap值

         if(*riter<16)

         {

              if(t==*riter)

                   ++i;

              else

                   i=0;

              j=*riter-3+i*13;

         }

         else

         {

              j=*riter-1;

         }

  

    BB_m.push_back((pDoc->m)+j);

         t=*riter;

     }

     for(i=0;i

     {

         MemDC.SelectObject(*(BB_m[i]));

         pDC->StretchBlt(5*width0+i*width0,height-7*height0,3*width0,3*height0,&MemDC

,0,0,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

     }

     if(x_machine!=0)

//之所以把current_player=1或者后的操作写在外面,是因为,当鼠标点击到飞按钮区域时图片依然存在

     {   

         std::multimap mp_machine,pm_machine,mmpp,ppmm;

         std::multimap::size_type st;

         std::multimap::iterator iter_machine;

         if(current_player==1)

         {

              transition(mp_machine,pm_machine,vec1);

             vcc.clear();//需要消去原来的元素,避免元素叠加

             machine(vec1,mp_machine,pm_machine);

         }

         else

         {

              transition(mp_machine,pm_machine,vec2);

             vcc.clear();

             machine(vec2,mp_machine,pm_machine);

         }

         transition(mmpp,ppmm,vcc);

         judge_game(mmpp,ppmm,vcc);

                

         x_machine=0;

     }

    if(current_player==1)//当一比二先下时的情况,包含接下来得二所要下的形式

     {

         std::vector B_m1;

//CBitmap 数组为什么无法相互赋值,而list,vector类型的确需要指针呢

         i=3;

         for(std::vector::reverse_iterator riter=vcc.rbegin();riter!=vcc.rend();riter++)

         {//游戏方牌组所对应的CBitmap值

              if(*riter<16)

             {

                   if(t==*riter)

                       --i;

                  else

                       i=3;

                  j=*riter-3+i*13;

             }

             else

             {

                   j=*riter-1;

             }

  

        B_m1.push_back((pDoc->m)+j);

             t=*riter;

          }

          for(i=0;i

          {

               MemDC.SelectObject(*(B_m1[i]));

              pDC->StretchBlt(5*width0+i*width0,height-11*height0,3*width0,3*height0,&MemDC

,0,0,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

          }

//以下是,机器一后,判断机器二是否有下,如果有则进行处理,可以加入更多的只能

          std::map c;

          c=Brand_size.begin()->first;

          int x=c.begin()->first;

          int y=c.begin()->second;

          int z=Brand_size.begin()->second;

          int xx=0;

          std::multimap mmm,ppp;

          transition(mmm,ppp,vec2);

         xx=continuation(mmm,z,y,x);//表示机器二是否有牌

          if(xx==0)

               current_player=1;//当二下次无法找到牌时,就在桌面上保持一的存在

          else

               current_player=2;

       

          if(xx!=0)

          {

               if((x==1&&vec2.size()<3)||(x==2&&vec2.size()<5)||(x==1&&z<14&&vec2.size()>2)

||(x==2&&z<12&&vec2.size()>4))

               {

                    std::multimap mp_machine,pm_machine,mmpp,ppmm;

                  std::multimap::size_type st;

                  std::multimap::iterator iter_machine;

                  transition(mp_machine,pm_machine,vec2);

                  vcc.clear();

                  machine(vec2,mp_machine,pm_machine);

//功能是除去vec2中的元素到vcc中作为图片载入的依据

                    

                    transition(mmpp,ppmm,vcc);

                  judge_game(mmpp,ppmm,vcc);//改变Brand_size的数值,保持与当时下牌方一致

               }

          }

     }

     if(current_player==2)//二下牌后的图片显示

     {

         std::vector B_m1;

//CBitmap 数组为什么无法相互赋值,而list,vector类型的确需要指针呢

         i=3;

//因为时间缘故,且不知道怎么判断花色,所以就直接的玩家下的牌就从前面顺序在m[]中找出CBitmap而两个机器就直接从后面算起,所以i=3;

         for(std::vector::reverse_iterator riter=vcc.rbegin();riter!=vcc.rend();riter++)

         {//游戏方牌组所对应的CBitmap值

              if(*riter<16)

             {

                   if(t==*riter)

                       --i;

                  else

                       i=3;

                  j=*riter-3+i*13;

             }

             else

             {

                   j=*riter-1;

             }

  

        B_m1.push_back((pDoc->m)+j);

             t=*riter;

          }

          for(i=0;i

          {

               MemDC.SelectObject(*(B_m1[i]));

              pDC->StretchBlt(5*width0+i*width0,height-15*height0,3*width0,3*height0,&MemDC

,0,0,pDoc->m_nWidth,pDoc->m_nHeight,SRCCOPY);

          }

          current_player=2;

//使得机器二能够在桌面上保持显示,直到二没有牌下,也作为玩家不要时,下牌者的判断依据

     }

     // TODO: 在此处为本机数据添加绘制代码

}

// C试验品View 打印

BOOL C试验品View::OnPreparePrinting(CPrintInfo* pInfo)

{

     // 默认准备

     return DoPreparePrinting(pInfo);

}

void C试验品View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

     // TODO: 添加额外的打印前进行的初始化过程

}

void C试验品View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)

{

     // TODO: 添加打印后进行的清除过程

}

// C试验品View 诊断

#ifdef _DEBUG

void C试验品View::AssertValid() const

{

     CView::AssertValid();

}

void C试验品View::Dump(CDumpContext& dc) const

{

     CView::Dump(dc);

}

C试验品Doc* C试验品View::GetDocument() const // 非调试版本是内联的

{

     ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(C试验品Doc)));

     return (C试验品Doc*)m_pDocument;

}

#endif //_DEBUG

// 判断点是否在矩形里面,返回对应矩形号

int C试验品View::JudgeRect(CPoint point)

{

     if(point.xrect[19].right||point.y

||point.y>rect[0].bottom)

     {

         for(int i=0;i<20;i++)

//需要这个否则点击随意后其他虽然弹入,但是当点其他时,还是会重新弹出,同时,不进行赋值的话,第一次点击不会弹出因为第一次时,下面的if语句会直接先赋值,即点击后还是按照原来的图片形式

              m_np[i]=0;

         return -1;

     }

     for(int i=0;i

     {

         if(point.x>rect[i].left&&point.xrect[i].

top&&point.y

         {

              if(m_np[i])

                   m_np[i]=0;

              else

                   m_np[i]=1;

              return i;

         }

     }

     return -1;

}

int C试验品View::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

     if (CView::OnCreate(lpCreateStruct) == -1)

         return -1;

     // TODO:  在此添加您专用的创建代码

     int w=width/25;

     int h=height/25;

//   m_Button1.Create(_T("出牌"),WS_CHILD | BS_PUSHBUTTON | WS_BORDER,//vs2005本身问题,需要把char[] 转换为LPCTSTR类型

     m_Button1.Create(_T("出牌"),WS_CHILD|BS_PUSHBUTTON|WS_VISIBLE|WS_BORDER,

         CRect(400,20,480,60),this,IDB_BUTTON1);

     m_Button2.Create(_T("不出"),WS_CHILD | BS_PUSHBUTTON |WS_VISIBLE | WS_BORDER,

         CRect(500,20,580,60),this,IDB_BUTTON2);

     return 0;

}

void C试验品View::OnButton1Clicked()

{

     int i,x1,y1,z1;

     int t=0;

     std::vector vec;//CString s;s.Format

     std::vector::reverse_iterator riter=vec_game.rbegin();

     std::map c1;

     if(current_player==1||current_player==2)

     {

         c1=Brand_size.begin()->first;

         x1=c1.begin()->first;

         y1=c1.begin()->second;

         z1=Brand_size.begin()->second;

     }

     std::multimap mp,pm;

     for(i=0;i<20;i++)

     {

         if(m_np[i]==1)

         {

              vec.push_back(*(riter+i));

              t=1;

         }

     }

     if(t==0)

         MessageBox(_T("请选择输出的牌"));

     else

     {

         std::sort(vec.begin(),vec.end());

         transition(mp,pm,vec);

         judge_game(mp,pm,vec);

         std::map c;

         c=Brand_size.begin()->first;

         int x=c.begin()->first;

         int y=c.begin()->second;

         int z=Brand_size.begin()->second;

         if(current_player==1||current_player==2)

         {

              if((x1!=x)||(y1!=y)||(!(z1

              {

                   MessageBox(_T("请重新选择输出的牌"));

                   std::map t;

                   t.insert(std::map::value_type(x1,y1));

                   Brand_size.clear();

                   Brand_size.insert(std::map,int>::value_type(t,z1));

                   x=0;

                   y=0;

                   z=0;

                   InvalidateRect(FALSE);

              }

         }

         if(x!=0&&y!=0&&z!=0)

         {

              i=vec_game.size()-1;

              vec_chu.clear();

              for(std::vector::iterator iter=vec_game.begin();iter!=vec_game.end();i--)

              {//减去游戏者所下的牌

                   if(m_np[i]==1)

                   {

                       vec_chu.push_back(*iter);

                       iter=vec_game.erase(iter);

                   }

                   else

                       iter++;

              }

              std::multimap mmm,ppp,mmm1,ppp1;

             transition(mmm,ppp,vec1);

            x_machine=continuation(mmm,z,y,x);//表示机器一是否有牌

              if(x_machine==0)//如果一有下,则调用一下地情况

              {

                   transition(mmm1,ppp1,vec1);

                x_machine=continuation(mmm1,z,y,x);//表示机器二是否有牌

                   if(x_machine==0)//否则,调用二下的情况,可以加入一些智能

                       current_player=0;

                   else

                       current_player=2;

              }

             else

                   current_player=1;//表示机器出牌

//            x_machine=1;

              InvalidateRect(FALSE);//传递窗口重绘的消息该OnDraw()

         }

//       CString str;

//       str.Format(_T("%d,%d,%d",x,y,z));想用这个调式看结果但是谁让对了,但是输出不对,到底该怎么用呢

//       MessageBox(str);

     }

}

void C试验品View::OnButton2Clicked()

{

     std::vector::iterator ir;

     std::map t;

     int d,k;

     if(current_player==1)

     {

         ir=vec1.begin();

         d=*ir;

         k=std::count(vec1.begin(),vec1.end(),d);

         if(k==1)

         {

              vcc.clear();

              vcc.push_back(d);

              vec1.erase(ir);

              t.insert(std::map::value_type(k,1));

             Brand_size.clear();

             Brand_size.insert(std::map,int>::value_type(t,d));

         }

         if(k>=2)

         {

              vcc.clear();

              vcc.push_back(d);

              vcc.push_back(d);

              ir=vec1.erase(ir);

              vec1.erase(ir);

              t.insert(std::map::value_type(2,1));

             Brand_size.clear();

             Brand_size.insert(std::map,int>::value_type(t,d));

         }

     }

     if(current_player==2)

     {

         ir=vec2.begin();

         d=*ir;

         k=std::count(vec2.begin(),vec2.end(),d);

         if(k==1)

         {

              vcc.clear();

              vcc.push_back(d);

              vec2.erase(ir,ir+1);

              t.insert(std::map::value_type(k,1));

             Brand_size.clear();

             Brand_size.insert(std::map,int>::value_type(t,d));

         }

         if(k>=2)

         {

              vcc.clear();

              vcc.push_back(d);

              vcc.push_back(d);

              ir=vec2.erase(ir,ir+2);

//            vec2.erase(ir);

              t.insert(std::map::value_type(2,1));

             Brand_size.clear();

             Brand_size.insert(std::map,int>::value_type(t,d));

         }

     }

}

// 得到连续的牌号(与order的区别在于,order只是判断所给的数据是不是符合,而这个函数则是找遍关联器直到找到或者都找完为止)

int C试验品View::continuation(std::multimap mmp, int d, int k, int wc)

{//得到连续的牌号(与order的区别在于,order只是判断所给的数据是不是符合,而这个函数则是找遍关联器直到找到或者都找完为止)

     int n=1,i;//n是用来记录iter运行到哪个数,用在判断剩下的数够不够再进行一次循环判断

     std::multimap::iterator iter=mmp.begin();

     std::multimap m;

     int j=0;

     int initial_number=0;

     for(i=0;i

     {

         if(iter->first>d)

              break;

         n++;

         iter++;//当iter->first

     }

     if(i==mmp.size())//找不到跳出

         return 0;

     while(1)

     {

         if((mmp.size()-n+1/*加一是因为每次都是在上次不能连续点开始的,所以剩下的数必须加上原来的一个点*/)

              break;

         initial_number=iter->first;//作为开始点

//       if(initial_number>10)//当开始点大于时会出现,但是(即对应的)是不能出现的

//            return 0;

         m.clear();//每次都要把存储判断数组清零

         for(j=iter->first;jfirst+k;j++)

         {

              m.insert(std::multimap::value_type(j,j));

         }//组建判断数组,iter无法加k,只能重载自加运算符

         int cnt=0;

         std::multimap::iterator it=m.begin();

         while(/*(++iter)!=m.end()&&*/mmp.find(it->first)/*得到对应键*/!=mmp.end())//判断数据是否连续

         {/*得到iter++,每次都指向下一个,必须在前面,因为it不符合时,必须跳过,但是iter必须是下一个*/

              iter++;

//            if(iter==m.end())//为什么无法这样呢,无法用m.end()与之相等

//                 break;

              if(wc>mmp.find(it->first)->second)//有这个判断,可以得到连续的双或者三

              {

                   iter++;//本意是指向下一个(因为原来有加,但是后来下面又减了,所以要加,

                   n++;//指向下一个

                   break;

              }

              ++cnt;

             ++it;

              n++;//每次都指向下一个

             if(cnt==k)//记录,是否连续的关键

                   return initial_number;

         }

         iter--;//加上这个是因为,当出现不符合。find()时,iter还是会加一,也就是在不连续点的下一个点,所以需要返回到不连续点处

     }

     return 0;

}

// //删去下一次出牌方下的牌,与continuation()连用,分别是判断(上面只是判断连续的方面),取牌initial_number/*开始的牌号*/,continuation_number/*连续量*/,suit_patterns/*是双是单还是三,四的*/

void C试验品View::Choose_Brand(std::vector & vc,std::vector & c,int initial_number/*开始的牌号*/,int continuation_number/*连续量*/,int suit_patterns/*是双是单还是三,四的*/)

{

     //删去下一次出牌方下的牌,与continuation()连用,分别是判断(上面只是判断连续的方面),取牌

     int d=initial_number,i;

     for(i=0;i

     {

         std::vector::iterator iter=std::find(vc.begin(),vc.end(),initial_number++);

         for(int j=0;j

         {

              c.push_back(*iter);

              iter=vc.erase(iter);

         }

     }

}

// 拆分关联器,得到需要的部分用于操作,注意这里输入的要是以牌数为键值的pm因为只有以牌数为键值的在后面才是牌数最多的牌号

std::multimap C试验品View::split(std::multimap pmm, int k)

{

     std::multimap::iterator iter=pmm.begin();

     for(int i=0;i

         iter++;

//   iter=iter+1;  multimap的迭代器不能使用加减号,只能自增自减

//   iter=iter+k-1;

     std::multimap m;

     do

     {

         m.insert(std::multimap::value_type(iter->second,iter->first));

//输出时是按照牌号为键值的,所以需要倒过来

         iter++;

     }while(iter!=pmm.end());

     return m;

}

// //判断不重复后的牌组,是否连续

int C试验品View::order(std::multimap mmp)

{

     int i;

     std::multimap m;

     std::multimap::iterator iter=mmp.begin();

     for(i=iter->first;ifirst+mmp.size();i++)

     {

         m.insert(std::multimap::value_type(i,i));

     }

     int cnt=0;

     std::multimap::iterator it=m.begin();

     while(mmp.find(it->first)/*得到对应键*/!=mmp.end())//判断数据是否连续

     {

         ++cnt;

         ++it;

         if(cnt==mmp.size())

              return iter->first;

     }

     return 0;

}

// 得到所出牌的multimap形式,需要multimap,因为在pm中键值需要重复,输入后,自动按键值排序

void C试验品View::transition(std::multimap & mp,std::multimap & pm,std::vector & vec)

{

     int i;

     for(std::vector::iterator iter=vec.begin();iter!=vec.end();iter+=i/*跳到下一个与该数不相等的数的迭代器上*/)

     {

         i=count(vec.begin(),vec.end(),*iter);//count不是容器等专有函数,而是泛型函数,返回的是对应数目

         mp.insert(std::multimap::value_type(*iter,i));//第一个数是牌,第二是数目

         pm.insert(std::multimap::value_type(i,*iter));//与上面相反,两个相反是为了得到数目(下面)为基的排序与牌号(上面的)为基的排序

     }//得到牌号及对应数目(此时,不会有牌号相同的情况

}

// 判断点击输出的值是否正确,获得当前所下的牌型,用Brand_size存储

void C试验品View::judge_game(std::multimap mp, std::multimap pm,std::vector vec)//炸弹无法判断

{

     std::multimap m1;

     std::vector::size_type vec_s=vec.size();

     int j;

     std::multimap::reverse_iterator riter=pm.rbegin();

//反向迭代器,得到后起第一个,即键值最大的,此时关联器是pm,为最大的牌数值对应的迭代器

     int wc=riter->first;//得到最大的牌数(同一种牌号)

     j=pm.count(wc);//得到了最大数目的次数(同一数目多少种牌号)

     int n=mp.size();//得到不重复牌数目

    

//   cout<

     if(Brand_size.begin()!=Brand_size.end())

         Brand_size.erase(Brand_size.begin());

     int magnitude=0;

//表示牌的大小,其中,-》,2-》,注意,内在的不会出现,2(只有界面才是)内在的用,15表示

    switch(wc)//判断牌型

     {

     case 1:

         if(n<5)

         {

              if(n==1)

                   magnitude=mp.begin()->first;//单只牌

              if(n==2)

              {

                   if((mp.begin())->first==53&&(mp.rbegin())->first==54)//两张大王时

                   {

                       magnitude=-1;//避过Brand_size的赋值行为

                       std::map t;

                       t.insert(std::map::value_type(100,100));

                       Brand_size.insert(std::map,int>::value_type(t,100));

                   }

              }

         }

         else

              magnitude=order(mp);//单顺时的情况

         if(n!=2&&magnitude!=0)//当牌型符合规则

         {

              std::map t;

              t.insert(std::map::value_type(1,n));

              Brand_size.insert(std::map,int>::value_type(t,magnitude));

         }

         else//不合规则

         {

              std::map t;

              t.insert(std::map::value_type(0,0));

              Brand_size.insert(std::map,int>::value_type(t,0));

//Brand_size三个参数分别代表着,最多数目量,有多少不同牌(只有最大为单时第二个参数才代表这个)(这两个用来判断牌型),最后一个为大小(一般结合第二个数判断)

         }                                                            

//其中不符合规则的牌型为三0,最大为三100(鬼炸)

         break;

     case 2:

         if(j==1&&n==1)//一双对的情况

         {

              magnitude=mp.begin()->first;//这里面的赋值可以考虑用函数,或类

              std::map t;

              t.insert(std::map::value_type(2,1));

              Brand_size.insert(std::map,int>::value_type(t,magnitude));

         }

         if(j>2&&n==j/*都是对的情况*/&&(magnitude=order(mp))!=0)

//此时已经判断了n==j,所以不用拆分mp直接可以判断是否连续

         {

              std::map t;

              t.insert(std::map::value_type(2,j));

              Brand_size.insert(std::map,int>::value_type(t,magnitude));

         }

         if(magnitude==0)

         {

              std::map t;

              t.insert(std::map::value_type(0,0));

              Brand_size.insert(std::map,int>::value_type(t,0));

         }

         break;

     case 3:

         m1=split(pm,n-j);//拆分关联器用以判断连续

         if(n==j&&(magnitude=order(mp))!=0)//单独三条或连续三条的情况

         {

              std::map t;

              t.insert(std::map::value_type(3,j));

              Brand_size.insert(std::map,int>::value_type(t,magnitude));

         }

         if(n<=2*j/*"<="的情况与case4的相同*/&&(magnitude=order(m1))!=0)

//三带的情况,此时,因为要判断连续的情况,又有单的情况,所以需要拆分

         {

              if(pm.count(1)==j||(vec_s-3*j)==j)//三带一,含连续带

              {

                   std::map t;

                   int d=j*10+1;

                   t.insert(std::map::value_type(3,d));

                   Brand_size.insert(std::map,int>::value_type(t,magnitude));

              }

              if(pm.count(2)==j)//三带二,含连续带

              {

                   std::map t;

                   int d=j*10+2;

                   t.insert(std::map::value_type(3,d));

                   Brand_size.insert(std::map,int>::value_type(t,magnitude));

              }

         }

         if(magnitude==0)

         {

              std::map t;

              t.insert(std::map::value_type(0,0));

              Brand_size.insert(std::map,int>::value_type(t,0));

         }

         break;

     case 4:

         m1=split(pm,n-j);

//拆分出部分是因为在使用order()函数时,无法单独判断最多数目的牌号间是否顺序,需要拆分出来

         if(n==1)//炸弹的情况

         {

              magnitude=mp.begin()->first;

              std::map t;

              t.insert(std::map::value_type(4,4));

              Brand_size.insert(std::map,int>::value_type(t,magnitude));

         }

         if(n<=3*j/*用"<="是因为也可能出现四带二个单时,单之间可能相同的情况*/&&(magnitude=order(m1))!=0)

         {

              if(pm.count(1)==2*j||(vec_s-4*j)==2*j/*即剩下牌的数目刚好是张的牌号的牌数(不重复,即除以)的两倍,即四带二个单,第二种情况是因为可能出现单的中有相同的牌*/)

              {

                   std::map t;

                   int d=j*10+1;//乘以+1,是为了区分四带二个双的情况

                   t.insert(std::map::value_type(4,d));

                   Brand_size.insert(std::map,int>::value_type(t,magnitude));

              }

              if(pm.count(2)==2*j)//四带二个双

              {

                   std::map t;

                   int d=j*10+2;

                   t.insert(std::map::value_type(4,d));

                   Brand_size.insert(std::map,int>::value_type(t,magnitude));

              }

              if((vec_s-4*j)!=2*j)

//这种情况是因为前面把magnitude已经赋值,但是剩余的牌又不符合规则,需要重新把magnitude赋

                   magnitude=0;

         }

         if(magnitude==0)

         {

              std::map t;

              t.insert(std::map::value_type(0,0));

              Brand_size.insert(std::map,int>::value_type(t,0));

         }

         break;

     default:

         break;

     }

}

// 在对应的牌组里面找出该下的牌

int C试验品View::machine(std::vector &vec,std::multimap mp,std::multimap pm)

{

     std::map m_b=Brand_size.begin()->first;

     int m_n=Brand_size.begin()->second;

     int o_n=m_b.begin()->first;

     int t_n=m_b.begin()->second;

     int d,b=0,k,l,q,r;

     switch(o_n)

     {

     case 1:

         if(t_n==1)

         {       

              d=continuation(mp,m_n,1,1);

             b=seek_max(mp,d,1);

         }

         else

         {

              b=continuation(mp,m_n,t_n,1);

         }

         if(b==0)

              break;

         Choose_Brand(vec,vcc,b,t_n,1);

         break;

     case 2:

         if(t_n==1)

         {

              d=continuation(mp,m_n,1,2);

              b=seek_max(mp,d,2);

         }

         else

         {

              b=continuation(mp,m_n,t_n,2);

         }

         if(b==0)

              break;

         Choose_Brand(vec,vcc,b,t_n,2);

         break;

     case 3:

         if(t_n<10)

         {

              d=continuation(mp,m_n,t_n,3);

              b=d;

            if(b==0)

                   break;

              Choose_Brand(vec,vcc,b,t_n,3);

         }

         else

         {

              if((t_n%10)==1)

              {

                   if((t_n-10)==1)

                   {

                       d=continuation(mp,m_n,1,3);

                       b=d;

                       int k=pm.find(1)->second;

                       if(k==0)

                       {

                            k=pm.find(2)->second;

                       }

                       if(b==0)

                            break;

                       Choose_Brand(vec,vcc,b,t_n,3);

                       Choose_Brand(vec,vcc,k,1,1);

                   }

                   if((t_n-20)==1)

                   {

                       d=continuation(mp,m_n,2,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(1)->second;

                       if(k==0)

                       {

                            k=pm.find(2)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,1);

                       int l=pm.find(1)->second;

                       if(l==0)

                       {

                            l=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,1);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

                  

                   if((t_n-30)==1)

                   {

                       d=continuation(mp,m_n,3,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(1)->second;

                       if(k==0)

                       {

                            k=pm.find(2)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,1);

                       l=pm.find(1)->second;

                       if(l==0)

                       {

                            l=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,1);

                       int q=pm.find(1)->second;

                       if(q==0)

                       {

                            q=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,q,1,1);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

                  

                   if((t_n-40)==1)

                   {

                       d=continuation(mp,m_n,3,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(1)->second;

                       if(k==0)

                       {

                            k=pm.find(2)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,1);

                       l=pm.find(1)->second;

                       if(l==0)

                       {

                            l=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,1);

                       q=pm.find(1)->second;

                       if(q==0)

                       {

                            q=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,q,1,1);

                    

                       int r=pm.find(1)->second;

                       if(r==0)

                       {

                            r=pm.find(2)->second;

                       }   

                       Choose_Brand(vec,vcc,r,1,1);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

              }

              else

              {

                   if((t_n-10)==2)

                   {

                       d=continuation(mp,m_n,1,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(2)->second;

                       if(k==0)

                       {

                            k=pm.find(3)->second;

                       }

                       Choose_Brand(vec,vcc,b,t_n,3);

                       Choose_Brand(vec,vcc,k,1,2);

                   }

                   if((t_n-20)==2)

                   {

                       d=continuation(mp,m_n,2,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(2)->second;

                       if(k==0)

                       {

                            k=pm.find(2)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,2);

                       l=pm.find(2)->second;

                       if(l==0)

                       {

                            l=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,2);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

                   if((t_n-30)==2)

                   {

                       d=continuation(mp,m_n,3,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(2)->second;

                       if(k==0)

                       {

                            k=pm.find(3)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,2);

                       l=pm.find(2)->second;

                       if(l==0)

                       {

                            l=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,2);

                       q=pm.find(2)->second;

                       if(q==0)

                       {

                            q=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,q,1,2);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

                   if((t_n-40)==2)

                   {

                       d=continuation(mp,m_n,3,3);

                       b=d;

                       if(b==0)

                            break;

                       k=pm.find(2)->second;

                       if(k==0)

                       {

                            k=pm.find(3)->second;

                       }

                       Choose_Brand(vec,vcc,k,1,2);

                       l=pm.find(2)->second;

                       if(l==0)

                       {

                            l=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,l,1,2);

                       q=pm.find(2)->second;

                       if(q==0)

                       {

                            q=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,q,1,2);

                   

                       r=pm.find(2)->second;

                       if(r==0)

                       {

                            r=pm.find(3)->second;

                       }   

                       Choose_Brand(vec,vcc,r,1,2);

                       Choose_Brand(vec,vcc,b,t_n,3);

                   }

              }

         }

         break;

     case 4:

         b=0;

         break;

     }

     if(b==0&&o_n!=4)

     {

         std::multimap::iterator iter_1,iter_2,iter_3;;

         iter_1=pm.find(4);

         iter_2=mp.find(53);

         iter_3=mp.find(54);

         if(iter_1!=pm.end())

         {

              Choose_Brand(vec,vcc,iter_1->second,1,4);

         }

         else if(iter_2!=mp.end()&&iter_3!=mp.end())

         {

              Choose_Brand(vec,vcc,53,1,1);

              Choose_Brand(vec,vcc,54,1,1);

         }

         else

         {

五.  课程设计总结(包括程序中遇到的问题及解决方案,以及课程设计收获)

总结:

1.  问题:选择什么语言

解决: C++ MFC

2.  问题: MFC的结构是怎样的

   解决:孙鑫的视频教程和相关书籍

3.  问题:具体AI是怎么样的,所想的是否不足

解决:网上查询

4.  问题:具体游戏框架怎么样

解决:分类思考,分成AI和 图片显示(由于视野所限,只有这些)

5.  问题:怎么在窗口中显示图片

解决:网上查询和书籍查询(得到StretchBlt函数)

6.  问题:图片的动态效果(即弹起,出牌等等)

解决:添加参数(在确定按钮中进行改变),用来判断是否进行改变,切换到另外的图片显示上

7.  问题:怎么判断是否出牌

解决:添加两个按钮,进行相关操作

8.  问题:怎么判断哪个牌需要弹起

解决:分割出一定区域,以矩形作为区域大小,同时,添加鼠标点击的响应函数,判断出所点击区域说在矩形区域,从而得到所对应的牌

9.  问题:如何显示机器玩家的出牌

解决:添加相关参数用来判断哪方出牌

问题:(由于时间的原因无法解决的问题)

1.  当玩家这一方出牌时,有时候不知道为什么出现系统错误,至今无法解决

2.  图片的分辨率问题,即在桌面上显示不好,同时,本来想要固定显示的窗口大小的,问题仍然无法解决

3.  怎么让所出的牌旋转45度(网上有相关的资料,可惜不懂)

4.  机器放的智能无法达到预期效果,好像(尚未调式)无法出三张以上,同时,AI方面不足,需要时间

5.  窗口的样式需要改变,由于时间和知识不牢固,无法解决

收获:

1.  了解了MFC得编程形式

2.  明白了做游戏的辛苦,大致明白游戏到底是怎么出现的

3.  学会了MFC的图片显示

4.  学会了坚持(本来由于时间和各方面压力的问题,无法完成的)

5.  巩固了C++的相关知识,但是还有很多不足,思想形式无法从C语言上转变过来

相关推荐