如何用C++玩generals.io

源自generals.io

大洋彼岸的服务器体验极差!

使用说明

整合了零人、单人、双人版

单人版&&通用规则

图片:https://www.picb.cc/image/tAJbks和https://www.picb.cc/image/tAJ7Nj

先输入0/1/2,代表游戏人数

然后要输入一个随机数种子(更新:长度可以任意),相同种子(相同编译器?)生成相同地图

地图:X为障碍,黑色背景的数为原有城市,红色为玩家的,蓝色为电脑的,城市和普通地面颜色不同

数字表示:数大于99时只显示最高位和一个字母 (e代表100,k代表1000,w代表10000),数大于99999就显示"ju" (巨)

在屏幕左下角可以看到光标所指的数的精确值(hp)

光标是一个小于号"<",用方向键控制光标

按下w/s/a/d时,光标的左边那个数(前提是自己的)会随光标移动

按下z,再按w/s/a/d,光标的左边那个数(前提是自己的)的一半会随光标移动

无法移动的情况:遇到障碍/下一个位置上的数不是自己的,且>=自己的数-1

时间以回合(count)为单位,在屏幕左下角

移动光标不算回合,移动数字算,按到空格键视作放弃一回合

城市每回合+2,其余被占领的地面每10回合+1

屏幕左下角的"army"指一方数字和,"land"指一方占领的格子数

零人版

两个一样的bfs算法对打

只要观战就可以啦

可以按方向键移动光标,但不能移动任何数

按下空格键进入下一回合

如果想快点看到结果,按f键,之后无法移动光标

双人版

红方键盘:(z/x+) w/s/a/d,默认只移动光标,按z移一半
数,按x移全部

蓝方键盘:(n/m+) 方向键,默认只移动光标,按n移一半数,按m移全部

任何一方按空格可以放弃一回合

游戏时间会很漫长

地图有概率出现“封城”,城市也可能分布不公平,换一个种
子重启(继续碰运气)即可

当一方操作结束,光标会移到地图的左上角或右下角,(希望)能方便操作

结束条件:占领所有主塔(最开始的塔再【1】【1】或【n】【n】)

#include<iostream> 
#include<cstdio> 
#include<fstream> 
#include<algorithm> 
#include<cmath> 
#include<deque> 
#include<vector> 
#include<queue> 
#include<string> 
#include<cstring> 
#include<map> 
#include<stack> 
#include<set> 
#include<windows.h>
#include<conio.h>
#include<ctime>
using namespace std;

const int cA=5;//red城市 
const int cB=3;//blue城市 
const int ca=4;//red地面 
const int cb=1;//blue地面 
const int cC=0;//black原有城市 
const int msize=16;//地图大小 
const int mount=16;//障碍数量 
const int grey=16;//城市数量 
const int pmain=2;//城市hp每回合增加量 
const int lcnt=10;//地面hp增加1所需回合 

char cMap[msize][msize];//大写字母表示城市,小写表示地面,Aa是红,Bb是蓝,C是白,X是障碍 
int hp[msize][msize];
int nCount,sx,sy;//回合累加,和光标的坐标 
bool bVis[msize][msize];//bfs
int dir[4][2]={1,0,-1,0,0,1,0,-1};//bfs

struct dRet//决策信息:位置为(x,y)的数移到(x+dx,y+dy) 
{
	int x;
	int y;
	int dx;
	int dy;
};

struct node//bfs 
{
	int x;
	int y;
	int step;
};

void vInit();//生成地图 
void vMove(int dx,int dy);//移动光标 
//以下5个函数,保证A=='A'||A=='B' 
void vMoveNum(int dx,int dy,char A);
void vMoveNum(int x,int y,int dx,int dy,char A);
void vDiv(int dx,int dy,char A);
void vDecide(char A);
dRet bfs(int x,int y,char A);
void vPlus();//每回合数值增加,计算army和land 
void vChange(int x,int y);//刷新屏幕上指定坐标的数 
void gotoxy(int x,int y);//移动输出的位置 
void color(int t,int b);//设置输出颜色,t为文字色,b为背景色 
void vMain0();
void vMain1();
void vMain2();
void vEnd();//判断游戏结束 

int main()
{
	int p; 
	cout<<"player:"<<endl;
	cin>>p;
	system("cls");
	if(p==0) vMain0();
	if(p==1) vMain1();
	if(p==2) vMain2();
	return 0;
}

