AI----------五子棋

一. 项目背景
1. 项目任务
编写人机对弈的五子棋游戏
2. 项目功能
1) 人机交互下子
2) 电脑有一定的防御能力
3) 用户可以任意终止游戏或重新开始
4) 可以判断双方的输赢
3. 运行条件
Windows 98/XP
Visual C++  6.0

二. 项目实现
1. 算法
1)要完成该游戏首先要解决显示问题,因此定义一棋盘类。该类中应包括棋盘信息,判断
   输赢的函数,电脑完成计算的函数,以及游戏终止的函数。定义的棋盘类如下:
      class  Qipan
{public:
           char Qizi[9][9];//棋盘信息
           char C_Weizi[2];//存放电脑要下的棋子坐标
     
           void QipanInitialize();//对棋盘初始化
          ~Qipan();
           void Qipan::ShowMe();//显示棋盘
           bool Qipan::Check();//判断棋盘是否已下满
           void C_Qizi(int i0,int j0);//电脑计算出要下的坐标
           bool Win_lose(char a,int i0,int j0);//判断输赢
};
用Qizi[9][9]来存放各位置的棋子信息(未下的为*,电脑的为1,用户的为0),用户输入要下棋子坐标
   后,电脑根据用户刚下的位置计算自己要下的位置,用伪代码描述为:
1) 获得用户刚下的位置坐标i0,j0
2) 在I0,J0所在的行和列分别查找用户的棋子个数sum_line,sum_row
3) if(sum_row>=sum_line)
{
   从I0,J0开始向左查找相连的子;
if(没有空位)
{再从I0,J0向又查找;
   if(没有空位)
    { 从该位置向右查找空位;
      保存该位置到C_Weizi[2];
}
else
{保存该位置到C_Weizi[2];}
}
else
{保存该位置到C_Weizi[2];}
}
else
{
   仿造上述方法在列中查找;
    找到后保存该位置到C_Weizi[2];
}
    电脑根据计算所得的坐标下子。

2)主函数的流程:
     初始化棋盘;
     显示棋盘;
