创建简单的二维“捕食者-被捕食者”模拟程序

题目:

创建简单的二维“捕食者-被捕食者”模拟程序。被捕食者是蚂蚁(ant),捕食者是狮蚁(doodlebug)。这些小生物生活在20×20的网格世界中。每个单元格每次只能由一个个体占据。网格是封闭的,所以个体不允许离开网格世界边缘。时间以time step为单位,个体在每个time step里面都要采取某项行动。具体规则如下:
1. 建立蚂蚁的行为规则模型。
(1)Move(移动):在每个time step中,都随机向上、向下、向左或者向右移动。假如所选方向上的邻居单元格被占据,或者会造成蚂蚁移动到网格的边缘之外,那么蚂蚁就停留在当前的单元格中。
(2)Breed(繁殖):如果一只蚂蚁在3个time step中保存存活,在第3个time step结束之后(也就是在移动之后),该蚂蚁会繁殖。为了模拟繁殖,需要在相邻(上、下、左或者右)的一个空单元格中创建一只新蚂蚁。没有可用的空单元格,就不会繁殖。一旦成功繁殖出后代,除非再次经历3个time step,否则不能繁殖另一个后代。
2. 建立狮蚁的行为规则模型。
(1)Move(移动):在每个time step中,假如有一只相邻的蚂蚁(上、下、左或者右),就移动到那个单元格,吃掉蚂蚁。否则,狮蚁就按照和蚂蚁相同的规则移动。注意,狮蚁不能吃掉狮蚁。
(2)Breed(繁殖):假如一只狮蚁在8个time step中保持存活,在第8个time step结束之后,会按照与蚂蚁相同的方式繁殖出一只新狮蚁。
(3)Starve(饥饿):假如一只狮蚁在连续3个time step中没有吃掉一只蚂蚁,在第3个time step结束之后,它会感到饥饿并死亡。该狮蚁应从网格中拿掉。
(4)在一轮中,所有狮蚁都应该先于蚂蚁移动。
3. 编写主程序来模拟“捕食者-被捕食者”游戏。
(1)使用ASCII字符“o”表示蚂蚁,“x”表示狮蚁。创建名为Organism(有机生物)的类,它封装了通用于蚂蚁和狮蚁的基本数据。该类应该有一个名为Move的virtual函数,它要在派生类Ant和Doodlebug中进行具体的定义。可能需要额外的数据结构来跟踪已移动的生物。
(2)使用5只狮蚁和100只蚂蚁初始化这个网格世界。在每个time step后,都提示用户按Enter键移动到下一个time step。应该看到狮蚁和蚂蚁数量的循环变化——虽然一些随机性的混乱可能造成一种或两种生物的毁灭。

代码:

#include "pch.h"//编译环境为Visual Studio 2017
#include 
#include
#include
using namespace std;
class Organism
{
public:
	Organism(int xx, int yy) :x(xx), y(yy) {}
	virtual void Move() = 0;
	virtual ~Organism() {}
	int x, y;
	int move = 0;
	int time_step = 0;
};
class Ant :public Organism
{
public:
	Ant(int x1 = 0, int y1 = 0) :Organism(x1, y1) {}
	virtual void Move();
	void Breed();
	virtual ~Ant() {}
};
class Doodlebug :public Organism
{
public:
	Doodlebug(int x2 = 0, int y2 = 0) :Organism(x2, y2) {}
	virtual void Move();
	void Breed();
	int Starve();
	virtual ~Doodlebug() {};
	int step_conti = 0;
};
struct grid
{
	Organism *p = NULL;
	char flag = ' ';
};
grid a[20][20];
void rands();
void display();
void show_number(int k1, int k2);
int main()
{
	int number1 = 0;
	int number2 = 0;
	rands();
	display();
	cout << "初始化已完成......" << endl;
	show_number(100, 5);
	cout << "请按下Enter键移动到下一个time step" << endl;
	char ch = getchar();
	while (ch == '\n')
	{
		for (int i = 0; i < 20; i++)
		{
			for (int j = 0; j < 20; j++)
			{
				if (a[i][j].flag == 'x'&&a[i][j].p->move == 0)
				{
					(a[i][j].p)->Move();
				}
			}
		}
		cout << "狮蚁的移动已完成......" << endl;
		for (int i = 0; i < 20; i++)
		{
			for (int j = 0; j < 20; j++)
			{
				if (a[i][j].flag == 'o' && (a[i][j].p)->move == 0)
				{
					(a[i][j].p)->Move();
			 	}
			}
		}
		cout << "蚂蚁的移动已完成......" << endl;
		system("cls");
		display();
		for (int i = 0; i < 20; i++)
		{
			for (int j = 0; j < 20; j++)
			{
				if (a[i][j].flag == 'o')
				{
					number1++; (a[i][j].p)->move = 0;
				}
				if (a[i][j].flag == 'x')
				{
					number2++; (a[i][j].p)->move = 0;
				}
			}
		}
		show_number(number1, number2);
		number1 = number2 = 0;
		cout << endl << "请按下Enter键移动到下一个time step" << endl;
		ch = getchar();
	}
	return 0;
}
void Ant::Move()
{
	int m;
	int mark = 0;
	int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
	while (mark == 0)
	{
		if ((x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ')||( x - 1 < 0 && y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ')||(x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 <0&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ')|| (x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 >= 20 &&y + 1 < 20 && a[x][y + 1].flag != ' ')|| (x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 >= 20))
		{
			mark = 1;
			break;
		}
		srand(time(NULL));
		m = rand() % 4;
		switch (m)
		{
		case 0:
		{
			if (c1 != 0)
			{
				break;
			}
			else
			{
				if (x - 1 >= 0 && a[x - 1][y].flag == ' ')
				{
					a[x][y].flag = ' ';
					x = x - 1;
					a[x][y].flag = 'o';
					a[x][y].p = a[x + 1][y].p;
					a[x + 1][y].p = NULL;
					time_step++;
					mark = 1;
					move = 1;
				}
				c1 = 1;
				break;
			}
		}
		case 1:
		{
			if (c2 != 0)
			{
				break;
			}
			else
			{
				if (x + 1 < 20 && a[x + 1][y].flag == ' ')
				{
					a[x][y].flag = ' ';
					x = x + 1;
					a[x][y].flag = 'o';
					a[x][y].p = a[x - 1][y].p;
					a[x - 1][y].p = NULL;
					time_step++;
					mark = 1;
					move = 1;
				}
				c2 = 1;
				break;
			}
		}
		case 2:
		{
			if (c3 != 0)
			{
				break;
			}
			else
			{
				if (y - 1 >= 0 && a[x][y - 1].flag == ' ')
				{
					a[x][y].flag = ' ';
					y = y - 1;
					a[x][y].flag = 'o';
					a[x][y].p = a[x][y + 1].p;
					a[x][y + 1].p = NULL;
					time_step++;
					mark = 1;
					move = 1;
				}
				c3 = 1;
				break;
			}
		}
		case 3:
		{
			if (c4 != 0)
			{
				break;
			}
			else
			{
				if (y + 1 < 20 && a[x][y + 1].flag == ' ')
				{
					a[x][y].flag = ' ';
					y = y + 1;
					a[x][y].flag = 'o';
					a[x][y].p = a[x][y - 1].p;
					a[x][y - 1].p = NULL;
					time_step++;
					mark = 1;
					move = 1;
				}
				c4 = 1;
				break;
			}
		}
		}
		if (c1 != 0 && c2 != 0 && c3 != 0 && c4 != 0)
			mark = 1;
	}
	Breed();
}
void Doodlebug::Move()
{
	if (x - 1 >= 0 && a[x - 1][y].flag == 'o')
	{
		delete a[x - 1][y].p;
		a[x][y].flag = ' ';
		x = x - 1;
		a[x][y].flag = 'x';
		a[x][y].p = a[x + 1][y].p;
		a[x + 1][y].p = NULL;
		time_step++;
		move = 1;
        step_conti = 0;
	}
	else if (x + 1 < 20 && a[x + 1][y].flag == 'o')
	{
		delete a[x + 1][y].p;
		a[x][y].flag = ' ';
		x = x + 1;
		a[x][y].flag = 'x';
		a[x][y].p = a[x - 1][y].p;
		a[x - 1][y].p = NULL;
		time_step++;
		move = 1;
		step_conti = 0;
	}
	else if (y - 1 >= 0 && a[x][y - 1].flag == 'o')
	{
		delete a[x][y - 1].p;
		a[x][y].flag = ' ';
		y = y - 1;
		a[x][y].flag = 'x';
		a[x][y].p = a[x][y + 1].p;
		a[x][y + 1].p = NULL;
		time_step++;
		move = 1;
		step_conti = 0;
	}
	else if (y + 1 < 20 && a[x][y + 1].flag == 'o')
	{
		delete a[x][y + 1].p;
		a[x][y].flag = ' ';
		y = y + 1;
		a[x][y].flag = 'x';
		a[x][y].p = a[x][y - 1].p;
		a[x][y - 1].p = NULL;
		time_step++;
		move = 1;
		step_conti = 0;
	}
	else
	{
		step_conti++;
		int m;
		int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
		int mark = 0;
		while (mark == 0)
		{
			srand(time(NULL));
			m = rand() % 4;
			if ((x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ') || (x - 1 < 0 && y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ') || (x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 < 0 && x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 < 20 && a[x][y + 1].flag != ' ') || (x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 >= 20 && y + 1 < 20 && a[x][y + 1].flag != ' ') || (x - 1 >= 0 && a[x - 1][y].flag != ' ' &&y - 1 >= 0 && a[x][y - 1].flag != ' '&&x + 1 < 20 && a[x + 1][y].flag != ' '&&y + 1 >= 20))
			{
				mark = 1;
				break;
			}
			switch (m)
			{
			case 0:
			{
				if (c1 != 0)
				{
					break;
				}
				else
				{
					if (x - 1 >= 0 && a[x - 1][y].flag == ' ')
					{
						a[x][y].flag = ' ';
						x = x - 1;
						a[x][y].flag = 'x';
						a[x][y].p = a[x + 1][y].p;
						a[x + 1][y].p = NULL;
						time_step++;
						mark = 1;
						move = 1;
					}
					c1 = 1;
					break;
				}
			}
			case 1:
			{
				if (c2 != 0)
				{
					break;
				}
				else
				{
					if (x + 1 < 20 && a[x + 1][y].flag == ' ')
					{
						a[x][y].flag = ' ';
						x = x + 1;
						a[x][y].flag = 'x';
						a[x][y].p = a[x - 1][y].p;
						a[x - 1][y].p = NULL;
						time_step++;
						mark = 1;
						move = 1;
					}
					c2 = 1;
					break;
				}
			}
			case 2:
			{
				if (c3 != 0)
				{
					break;
				}
				else
				{
					if (y - 1 >= 0 && a[x][y - 1].flag == ' ')
					{
						a[x][y].flag = ' ';
						y = y - 1;
						a[x][y].flag = 'x';
						a[x][y].p = a[x][y + 1].p;
						a[x][y + 1].p = NULL;
						time_step++;
						mark = 1;
						move = 1;
					}
					c3 = 1;
					break;
				}
			}
			case 3:
			{
				if (c4 != 0)
				{
					break;
				}
				else
				{
					if (y + 1 < 20 && a[x][y + 1].flag == ' ')
					{
						a[x][y].flag = ' ';
						y = y + 1;
						a[x][y].flag = 'x';
						a[x][y].p = a[x][y - 1].p;
						a[x][y - 1].p = NULL;
						time_step++;
						mark = 1;
						move = 1;
					}
					c4 = 1;
					break;
				}
			}
			}
			if (c1 != 0 && c2 != 0 && c3 != 0 && c4 != 0)
				mark = 1;
		}
	}
	if (Starve() == 0)
		Breed();
}
void Ant::Breed()
{
	if (time_step == 3)
	{
		if (x - 1 >= 0 && a[x - 1][y].flag == ' ')
		{
			a[x - 1][y].flag = 'o';
			a[x - 1][y].p = new Ant();
			a[x - 1][y].p->x = x - 1;
			a[x - 1][y].p->y = y;
		}
		else if (x + 1 < 20 && a[x + 1][y].flag == ' ')
		{
			a[x + 1][y].flag = 'o';
			a[x + 1][y].p = new Ant();
			a[x + 1][y].p->x = x + 1;
			a[x + 1][y].p->y = y;
		}
		else if (y - 1 >= 0 && a[x][y - 1].flag == ' ')
		{
			a[x][y - 1].flag = 'o';
			a[x][y - 1].p = new Ant();
			a[x][y - 1].p->x = x;
			a[x][y - 1].p->y = y - 1;
		}
		else if (y + 1 < 20 && a[x][y + 1].flag == ' ')
		{
			a[x][y + 1].flag = 'o';
			a[x][y + 1].p = new Ant();
			(a[x][y + 1].p)->x = x;
			(a[x][y + 1].p)->y = y + 1;
		}
		time_step = 0;
	}
}
void Doodlebug::Breed()
{
	if (time_step == 8)
	{
		if (x - 1 >= 0 && a[x - 1][y].flag == ' ')
		{
			a[x - 1][y].flag = 'x';
			a[x - 1][y].p = new Doodlebug();
			a[x - 1][y].p->x = x - 1;
			a[x - 1][y].p->y = y;
		}
		else if (x + 1 < 20 && a[x + 1][y].flag == ' ')
		{
			a[x + 1][y].flag = 'x';
			a[x + 1][y].p = new Doodlebug();
			a[x + 1][y].p->x = x + 1;
			a[x + 1][y].p->y = y;
		}
		else if (y - 1 >= 0 && a[x][y - 1].flag == ' ')
		{
			a[x][y - 1].flag = 'x';
			a[x][y - 1].p = new Doodlebug();
			a[x][y - 1].p->x = x;
			a[x][y - 1].p->y = y - 1;
		}
		else  if (y + 1 < 20 && a[x][y + 1].flag == ' ')
		{
			a[x][y + 1].flag = 'x';
			a[x][y + 1].p = new Doodlebug();
			a[x][y + 1].p->x = x;
			a[x][y + 1].p->y = y + 1;
		}
		time_step = 0;
	}
}
void del(int x, int y)
{
	delete a[x][y].p;
	a[x][y].p = NULL;
	a[x][y].flag = ' ';
}
int Doodlebug::Starve()
{
	if (step_conti == 3)
	{
		del(x, y);
		return 1;
	}
	return 0;
}
void rands()
{
	int x, y;
	time_t t;
	srand((unsigned)time(&t));
	for (int i = 0; i < 5; i++)
	{
		x = rand() % 20;
		y = rand() % 20;
		if (a[x][y].flag == ' ')
		{
			a[x][y].flag = 'x';
			a[x][y].p = new Doodlebug();
			a[x][y].p->x = x;
			a[x][y].p->y = y;
		}
		else
			i--;
	}
	for (int i = 0; i < 100; i++)
	{
		x = rand() % 20;
		y = rand() % 20;
		if (a[x][y].flag == ' ')
		{
			a[x][y].flag = 'o';
			a[x][y].p = new Ant();
			a[x][y].p->x = x;
			a[x][y].p->y = y;
		}
		else
			i--;
	}
}
void display()
{
	cout << "**************************************************************" << endl;
	cout << "             二维“捕食者 - 被捕食者”模拟程序" << endl;
	cout << "**************************************************************" << endl;
	for (int i = 0; i < 20; i++)
	{
		cout << "*";
		for (int j = 0; j < 20; j++)
		{
			if (a[i][j].flag == 'x')
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
			else if (a[i][j].flag == 'o')
			{
				SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
			}
			cout << " " << a[i][j].flag << " ";
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
		}
		cout << "*";
		cout << endl;
	}
	cout << "**************************************************************" << endl;
}
void show_number(int k1, int k2)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
	cout << "被捕食者——蚂蚁数量:  " << k1 << endl;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
	cout << "捕食者  ——狮蚁数量:  " << k2 << endl;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
}

运行结果

创建简单的二维“捕食者-被捕食者”模拟程序_第1张图片

你可能感兴趣的:(创建简单的二维“捕食者-被捕食者”模拟程序)