void vMain0()
{
	int in;
	bool cur=true;
	vInit();
	for(nCount=0;;nCount++)
	{
		gotoxy(msize,0);
		color(15,0);
		cout<<"count="<<nCount<<endl;
		if(cur)
		{
			do
			{
				in=getch();
				if(in==224) 
				{
					in=getch();
					if(in==72) vMove(-1,0);
					if(in==80) vMove(1,0);
					if(in==75) vMove(0,-1);
					if(in==77) vMove(0,1);
				}
			}while(in!=' '&&in!='f');
			if(in=='f') cur=false;
		}
		vDecide('A');
		vDecide('B');
		vPlus();
	}
}

void vMain1()
{
	int in;
	vInit();
	for(nCount=0;;nCount++)
	{
		gotoxy(msize,0);
		color(15,0);
		cout<<"count="<<nCount<<endl;
		do
		{
			in=getch();
			if(in==224) 
			{
				in=getch();
				if(in==72) vMove(-1,0);
				if(in==80) vMove(1,0);
				if(in==75) vMove(0,-1);
				if(in==77) vMove(0,1);
			}
		}while(in!='w'&&in!='s'&&in!='a'&&in!='d'&&in!='z'&&in!=' ');
		if(in=='w') vMoveNum(-1,0,'A');
		if(in=='s') vMoveNum(1,0,'A');
		if(in=='a') vMoveNum(0,-1,'A');
		if(in=='d') vMoveNum(0,1,'A');
		if(in=='z')
		{
			in=getch();
			if(in=='w') vDiv(-1,0,'A');
			if(in=='s') vDiv(1,0,'A');
			if(in=='a') vDiv(0,-1,'A');
			if(in=='d') vDiv(0,1,'A');
		}
		vDecide('B');
		vPlus();
	}
}

void vMain2()
{
	int in;
	vInit();
	for(nCount=0;;nCount++)
	{
		gotoxy(msize,0);
		color(15,0);
		cout<<"count="<<nCount;
		vMove(-sx,-sy);
		gotoxy(msize+1,0);
		cout<<"red ";
		do
		{
			in=getch();
			if(in=='w') vMove(-1,0);
			if(in=='s') vMove(1,0);
			if(in=='a') vMove(0,-1);
			if(in=='d') vMove(0,1);
		}while(in!='x'&&in!='z'&&in!=' ');
		if(in=='x')
		{
			in=getch();
			if(in=='w') vMoveNum(-1,0,'A');
			if(in=='s') vMoveNum(1,0,'A');
			if(in=='a') vMoveNum(0,-1,'A');
			if(in=='d') vMoveNum(0,1,'A');
		}
		else if(in=='z')
		{
			in=getch();
			if(in=='w') vDiv(-1,0,'A');
			if(in=='s') vDiv(1,0,'A');
			if(in=='a') vDiv(0,-1,'A');
			if(in=='d') vDiv(0,1,'A');
		}
		vEnd();
		////////////////////////////////
		vMove(msize-1-sx,msize-1-sy);
		gotoxy(msize+1,0);
		color(15,0);
		cout<<"blue";
		do
		{
			in=getch();
			if(in==224) 
			{
				in=getch();
				if(in==72) vMove(-1,0);
				if(in==80) vMove(1,0);
				if(in==75) vMove(0,-1);
				if(in==77) vMove(0,1);
			}
		}while(in!='n'&&in!='m'&&in!=' ');
		if(in=='m')
		{
			in=getch();
			if(in==224) 
			{
				in=getch();
				if(in==72) vMoveNum(-1,0,'B');
				if(in==80) vMoveNum(1,0,'B');
				if(in==75) vMoveNum(0,-1,'B');
				if(in==77) vMoveNum(0,1,'B');
			}
		}
		else if(in=='n')
		{
			in=getch();
			if(in==224) 
			{
				in=getch();
				if(in==72) vDiv(-1,0,'B');
				if(in==80) vDiv(1,0,'B');
				if(in==75) vDiv(0,-1,'B');
				if(in==77) vDiv(0,1,'B');
			}
		}
		vPlus();
	}
}