while(棋盘未下满)
{   用户输入要下的位置i0,j0;
    根据i0,j0的值执行相应的功能;
    判断是否赢了;
    if(赢)
    {break;}
    else
    {电脑计算并下子;
      判断是否赢了;
}

2. 程序
    
#include <iostream.h>
//定义棋盘类
class  Qipan
{public:
   char Qizi[9][9];//棋盘信息
   char C_Weizi[2];//存放电脑要下的棋子坐标
  
   void QipanInitialize();//对棋盘初始化
  ~Qipan();
   void Qipan::ShowMe();//显示棋盘
   bool Qipan::Check();//判断棋盘是否已下满
   void C_Qizi(int i0,int j0);//电脑计算出要下的坐标
   bool Win_lose(char a,int i0,int j0);//判断输赢
};
//定义棋盘初始化函数
void Qipan::QipanInitialize()
{    
  for(int i=0;i<=8;i++)
 {for(int j=0;j<=8;j++)
   Qizi[i][j]='*';
 }
}
//定义解构函数
Qipan::~Qipan()
{cout<<endl<<"欢迎下次再玩!"<<endl<<endl;}
//定义显示函数
void Qipan::ShowMe()
{
 for(int i=0;i<=8;i++)
 {
  switch(i)
  {  
     case 2:
      {
       for(int j=0;j<=8;j++)
       {  if(j==8) 
               cout<<Qizi[i][j]<<"      "<<"SIGO五子棋说明:"<<endl<<endl;
                      else     
            cout<<Qizi[i][j]<<"    ";
       }
          break;
      }
     case 3:
      {
          for(int j=0;j<=8;j++)
       {  if(j==8) 
               cout<<Qizi[i][j]<<"          "<<"1)你的棋子为0,电脑的棋子为1"<<endl<<endl;
                      else     
            cout<<Qizi[i][j]<<"    ";
       }
          break;
      }
   
     case 4:
    
    {
     for(int j=0;j<=8;j++)
     {  if(j==8) 
                cout<<Qizi[i][j]<<"          "<<"2)你只须键入你要下的棋子坐标"<<endl<<endl;
                       else     
             cout<<Qizi[i][j]<<"    ";
     }
        break;
    }
    
     case 5:
    {
     for(int j=0;j<=8;j++)
     {  if(j==8) 
                cout<<Qizi[i][j]<<"          "<<"3)重新开始请输入-1,-1"<<endl<<endl;
                       else     
             cout<<Qizi[i][j]<<"    ";
     }
       break;
    }
     case 6:
    {
     for(int j=0;j<=8;j++)
     {  if(j==8) 
                cout<<Qizi[i][j]<<"          "<<"4)结束游戏请输入0,0"<<endl<<endl;
                       else     
             cout<<Qizi[i][j]<<"    ";
     }
       break;
    }
     default:
      {
     for(int j=0;j<=8;j++)
     {  if(j==8) 
                cout<<Qizi[i][j]<<endl<<endl;
                       else     
             cout<<Qizi[i][j]<<"    ";
      }
    }
  }
 }
}

//判断是否棋盘已下满  
bool Qipan::Check()
{
 for(int i=0;i<=8;i++)
 {
  for(int j=0;j<=8;j++)
  {
   if(Qizi[i][j]=='*')
      return true;
  }
 }
   return false; 
}
//电脑计算要下的子坐标并保存
void Qipan::C_Qizi(int i0,int j0)
{  
   int sum_line=0,sum_row=0;
   for(int i=0;i<=8;i++)
   {if(Qizi[i][j0]=='0')
    sum_line++;
   }
   for(int j=0;j<=8;j++)
   {if(Qizi[i0][j]=='0')
    sum_row++;
   }                 //比较横行和纵行上人的棋子个数
  
   if(sum_row>=sum_line)
   {
  j=j0;
     while(Qizi[i0][j]=='0'&&j>=0)
   j--;
  if(j<0||Qizi[i0][j]=='1')
  {
   j=j0;
      while(Qizi[i0][j]=='0'&&j<=8)
  j++;
     if(Qizi[i0][j]=='1')
  {
       j=j0;
    while((Qizi[i0][j]=='1'||Qizi[i0][j]=='0')&&j<=8)
          j++;
    C_Weizi[0]=i0;//存放要下的位置坐标
       C_Weizi[1]=j;
  }
     else
  {C_Weizi[0]=i0;//存放要下的位置坐标
      C_Weizi[1]=j;
  }
  }
  else
     {C_Weizi[0]=i0;//存放要下的位置坐标
      C_Weizi[1]=j;
  }
   }
    
 
   //如果纵行人的棋子较多
   else
   {//从人刚下的位置往上检验相连的子
  i=i0;
     while(Qizi[i][j0]=='0'&&i>=0)
  i--;
 
  if(i<0||Qizi[i][j0]=='1')
  { i=i0;
    while(Qizi[i][j0]=='0'&&i<=8)
     i++;
       if(Qizi[i][j0]=='1')
    {
     while((Qizi[i][j0]=='0'||Qizi[i][j0]=='1')&&i<=8)
      i++;
            C_Weizi[0]=i;
            C_Weizi[1]=j0;
    }
       else
    {C_Weizi[0]=i;
        C_Weizi[1]=j0;
    }
  }
  else
  { C_Weizi[0]=i;
    C_Weizi[1]=j0;
  }
   }


    
    //判断输赢(可以对人和电脑判断)
bool Qipan::Win_lose(char a,int i0,int j0)
{   int i=i0-1;int j=j0-1;
    int sum_line=0,sum_row=0,sum_xie1=0,sum_xie2=0;
   
 while(Qizi[i][j0]==a&&i>=0)
      i--;
    i+=1;
 while(Qizi[i][j0]==a)
 {
  sum_line++;
  i++;
 }
 if(sum_line==5) return  true;//判断纵行是否满足
 
    while(Qizi[i0][j]==a&&j>=0)
  j--;
  j+=1;

 while(Qizi[i0][j]==a)
 {sum_row++;
     j++;
 }
 if(sum_row==5)  return true;//判断横行是否满足
    
 i=i0-1;j=j0-1;
    while(Qizi[i][j]==a&&i>=0&&j>=0)
 {i--;j--;}
 i+=1;
 j+=1;
 while(Qizi[i][j]==a)
  {sum_xie1++;i++;j++;}
 if(sum_xie1==5) return true;//判断斜行是否满足
 
 i=i0-1;j=j0+1;
 while(Qizi[i][j]==a&&i>=0&&j>=0)
 {i--;j++;}
 i+=1;j-=1;
 while(Qizi[i][j]==a)
 {sum_xie2++;i++;j--;}
 if(sum_xie2==5) return true;//判断另一斜行是否满足

    return false;
}

  
//主函数
void main()
{
 Qipan qipan1;
 qipan1.QipanInitialize();//初始化棋盘
 
 int i=1,j=1;
 
 while(qipan1.Check())//当棋盘全部下满时停止游戏
 {
  qipan1.ShowMe();
     if(qipan1.Win_lose('1',i-1,j-1))//判断电脑是否赢了
   {
    cout<<"你输了!!"<<endl<<endl;
          break;
   }
  else
  {
     cout<<"输入棋子位置:";
        cin>>i>>j;
     if(i==0&&j==0)
     {break;}
     else 
     {
   if(i==-1&&j==-1)
    {
     qipan1.QipanInitialize();
        qipan1.ShowMe();
     cout<<"输入棋子位置:";//刷新之后重新开始
              cin>>i>>j;
        qipan1.Qizi[i-1][j-1]='0';
           
        if(qipan1.Win_lose('0',i-1,j-1))
     {
       cout<<"你赢了!!"<<endl<<endl;
                   break;
     }
        else
     {//电脑完成计算
          qipan1.C_Qizi(i-1,j-1);
          qipan1.Qizi[qipan1.C_Weizi[0]][qipan1.C_Weizi[1]]='1';
     }
    }
    else
             {    //输入的坐标必须满足条件
     while(i<=0||i>9||j<=0||j>9||qipan1.Qizi[i-1][j-1]=='0'||
      qipan1.Qizi[i-1][j-1]=='1')
     {
          cout<<"请重新输入:";
          cin>>i>>j;
     }
       
     qipan1.Qizi[i-1][j-1]='0';
                 //判断人是否赢了
        if(qipan1.Win_lose('0',i-1,j-1))
     {
       cout<<"你赢了!!"<<endl<<endl;
             break;
     }
        else
     {//电脑完成计算
          qipan1.C_Qizi(i-1,j-1);
          qipan1.Qizi[qipan1.C_Weizi[0]][qipan1.C_Weizi[1]]='1';
     }
    }
     }
  }
 }
}

三. 项目总结
1) 编写类的多个成员函数时应该逐个编写并检验,否则出错的话很难查找。
2) 一个程序的关键部分是算法,让电脑做一件就要为它编制相应的算法。
3) 编写程序时应该考虑到所有的可能性,并给出相应的处理方法。
4) 逐步求精。例如当编写电脑计算如何下子的函数时,先实现一些比较简单的功能,让它可以给出一个
没有下过子的位置,然后检验该函数,成功的话,就说明该函数的接口是可行的,然后只须再改进该、
函数即可,增强它的功能。   
   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值