1.網格世界類
網格中每個元素存放各種生物對象的指針或者為空。模擬過程中,我們需要移動生物,還有繁殖和饑餓(死亡),所以在網格類中,我們可以將一只生物放到網格中;可以讀取網格中的某個指定位置的生物,獲取它的指針,以便在每一個time step中對它進行處理(移動、繁殖和饑餓死亡)。在一個time step中,網格中每只生物都要處理一遍,先獅蟻,後螞蟻。另外,應該有一個顯示網格的成員函數。
2.有機生物類
生物要能夠放到網格中,所以每一只生物都有相關的函數。可以是構造函數,即構造生物的時候,同時指明放到網格的哪一個位置上。
有Move函數,Breed函數,Starve函數(是否餓死)。這些函數在派生類中有派生類自己的實現。所以,在有機生物類中,這些函數應該是純虛函數,有機生物類是一個抽象類。
網格世界類中,從某個網格位置讀取生物並處理時,需要知道是哪一種類型的生物(是獅蟻還是螞蟻),所以,有機生物類裡應該考慮如何返回生物的類型。簡單的辦法是,用不同的常量來表示獅蟻和螞蟻。例如,用整數1表示獅蟻,2表示螞蟻。在有機生物類中定義純虛函數GetType,返回生物的具體類型。
3.螞蟻類
實現Move函數,Breed函數,Starve函數和GetType函數。
4.獅蟻類
實現Move函數,Breed函數,Starve函數和GetType函數。
(二)細化:
1.網格世界類:
(1)屬性。數據結構:網格世界中如何存放螞蟻或獅蟻對象?
20*20的網格,用一個20*20的二維數組來表示,數組元素是什麼類型?
(2)方法。網格世界類應該有哪些成員函數?
構造函數:初始化網格。
析構函數:釋放掉所有生物。
Set函數:指定x,y位置(二維數組的下標),以及一只生物的地址(指針),將這只生物存入網格中。
Get函數:獲取網格中x,y坐標上的生物的地址(指針)。
OneStep函數:在一個time step中,網格中每只生物都要處理一遍,包括移動、繁殖和饑餓。首先,把網格中的每一只生物在本輪是否移動過的標記moved先都標記為假(為什麼?);其次,移動,先獅蟻,後螞蟻,同時把該生物的moved標記為真;再次,把饑餓的獅蟻消滅掉;最後,繁殖。
Display函數:顯示函數,顯示網格中的具體情況。每個網格,如果是空,顯示”.”;如果是螞蟻,顯示”o”;如果是獅蟻,顯示”x”。
2.有機生物類
(1)屬性
要記錄每只生物的一些基本屬性:屬於哪個網格對象,具體在哪個位置上(x,y坐標),本輪是否移動過。另外,為了記錄是否到了繁殖時間,要有一個跟蹤器,即記錄上次繁殖之後,又經歷了多少次time step。
(2)方法
構造函數:
帶參數的構造函數:指定網格對象和x、y位置,把構造的生物放到網格中。
析構函數:
Move函數,Breed函數,Starve函數和GetType函數為純虛函數。
3.螞蟻類
(1)屬性
不需要再添加屬性。
(2)方法
構造函數:
帶參數的構造函數:指定網格對象和x、y位置,把構造的螞蟻放到網格中。
析構函數:
Move函數:隨機選擇一個方向,看是否能移動,否則保持在原位置。
Breed函數:繁殖跟蹤器+1.如果是3的倍數,就需要繁殖,同時跟蹤器清零。
Starve函數:本模擬中螞蟻不會餓死,所以僅返回false值即可。
GetType函數:返回螞蟻的類型標記。
4.獅蟻類
(1)屬性
獅蟻會餓死,需要添加一個屬性,跟蹤記錄獅蟻饑餓了多少次time step。
(2)方法
構造函數:
帶參數的構造函數:指定網格對象和x、y位置,把構造的獅蟻放到網格中。
析構函數:
Move函數:若有相鄰螞蟻,移動到單元網格,吃掉螞蟻;否則,隨機選擇一個方向,看是否能移動,不能移動則保持在原位置。
Breed函數:繁殖跟蹤器+1,如果是8的倍數,就需要繁殖,同時跟蹤器清零。
Starve函數:饑餓跟蹤器+1,如果是3的倍數,則饑餓並死亡,從網格中拿掉該獅蟻,同時跟蹤器清零。
GetType函數:返回獅蟻的類型標記。
四、其它
(一)所有涉及的常量定義為類型常量。如:
const int ANTBREED = 3; //螞蟻的繁殖周期為3個time steps
const int DOODLEBREED = 8; //獅蟻的繁殖周期為8個time steps
初始化網格世界時,用的獅蟻只數和螞蟻只數,分別為5只和100只,也定義為類型常量。如:
const int INITIALANTS = 100;
const int INITIALBUGS = 5;
#ifndef __SOURCE_H__
#define __SOURCE_H__
struct Step
{
int dx;
int dy;
};
enum AnimalType
{
IsAnt,
IsDoodlebug
};
class Animal;
class Cell
{
public:
int x;
int y;
Animal *animal;
public:
Cell(int x0, int y0);
Cell *nearbyCell(int dir);
bool in(Animal *animal0);
Animal *leave();
};
class Animal
{
protected:
int maxBreedTime;
int breedTime;
int maxStarveTime;
int starveTime;
public:
AnimalType type;
Animal *next;
Animal *prior;
public:
Animal();
virtual ~Animal();
public://virtual
virtual Animal *breedChild() = 0;
virtual bool canEat(AnimalType animal) = 0;
virtual bool eat() = 0;
public:
Cell *cell;
bool breed();
bool move();
void step();
};
class Ant :public Animal
{
public:
Ant() ;
public:
virtual Animal *breedChild();
virtual bool canEat(AnimalType t);
virtual bool eat();
};
class Doodlebug :public Animal
{
public:
Doodlebug() ;
public:
virtual Animal *breedChild();
virtual bool canEat(AnimalType t);
virtual bool eat();
};
Step Steps[4] = { { 0, 1 }, { 1, 0 }, { 0, -1 }, { -1, 0 } };
int maxWidth;
int maxHeight;
Cell ***Status;
Animal *DoodleBugs;
Animal *Ants;
#endif //__SOURCE_H__
SOURCE.CPP
#include <stdio.h>
#include <stdlib.h>
#include "Source.h"
//========================================
//
// Cell
//
Cell::Cell(int x0, int y0)
{
this->x = x0;
this->y = y0;
this->animal = NULL;
}
Cell *Cell::nearbyCell(int dir)
{
int x0 = this->x + Steps[dir].dx;
int y0 = this->y + Steps[dir].dy;
if (x0 < 0 || y0 < 0 || x0 >= maxWidth || y0 >= maxHeight)
return NULL;
else
{
return Status[x0][y0];
}
}
bool Cell::in(Animal *animal0)
{
if (this->animal != NULL)
return false;
else
{
animal0->cell = this;
this->animal = animal0;
return true;
}
}
Animal *Cell::leave()
{
Animal *theAnimal = this->animal;
theAnimal->cell = NULL;
this->animal = NULL;
return theAnimal;
}
//========================================
//
// Animal
//
Animal::Animal()
{
this->cell = NULL;
this->breedTime = 0;
this->starveTime = 0;
this->prior = NULL;
this->next = NULL;
}
bool Animal::breed()
{
if (this->breedTime >= maxBreedTime)
{
for (int i = 0; i < 4; i++)
{
Cell *c = this->cell->nearbyCell(i);
if (c != NULL && c->animal == NULL)
{
c->in(this->breedChild());
this->breedTime = 0;
return true;
}
}
}
return false;
}
bool Animal::move()
{
int dir = rand() % 4;
Cell *c = this->cell->nearbyCell(dir);
if (c == NULL)
return false;
else if (c->animal == NULL)
{
c->in(this->cell->leave());
return true;
}
}
void Animal::step()
{
bool dosth = false;
this->breedTime++;
this->starveTime++;
dosth |= this->breed();
dosth |= this->eat();
if (!dosth)
{
this->move();
}
if (this->maxStarveTime > 0 && this->starveTime >= this->maxStarveTime)
{
//starve
this->cell->leave();
delete (this);
}
}
Animal::~Animal()
{
Animal *t = this->next;
this->prior->next = t;
if (t != NULL)
t->prior = this->prior;
}
//========================================
//
// Ant
//
Ant::Ant() : Animal()
{
this->type = IsAnt;
this->maxStarveTime = -1;
this->maxBreedTime = 3;
if (Ants != NULL)
{
this->prior = Ants;
this->next = Ants->next;
if (Ants->next != NULL) Ants->next->prior = this;
Ants->next = this;
}
}
Animal *Ant::breedChild()
{
return new Ant();
}
bool Ant::canEat(AnimalType t)
{
return false;
}
bool Ant::eat()
{
return false;
}
//========================================
//
// Doodlebug
//
Doodlebug::Doodlebug() :Animal()
{
this->type = IsDoodlebug;
this->maxStarveTime = 3;
this->maxBreedTime = 8;
if (DoodleBugs != NULL)
{
this->prior = DoodleBugs;
this->next = DoodleBugs->next;
if (DoodleBugs->next != NULL) DoodleBugs->next->prior = this;
DoodleBugs->next = this;
}
}
Animal * Doodlebug::breedChild()
{
return new Doodlebug();
}
bool Doodlebug::canEat(AnimalType t)
{
if (t == IsAnt)
return true;
else
return false;
}
bool Doodlebug::eat()
{
for (int i = 0; i < 4; i++)
{
Cell *c = this->cell->nearbyCell(i);
if (c!=NULL && c->animal != NULL && this->canEat(c->animal->type))
{
Animal *theAnimal = c->leave();
delete(theAnimal);
this->starveTime = 0;
return true;
}
}
return false;
}
//========================================
//
// main
//
void randomSet(Animal *animal0)
{
srand(0);
int x;
int y;
do
{
x = rand() % maxWidth;
y = rand() % maxHeight;
}
while (Status[x][y]->animal != NULL);
Status[x][y]->in(animal0);
}
void printoutHead()
{
printf("+");
for (int i = 0; i < maxWidth; i++)
{
printf("=");
}
printf("+\n");
}
void printoutDetail(int r)
{
printf("|");
for (int i = 0; i < maxWidth; i++)
{
if (Status[i][r]->animal == NULL)
printf(" ");
else
{
switch (Status[i][r]->animal->type)
{
case IsAnt:
printf("O");
break;
case IsDoodlebug:
printf("X");
break;
default:
printf("?");
break;
}
}
}
printf("|\n");
}
void printout()
{
printoutHead();
for (int i = 0; i < maxHeight; i++)
printoutDetail(i);
printoutHead();
}
void main()
{
int nDoodleBug;
int nAnt;
printf("請輸入區域寬度:");
scanf("%d", &maxWidth);
printf("請輸入區域高度:");
scanf("%d", &maxHeight);
printf("請輸入初始獅蟻數量:");
scanf("%d", &nDoodleBug);
printf("請輸入初始螞蟻數量:");
scanf("%d", &nAnt);
//maxWidth = 3;
//maxHeight = 4;
//nDoodleBug = 2;
//nAnt = 5;
Status = new Cell**[maxWidth];
DoodleBugs = new Doodlebug();
Ants = new Ant();
for (int i = 0; i < maxWidth; i++)
{
Status[i] = new Cell*[maxHeight];
for (int j = 0; j < maxHeight; j++)
{
Status[i][j] = new Cell(i, j);
}
}
for (int i = 0; i < nDoodleBug; i++)
{
randomSet(new Doodlebug());
}
for (int i = 0; i < nAnt; i++)
{
randomSet(new Ant());
}
printout();
system("pause");
while (true)
{
Animal *a = DoodleBugs->next;
Animal *a0;
for ( a0 = (a == NULL ? NULL : a->next); a != NULL; a = a0, a0 = (a == NULL ? NULL : a->next))
a->step();
a = Ants->next;
for ( a0 = (a == NULL ? NULL : a->next); a != NULL; a = a0, a0 = (a == NULL ? NULL : a->next))
a->step();
printout();
system("pause");
}
}