void vInit()
{
	int i,j,x,y;
	string sSeed; 
	unsigned int sd=20190622;
	cout<<"seed:"<<endl;
	cin>>sSeed;
	system("cls");
	for(i=0;i<sSeed.size();i++) sd=sd*233+sSeed[i];
	srand(sd);
	cMap[0][0]='A';
	hp[0][0]=pmain;
	vChange(0,0);
	cMap[msize-1][msize-1]='B';
	hp[msize-1][msize-1]=pmain;
	vChange(msize-1,msize-1);
	for(i=1;i<=mount;i++)
	{
		x=rand()%msize;
		y=rand()%msize;
		if(cMap[x][y]!=0) i--;
		else
		{
			cMap[x][y]='X';
			gotoxy(x,y*3);
			color(15,0);
			cout<<" X";
		}
	}
	for(i=1;i<=grey;i++)
	{
		x=rand()%msize;
		y=rand()%msize;
		if(cMap[x][y]!=0) i--;
		else
		{
			cMap[x][y]='C';
			hp[x][y]=40+rand()%10;
			vChange(x,y);
		}
	}
	sx=sy=0;
	gotoxy(0,2);
	color(15,0);
	cout<<"<";
}

void vMove(int dx,int dy)
{
	color(15,0);
	dx+=sx;dy+=sy;
	if(!(dx>=0&&dx<msize&&dy>=0&&dy<msize)) return;
	gotoxy(sx,sy*3+2);
	cout<<" ";
	sx=dx;sy=dy;
	gotoxy(sx,sy*3+2);
	cout<<"<";
	gotoxy(msize+1,0);
	cout<<"cMap="<<cMap[dx][dy]<<",hp="<<hp[dx][dy]<<"            ";
}

void vMoveNum(int x,int y,int dx,int dy,char A)
{
	char a,B,b;
	a=A-'A'+'a';
	B=(A=='A')?'B':'A';
	b=B-'A'+'a';
	if(cMap[x][y]!=a&&cMap[x][y]!=A) return;
	dx+=x;dy+=y;
	if(!(dx>=0&&dx<msize&&dy>=0&&dy<msize&&cMap[dx][dy]!='X')) return;
	char &cd=cMap[dx][dy];
	int &hd=hp[dx][dy],&hs=hp[x][y];
	if(cd!=a&&cd!=A&&hd>=hs-1) return;
	if(cd==0)
	{
		cd=a;
		hd=hs-1;
	}
	else if(cd==A||cd==a)
	{
		hd+=hs-1;
	}
	else if(cd==B||cd==b)
	{
		if(B=='B') cd--;
		else cd++;
		hd=hs-1-hd;
	}
	else//'C'
	{
		cd=A;
		hd=hs-1-hd;
	}
	hs=1;
	vChange(dx,dy);
	vChange(x,y);
}

void vMoveNum(int dx,int dy,char A)
{
	vMoveNum(sx,sy,dx,dy,A);
	vMove(dx,dy);
}

void vDiv(int dx,int dy,char A)
{
	char a,B,b;
	a=A-'A'+'a';
	B=(A=='A')?'B':'A';
	b=B-'A'+'a';
	if(cMap[sx][sy]!=a&&cMap[sx][sy]!=A) return;
	dx+=sx;dy+=sy;
	if(!(dx>=0&&dx<msize&&dy>=0&&dy<msize&&cMap[dx][dy]!='X')) return;
	char &cd=cMap[dx][dy];
	int &hd=hp[dx][dy],&hs=hp[sx][sy],tmp=hs/2;
	if(tmp==0) return;
	if(cd!=a&&cd!=A&&hd>=tmp-1) return;
	if(cd==0)
	{
		cd=a;
		hd=tmp;
	}
	else if(cd==A||cd==a)
	{
		hd+=tmp;
	}
	else if(cd==B||cd==b)
	{
		if(B=='B') cd--;
		else cd++;
		hd=tmp-hd;
	}
	else//'C'
	{
		cd=A;
		hd=tmp-hd;
	}
	hs-=tmp;
	vChange(dx,dy);
	vChange(sx,sy);
	vMove(dx-sx,dy-sy);
}

void vDecide(char A)
{
	char a,B,b;
	a=A-'A'+'a';
	B=(A=='A')?'B':'A';
	b=B-'A'+'a';
	int i,j,k,x,y,dx,dy;
	dRet tmp,res;
	bool bd=false,bm=false;
	for(i=(A=='A')?0:(msize-1);(A=='A')?(i<=msize-1):(i>=0);(A=='A')?(i++):(i--))
	{
		for(j=(A=='A')?0:(msize-1);(A=='A')?(j<=msize-1):(j>=0);(A=='A')?(j++):(j--))
		{
			if(!bd&&(cMap[i][j]==B||cMap[i][j]=='C'))
			{
				tmp=bfs(i,j,A);
				if(tmp.dx+tmp.dy==0) continue;
				bd=true;
				res=tmp;
			}
			if(!bd&&!bm&&(cMap[i][j]==A||cMap[i][j]==a)&&hp[i][j]>1)
			{
				for(k=0;k<4;k++)
				{
					dx=dir[k][0]+i;
					dy=dir[k][1]+j;
					if(!(dx>=0&&dx<msize&&dy>=0&&dy<msize)) continue;
					if((cMap[dx][dy]==0||cMap[dx][dy]==b)&&hp[dx][dy]<hp[i][j]-1)
					{
						bm=true;
						res.dx=dir[k][0];
						res.dy=dir[k][1];
						res.x=i;
						res.y=j;
						break;
					}
				}
			}
			if(bd) break;
		}
		if(bd) break;
	}
	if(!bd&&!bm) return;
	vMoveNum(res.x,res.y,res.dx,res.dy,A);
}

