中国传统象棋游戏(DLUT)

不管怎么想还是觉得第一篇技术博客就要记录这个第一个项目

估计很多年以后我一定会觉得这个项目幼稚 繁琐 这篇博客好丑 没有条理

但是至少啊 现在的我很自豪呐 暗戳戳地感谢布置大作业于红老师QwQ

——————————————————————————————————

进入正题 

数据结构设计

1.设置两个全局变量数组:显示棋盘chessboard、基类指针棋盘 board。

#两个棋盘的设置是该程序的重点之处,利用一个基类指针数组和显示棋盘数组保持一致,通过调用基类指针完成动态多态,找到需要操作的棋子。

2.设置一个抽象棋子类和七个派生的棋子类。

//棋盘:一个负责显示,一个是基类指针负责对象的操作,两者对应位置保持一致
char chessboard[11][10];
Piece* board[11][10];
//基类棋子:抽象类
class Piece
{
public:
   int flag;                                                 //用于判断棋子颜色以及后续操作
   virtual int p_sign(int x1,int y1,int x2,int y2)=0;        //检验棋子能否移动到制定点
   virtual void p_move(int x1,int y1,int x2,int y2)=0;       //进行后台移动操作
};

棋子的判断与移动

棋子根据走法相似性和规则局限性分为:将和士,车和炮,马和象,兵

共性:每个棋子的移动都要经过p_sign函数的判断,根据返回值sign ,告知是否会吃掉对方的子。并且移动时要注意两个棋盘同时移动。

棋子特点:将和士不能离开九宫格 将要用于胜负判断 马和象行走距离固定 兵只走一格 方向与其所处位置有关 车和炮走直 

由此可见,棋子差异主要体现在判断函数上,其他都可以 ctrl c +v解决。

ps:通过flag以及字母大小写判断红黑双方

以将为例

class King:public Piece                          //继承自基类(棋子抽象类)
{
public:
     int x,y;
     King(int f,int xx,int yy){flag=f;x=xx;y=yy;}      //构造函数
     int p_sign(int x1,int y1,int x2,int y2);
     void p_move(int x1,int y1,int x2,int y2);
};
int King::p_sign(int x1,int y1,int x2,int y2)
{
    int sign=0;
    int dis;                                           //确定用户移动棋子距离 便于用数学知识排除错误情况
    dis=pow((x2-x1),2)+pow((y2-y1),2); 
     if(dis!=1)   return sign;                         //保证只走一步
    if(flag)
    {
       if(x2>10||y2<4||y2>6||x2<8)                     //保证在九宫格内
            return sign;
       if((chessboard[x2][y2]<90)||(chessboard[x2][y2]=='*'))                  //吃掉敌方棋子或移动
            sign=1;
    }
    if(!flag)
    {
        if(x2>3||y2<4||y2>6||x2<1)                  //保证在九宫格内
            return sign;
        if((chessboard[x2][y2]>90)||(chessboard[x2][y2]=='*'))                  //吃掉敌方棋子或移动
            sign=1;
    }
    return sign;
}  void King::p_move(int x1,int y1,int x2,int y2)
{
    //时刻监控将和帅的位置以便判断胜负
    if(p_sign(x1,y1,x2,y2)!=0)
    {
         x=x2; y=y2;
        board[x1][y1]=NULL;
        board[x2][y2]=this;
    }
    if(flag)
    {
      if(p_sign(x1,y1,x2,y2)!=0)            //吃子或者移动
      {
        chessboard[x2][y2]='k';
        chessboard[x1][y1]='*';
      }
    }
    if(!flag)
    {
      if(p_sign(x1,y1,x2,y2)!=0)            //吃子或者移动
      {
        chessboard[x2][y2]='K';
        chessboard[x1][y1]='*';
      }
    }
}

打印棋盘与棋盘美化

#使用windows头文件 改变控制台所显示的字体颜色

 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE);

FOREGROUND代表前景色 BACKGROUND则是背景色

#清屏函数(#include <stdlib.h>)随时更新棋盘 不造成丑陋的堆积

   system("cls"); 
