zoukankan      html  css  js  c++  java
  • 「THUPC2019」鸭棋

    我第一次写的时候只写了 80 分钟吧,发现读入完全不一样就扔了,第二次重构甚至只用 40 分钟重构,剩下时间都是调的,还有 5 分钟在调调试函数

    写大模拟就要写这种题意清清楚楚的大模拟。有益于身体健康,锻炼码力,理顺思维。实际上这道题不通过加注释就能完成。


    捋一捋流程:

    • 先手红棋;
    • 如果游戏结束,输出 Invalid command
    • 否则根据输入选一个格子 ((s,t)),将上面的棋子移到 ((x,y)),以以下流程判断是否可行:
      • 如果 ((s,t)) 没有当前执棋家的棋,不可行;
      • 如果 ((x,y))当前执棋家的棋,不可行;
      • 如果 ((x,y)) 这个位置不合法,不可行;
      • 否则判断当前棋子能否通过合法方案从 ((s,t)) 移至 ((x,y))
    • 如果不可行,输出 Invalid command
    • 否则,将棋子从 ((s,t)) 移至 ((x,y))
    • 如果 ((x,y)) 有对家的棋子:
      • 如果 ((x,y)) 是对方的王,打上游戏结束标记;
      • 吃掉 ((x,y)) 上面的,对家的棋子。
    • 判断当前局面是否是将军;
    • 判断游戏已经结束。

    流程捋顺了,具体讲解。


    首先讲一下大题的框架:

    const char chessName[10][15]={"","captain","guard","elephant","horse","car","duck","soldier"};//存储各个棋子编号对应的棋子名称
    const char colorOutput[2][10]={"red","blue"};//执棋家颜色
    const char checkOutput[2][10]={"no","yes"};//真还是假
    const int sx[3]={0,1,-1},sy[3]={0,1,-1};//如象,马,鸭移动方法描述,这里是蠢了开了两个,实际上两个一样显然可以共用
    class Duckchess{
    	bool Occupy(int x,int y,int c);//执棋家 c 有没有棋子在 (x,y) 上 E
    	bool Occupy(int x,int y);//有没有棋子在 (x,y) 上 E
    	bool Outside(int x,int y);//(x,y) 是否在棋盘内 E
    	bool captainMoveCor(int s,int t,int x,int y);//王从 (s,t) 移动至 (x,y) 是否合法,下同
    	bool guardMoveCor(int s,int t,int x,int y);
    	bool elephantMoveCor(int s,int t,int x,int y);
    	bool duckMoveCor(int s,int t,int x,int y);
    	bool soldierMoveCor(int s,int t,int x,int y);
    	bool moveCorrect(int op,int s,int t,int x,int y);//对于棋子 op,从 (s,t) 移动至 (x,y) 是否合法
    	bool attack(int x,int y,int c);//有没有 c 家的棋子能攻击到 (x,y)
    public:
    	int board[12][12][2];//棋盘
    	bool gameOver;//游戏结束标记
    	Duckchess(){}//构造函数,用于构造棋盘
    	~Duckchess(){}//析构函数,可以不要,为了封装的完整性留下来了
    	bool isMoveSuc(int s,int t,int x,int y,int c);//执棋家为 c 时,棋子从 (s,t) 移动到 (x,y) 是否合法
    	void moveChess(int s,int t,int x,int y,int c);//将 c 家的棋子从 (s,t) 移动到 (x,y)
    	void chessDelete(int s,int t,int c);//删除 c 家在 (s,t) 的棋子
    	bool isGeneral();//判断将军局面
    }game;
    

    注:实际上为了将 class 封装得更好看,可以使用 enum,指针,或者是更多的函数去实现。但是我拒绝。

    没问题?继续看主函数。

    int main(){
    	int control=0,T=read();//先手红棋
    	while(T-->0)
    	{
    		int s=read(),t=read(),x=read(),y=read();
    		if(game.isMoveSuc(s,t,x,y,control) && !game.gameOver)//如果移动合法且游戏未结束
    		{
    			int k=game.board[s][t][control];//得到当前棋子
    			printf("%s %s;",colorOutput[control],chessName[k]);//输出
    			game.moveChess(s,t,x,y,control);//移动棋子
    			game.chessDelete(x,y,control);//删除对方棋子
    			printf("%s;%s
    ",checkOutput[game.isGeneral()],checkOutput[game.gameOver]);//输出是否将军,是否结束
    			control^=1;//两家交换执棋
    		}
    		else	puts("Invalid command");//无效操作
    	}
    	return 0;
    }
    

    接下来的工作就是把剩下的函数全部填下来。啥?这还要我讲?

    实际的实现中并没有用到注释。写每一个函数使得你写代码的过程相互独立,可以让你的思维很清晰,实现模块化编程。

    #include<bits/stdc++.h>
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    #define getchar() (p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    int read()
    {
    	int x=0,f=1;
    	char c=getchar();
    	while(c<'0' || c>'9')
    	{
    		if(c=='-')	f=-1;
    		c=getchar();
    	}
    	while(c>='0' && c<='9')	x=(x<<1)+(x<<3)+(c^'0'),c=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	if(x<0)	putchar('-'),x=-x;
    	if(x>9)	write(x/10);
    	putchar(x%10+'0');
    }
    const char chessName[10][15]={"","captain","guard","elephant","horse","car","duck","soldier"};
    const char colorOutput[2][10]={"red","blue"};
    const char checkOutput[2][10]={"no","yes"};
    const int sx[3]={0,1,-1},sy[3]={0,1,-1};
    class Duckchess{
    	bool Occupy(int x,int y,int c){return bool(board[x][y][c]);}
    	bool Occupy(int x,int y){return bool(board[x][y][0] || board[x][y][1]);}
    	bool Outside(int x,int y){return !(x>=0 && y>=0 && x<=9 && y<=8);}
    	bool captainMoveCor(int s,int t,int x,int y){return abs(s-x)+abs(t-y)==1;}
    	bool guardMoveCor(int s,int t,int x,int y){return abs(s-x)==1 && abs(t-y)==1;}
    	bool elephantMoveCor(int s,int t,int x,int y)
    	{
    		for(int dx=1;dx<=2;++dx)
    		{
    			for(int dy=1;dy<=2;++dy)
    			{
    				int p=s+sx[dx]*2,q=t+sy[dy]*2;
    				if(Outside(p,q))	continue;
    				if(p==x && q==y)
    				{
    					if(!Occupy(s+sx[dx],t+sy[dy]))	return true;
    					return false;
    				}
    			}
    		}
    		return false;
    	}
    	bool horseMoveCor(int s,int t,int x,int y)
    	{
    		for(int dx=1;dx<=2;++dx)
    		{
    			for(int dy=1;dy<=2;++dy)
    			{
    				int p=s+sx[dx]*2,q=t+sy[dy];
    				if(Outside(p,q))	continue;
    				if(p==x && q==y)
    				{
    					if(!Occupy(s+sx[dx],t))	return true;
    					return false;
    				}
    			}
    		}
    		for(int dx=1;dx<=2;++dx)
    		{
    			for(int dy=1;dy<=2;++dy)
    			{
    				int p=s+sx[dx],q=t+sy[dy]*2;
    				if(Outside(p,q))	continue;
    				if(p==x && q==y)
    				{
    					if(!Occupy(s,t+sy[dy]))	return true;
    					return false;
    				}
    			}
    		}
    		return false;
    	}
    	bool carMoveCor(int s,int t,int x,int y)
    	{
    		if(s!=x && t!=y)	return false;
    		if(s==x)
    		{
    			if(t>y)
    			{
    				for(int i=t-1;i>y;--i)	if(Occupy(s,i))	return false;
    			}
    			else
    			{
    				for(int i=t+1;i<y;++i)	if(Occupy(s,i))	return false;
    			}
    			return true;
    		}
    		else
    		{
    			if(s>x)
    			{
    				for(int i=s-1;i>x;--i)	if(Occupy(i,t))	return false;
    			}
    			else
    			{
    				for(int i=s+1;i<x;++i)	if(Occupy(i,t))	return false;
    			}
    			return true;
    		}
    	}
    	bool duckMoveCor(int s,int t,int x,int y)
    	{
    		for(int dx=1;dx<=2;++dx)
    		{
    			for(int dy=1;dy<=2;++dy)
    			{
    				int p=s+sx[dx]*3,q=t+sy[dy]*2;
    				if(Outside(p,q))	continue;
    				if(p==x && q==y)
    				{
    					if(Occupy(s+2*sx[dx],t+sy[dy]) || Occupy(s+sx[dx],t))	return false;
    					return true;
    				}
    			}
    		}
    		for(int dx=1;dx<=2;++dx)
    		{
    			for(int dy=1;dy<=2;++dy)
    			{
    				int p=s+sx[dx]*2,q=t+sy[dy]*3;
    				if(Outside(p,q))	continue;
    				if(p==x && q==y)
    				{
    					if(Occupy(s+sx[dx],t+2*sy[dy]) || Occupy(s,t+sy[dy]))	return false;
    					return true;
    				}
    			}
    		}
    		return false;
    	}
    	bool soldierMoveCor(int s,int t,int x,int y){return abs(s-x)<=1 && abs(t-y)<=1;}
    	bool moveCorrect(int op,int s,int t,int x,int y)
    	{
    		if(op==1)	return captainMoveCor(s,t,x,y);
    		else if(op==2)	return guardMoveCor(s,t,x,y);
    		else if(op==3)	return elephantMoveCor(s,t,x,y);
    		else if(op==4)	return horseMoveCor(s,t,x,y);
    		else if(op==5)	return carMoveCor(s,t,x,y);
    		else if(op==6)	return duckMoveCor(s,t,x,y);
    		else	return soldierMoveCor(s,t,x,y);
    	}
    	bool attack(int x,int y,int c)
    	{
    		for(int i=0;i<=9;++i)	for(int j=0;j<=8;++j)	if(board[i][j][c] && moveCorrect(board[i][j][c],i,j,x,y))	return true;
    		return false;
    	}
    public:
    	int board[12][12][2];
    	bool gameOver;
    	Duckchess()
    	{
    		gameOver=false;
    		board[0][4][0]=board[9][4][1]=1;
    		board[0][3][0]=board[9][3][1]=board[0][5][0]=board[9][5][1]=2;
    		board[0][2][0]=board[9][2][1]=board[0][6][0]=board[9][6][1]=3;
    		board[0][1][0]=board[9][1][1]=board[0][7][0]=board[9][7][1]=4;
    		board[0][0][0]=board[9][0][1]=board[0][8][0]=board[9][8][1]=5;
    		board[2][0][0]=board[7][0][1]=board[2][8][0]=board[7][8][1]=6;
    		board[3][0][0]=board[3][2][0]=board[3][4][0]=board[3][6][0]=board[3][8][0]=7;
    		board[6][0][1]=board[6][2][1]=board[6][4][1]=board[6][6][1]=board[6][8][1]=7;
    	}
    	~Duckchess(){memset(board,0,sizeof board);}
    	bool isMoveSuc(int s,int t,int x,int y,int c)
    	{
    		if(!Occupy(s,t,c))	return false;
    		if(Occupy(x,y,c))	return false;
    		if(Outside(x,y))	return false;
    		int chessid=board[s][t][c];
    		return moveCorrect(chessid,s,t,x,y);
    	}
    	void moveChess(int s,int t,int x,int y,int c)
    	{
    		board[x][y][c]=board[s][t][c];
    		board[s][t][c]=0;
    	}
    	void chessDelete(int s,int t,int c)
    	{
    		if(board[s][t][c^1])
    		{
    			printf("%s %s",colorOutput[c^1],chessName[board[s][t][c^1]]);
    			if(board[s][t][c^1]==1)	gameOver=true;
    			board[s][t][c^1]=0;
    		}
    		else	printf("NA");
    		putchar(';');
    	}
    	bool isGeneral()
    	{
    		if(gameOver)	return false;
    		for(int i=0;i<=9;++i)
    		{
    			for(int j=0;j<=8;++j)
    			{
    				if(board[i][j][0]==1 && attack(i,j,1))	return true;
    				if(board[i][j][1]==1 && attack(i,j,0))	return true;
    			}
    		}
    		return false;
    	}
    }game;
    int main(){
    	int control=0,T=read();
    	while(T-->0)
    	{
    		int s=read(),t=read(),x=read(),y=read();
    		if(game.isMoveSuc(s,t,x,y,control) && !game.gameOver)
    		{
    			int k=game.board[s][t][control];
    			printf("%s %s;",colorOutput[control],chessName[k]);
    			game.moveChess(s,t,x,y,control);
    			game.chessDelete(x,y,control);
    			printf("%s;%s
    ",checkOutput[game.isGeneral()],checkOutput[game.gameOver]);
    			control^=1;
    		}
    		else	puts("Invalid command");
    	}
    	return 0;
    }
    
  • 相关阅读:
    Scala学习十二——高阶函数
    Scala学习十一——操作符
    Scala学习十——特质
    Scala学习九——文件和正则表达式
    Scala学习八——继承
    Scala学习七——包和引入
    Scala学习六——对象
    Scala学习五——类
    Scala学习四——映射和数组
    Spark Broadcast内幕解密:Broadcast运行机制彻底解密、Broadcast源码解析、Broadcast最佳实践
  • 原文地址:https://www.cnblogs.com/amagaisite/p/13795377.html
Copyright © 2011-2022 走看看