不管怎么想还是觉得第一篇技术博客就要记录这个第一个项目
估计很多年以后我一定会觉得这个项目幼稚 繁琐 这篇博客好丑 没有条理
但是至少啊 现在的我很自豪呐 暗戳戳地感谢布置大作业的于红老师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;
}
}
整个项目对应的流程图