//将字符数组中的英文转换成汉字
void printchinese(int i,int j)
{
    //设置颜色
    char ch=chessboard[i][j];
    if(chessboard[i][j]>90)
      SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE);
    if(chessboard[i][j]>65&&chessboard[i][j]<90)
      SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_RED);
    if(chessboard[i][j]=='*'||(chessboard[i][j]>=48&&chessboard[i][j]<=57))
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
    switch(ch)
    {
  case 'A':
    cout<<setw(2)<<"10";
    break;
  case 'K':
    cout<<"将";
    break;
  case 'C':
    cout<<"炮";
    break;
  case 'T':
    cout<<"车";
    break;
  case 'E':
    cout<<"象";
    break;
  case 'M':
    cout<<"相";
    break;
  case 'P':
    cout<<"兵";
    break;
  case 'k':
    cout<<"帅";
    break;
  case 'm':
    cout<<"士";
    break;
  case 'c':
    cout<<"炮";
    break;
  case 't':
    cout<<"车";
    break;
  case 'p':
    cout<<"卒";
    break;
  case 'e':
    cout<<"象";
    break;
  case 'H':
    cout<<"马";
    break;
  case 'h':
    cout<<"马";
    break;
  default:
    cout<<setw(2)<<chessboard[i][j];
    }
}
//打印棋盘
void printchess()
{
    system("cls");              //清屏
    for (int i =0; i < 6; i++){
    for (int j = 0; j < 10; j++){
      printchinese(i,j);
      cout<< (j == 9 ? "\n\n" : "    ");}}
      for(int k=0;k<57;k++)
          cout<<"-";
      cout<<endl;
      for(int k=0;k<27;k++)
      {
          cout<<" ";
          if(k==18 )
          cout<<"楚  汉  之   隔";
      }
      cout<<endl;
      for(int k=0;k<57;k++)
          cout<<"-";
      cout<<endl;
    for (int i =6; i < 11; i++)
        {
          for (int j = 0; j < 10; j++){
          printchinese(i,j);
          cout<< (j == 9 ? "\n\n" : "    ");}
        }
}

胜负判断函数

两种情况:一是一方将或帅被吃掉 或是两将碰面

//为了监控胜负 把将设为全局变量
    King R_King(0,1,5),B_King(1,10,5);
//判断胜负来决定是否继续循环
    bool judge()
{
        bool j=true;
        int cont=0;
        if(chessboard[R_King.x][R_King.y]!='K'||chessboard[B_King.x][B_King.y]!='k')
        {
            j=false;
            return j;
        }
        if(R_King.y==B_King.y)
        {
            for(int k=R_King.x+1;k<B_King.x;k++)
            {
                if(chessboard[k][B_King.y]!='*')
                {
                  cont++;
                }
        }
        if(cont==0)//证明两将之间没有棋子
        {
             j=false;
        }
    }
     return j;
}

对战主体部分

   while(judge()&&choice!=0)
 {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
   cout<<"红方执棋,请输入棋子目前位置,以及终止位置"<<endl;
   cin>>x1>>y1>>x2>>y2;
    while(chessboard[x1][y1]=='*'||board[x1][y1]->p_sign(x1,y1,x2,y2)==0||board[x1][y1]->flag==1)
   {
       cout<<"操作不符合规则,重新输入。"<<endl;
       cout<<"红方执棋,请输入棋子目前位置,以及终止位置"<<endl;
       cin>>x1>>y1>>x2>>y2;
   }
   board[x1][y1]->p_move(x1,y1,x2,y2);
   choice=1;//证明红方操作
   printchess();
   if(!judge())   break;
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
   cout<<"黑方执棋,请输入棋子目前位置,以及终止位置"<<endl;
   cin>>x1>>y1>>x2>>y2;
   while(chessboard[x1][y1]=='*'||board[x1][y1]->p_sign(x1,y1,x2,y2)==0||board[x1][y1]->flag==0)
   {
       SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
       cout<<"操作不符合规则,重新输入。"<<endl;
       cout<<"黑方执棋,请输入棋子目前位置,以及终止位置"<<endl;
       cin>>x1>>y1>>x2>>y2;
   }
   board[x1][y1]->p_move(x1,y1,x2,y2);
   choice=2;
   printchess();
   SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
   cout<<"人工中止请输入0,继续则输入任意非零整数"<<endl;
   cin>>choice;
  }
   if(!judge())
   {
       SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
       cout<<"胜负已分!"<<endl;
       if(chessboard[R_King.x][R_King.y]!='K')
         cout<<"黑方胜"<<endl;
       if(chessboard[B_King.x][B_King.y]!='k')
         cout<<"红方胜"<<endl;
       else
        {
         if(choice==1)    cout<<"两将碰面,黑方胜"<<endl;
         if(choice==2)    cout<<"两将碰面,红方胜"<<endl;
        }
   }

整个项目对应的流程图




猜你喜欢

转载自blog.csdn.net/qq_40070622/article/details/80873685