dRet bfs(int x,int y,char A)
{
	char a,B,b;
	a=A-'A'+'a';
	B=(A=='A')?'B':'A';
	b=B-'A'+'a';
	int i,dx,dy;
	dRet ret;
	node now,nxt;
	queue<node>q;
	now.step=hp[x][y]+2;
	now.x=x;
	now.y=y;
	q.push(now);
	memset(bVis,false,sizeof bVis);
	bVis[x][y]=true;
	while(!q.empty())
	{
		now=q.front();
		q.pop();
		for(i=0;i<4;i++)
		{
			dx=dir[i][0]+now.x;
			dy=dir[i][1]+now.y;
			if(dx>=0&&dx<msize&&dy>=0&&dy<msize&&!bVis[dx][dy]&&cMap[dx][dy]!='X')
			{
				bVis[dx][dy]=true;
				if(cMap[dx][dy]==0) nxt.step=now.step+1;
				if(cMap[dx][dy]==b||cMap[dx][dy]==B||cMap[dx][dy]=='C') nxt.step=now.step+hp[dx][dy]+2;
				else
				{
					nxt.step=now.step-hp[dx][dy]+1;
					if(nxt.step<-5&&(cMap[dx][dy]==A||cMap[dx][dy]==a))
					{
						ret.dx=-dir[i][0];
						ret.dy=-dir[i][1];
						ret.x=dx;
						ret.y=dy;
						return ret;
					}
				}
				nxt.x=dx;
				nxt.y=dy;
				q.push(nxt);
			}
		}
	}
	ret.dx=ret.dy=0;
	return ret;
}

void vPlus()
{
	int i,j,aa=0,ba=0,al=0,bl=0;
	if(nCount%lcnt==0)
	{
		for(i=0;i<msize;i++)
		{
			for(j=0;j<msize;j++)
			{
				if(cMap[i][j]=='a'||cMap[i][j]=='b')
				{
					hp[i][j]++;
					vChange(i,j);
				}
			}
		}
	}
	for(i=0;i<msize;i++)
	{
		for(j=0;j<msize;j++)
		{
			if(cMap[i][j]=='A'||cMap[i][j]=='B')
			{
				hp[i][j]+=pmain;
				vChange(i,j);
			}
			if(cMap[i][j]=='A'||cMap[i][j]=='a') al++,aa+=hp[i][j];
			if(cMap[i][j]=='B'||cMap[i][j]=='b') bl++,ba+=hp[i][j];
		}
	}
	color(15,0);
	gotoxy(msize+2,0);
	cout<<"red army:"<<aa<<"   "<<endl;
	cout<<"red land:"<<al<<"   "<<endl;
	cout<<"blue army:"<<ba<<"   "<<endl;
	cout<<"blue land:"<<bl<<"   "<<endl;
	vEnd();
}

void vEnd()
{

	if(cMap[0][0]=='B')
	{
		cout<<"blue win"<<endl;
		while(1);
	}
	if(cMap[msize-1][msize-1]=='A')
	{
		cout<<"red win"<<endl;
		while(1);
	}
}

void vChange(int x,int y)
{
	int c;
	char cm=cMap[x][y];
	if(cm=='A') c=cA;
	if(cm=='a') c=ca;
	if(cm=='B') c=cB;
	if(cm=='b') c=cb;
	if(cm=='C') c=cC;
	gotoxy(x,y*3);
	color(15,c);
	int val=hp[x][y];
	if(val<10) cout<<" "<<val;
	else if(val<100) cout<<val;
	else if(val<1000) cout<<val/100<<"e";
	else if(val<10000) cout<<val/1000<<"k";
	else if(val<100000) cout<<val/10000<<"w";
	else cout<<"ju";
}

void gotoxy(int x,int y)
{
	COORD c;
	c.X=y;
	c.Y=x;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),c);
}

void color(int t,int b)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),t+b*16);
}