以30%的概率动态分配和初始化新对象



我正在编写一个程序,模拟正在登山的跑步者之间的随机比赛,矮兽人(dorcs)正在下山攻击跑步者。比赛开始于两位名叫哈罗德和蒂米的选手在山脚下。跑步者以随机的方式上山,他们可以在山上前进,也可以从山上滑回来。多奇是随机生成的,如果它们碰撞,会对跑步者造成伤害。当其中一名跑步者到达山顶时,或者当两名跑步者都死亡时,模拟结束。

我正在为一个必须实现实际比赛循环的部分而挣扎。一旦比赛被初始化,比赛循环将迭代,直到比赛结束。当宣布获胜者时,或者当所有参赛者都死了时,就会发生这种情况。

比赛循环的每一次迭代都将执行以下操作:

以30%的概率,动态分配一个新的dorc作为EntityType结构,并按如下方式初始化它:

(a) dorc的化身总是"d">

(b) 每个多尔克在第2排的山顶开始比赛

(c) 在相同的概率下,dorc可以被放置在与timmy相同的列中,或者与harold相同的列,或者正好位于两个中间的列中

(d) 将新的dorc添加到种族的dorc 阵列中

(e) 使用pthread_create()函数,为新的dorc创建一个线程,并将线程指针保存在dorc的实体结构中;每个dorc线程将执行的函数是您将在稍后步骤中实现的void*goDorc(void*)函数;goDorc()函数的参数将是对应于该dorc 的EntityType指针

我想我对如何处理这个问题的逻辑感到困惑。我决定制作一个名为isOver()的函数来指示比赛是否结束,然后制作一个单独的函数addDorc()来初始化Dorc元素并完成上面的所有要求。

在isOver()中,我试图通过对竞赛循环的每次迭代执行addDorc(race);来将dorc对象添加到dorcs数组中/如果竞赛尚未结束或没有人死亡。但我一直得到错误:

control.c:82:3: error: too few arguments to function ‘addDorc’
addDorc(race);

问题是我不认为我可以手动声明addDorc()中的所有参数;路径";论点是基于概率的。如上所述,在相同的概率下,dorc可以被放置在与timmy相同的列中,或者与harold相同的列,或者正好位于两者中间的列中。问题是在调用addDorc()时,我不知道如何计算这个随机值,希望能提供一些帮助。我也不知道我是否在做";以30%的概率动态地分配新的dorc作为EntityType结构";正确,并将感谢在这方面的一些意见。

defs.h

typedef struct {
pthread_t thr;
char avatar[MAX_STR];
int  currPos; 
int  path; 
} EntityType;
typedef struct {
EntityType ent;
char name[MAX_STR];
int  health;
int  dead; 
} RunnerType;
typedef struct {
int numRunners;
RunnerType *runners[MAX_RUNNERS];  
int numDorcs;
EntityType *dorcs[MAX_DORCS]; 
char winner[MAX_STR]; 
int  statusRow; 
sem_t mutex;
} RaceInfoType;
void launch();
int addDorc(RaceInfoType*, char*, int, int);
int isOver(RaceInfoType*);
void initRunners(RaceInfoType*);
int addRunner(RaceInfoType*, char*, char*, int, int, int, int);
int  randm(int);
void *goRunner(void*);
void *goDorc(void*);
RaceInfoType *race;

control.c

void launch(){
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;

initRunners(race);

if (sem_init(&race->mutex, 0, 1) < 0) {
printf("semaphore initialization errorn");
exit(1);
}

strcpy(race->winner, " ");


srand((unsigned)time(NULL));

int i;
for(i = 0; i < race->numRunners; ++i){
pthread_create(&(race->runners[i]->ent.thr), NULL, goRunner, " ");
}

race->numDorcs = 0;
}

int addDorc(RaceInfoType* race, char *avatar, int path, int currPos){ 
if(race->numDorcs == MAX_DORCS){ 
printf("Error: Maximum dorcs already reached. n");
return 0;
}       
race->dorcs[race->numDorcs] = malloc(sizeof(EntityType));

int timmysColumn = race->dorcs[race->numDorcs]->currPos;
int haroldsColumn = race->dorcs[race->numDorcs]->currPos;
int halfwayColumn = (timmysColumn+haroldsColumn)/2;

int r = rand()%100;

pthread_t dorc;

if(r <= 30){
strcpy(race->dorcs[race->numDorcs]->avatar, "d");
race->dorcs[race->numDorcs]->currPos = 2;
if(r <= 33){
race->dorcs[race->numDorcs]->path = timmysColumn;
}else if(r <= 66){
race->dorcs[race->numDorcs]->path = haroldsColumn;
}else{
race->dorcs[race->numDorcs]->path = halfwayColumn;
}
pthread_create(&dorc, NULL, goDorc, " ");
}
race->numRunners++;
}
int isOver(RaceInfoType* race){ 
int i;
for(i = 0; i < race->numRunners; ++i){
if((race->winner != " ") || (race->runners[race->numRunners]->dead = 1)){
return 1;
}
addDorc(race);
return 0;
}
}
void initRunners(RaceInfoType* r){
addRunner(r, "Timmy", "T", 10, 35, 50, 0); 
addRunner(r, "Harold", "H", 14, 35, 50, 0); 
}

int addRunner(RaceInfoType* race, char *name, char *avatar, int path, int currPos, int health, int dead){
if(race->numRunners == MAX_RUNNERS){ 
printf("Error: Maximum runners already reached. n");
return 0;
}       
race->runners[race->numRunners] = malloc(sizeof(RunnerType));
strcpy(race->runners[race->numRunners]->name, name);
strcpy(race->runners[race->numRunners]->ent.avatar, avatar);
race->runners[race->numRunners]->ent.path = path;
race->runners[race->numRunners]->ent.currPos = currPos;
race->runners[race->numRunners]->health = health;
race->runners[race->numRunners]->dead = dead;
race->numRunners++;
return 1;
}

注意事项:因为有太多未写的代码缺失,所以这不是一个完整的解决方案。

但是,我注意到至少有两个错误:在我的顶部评论中的isOver错误。并且,在addDorc中递增race->numRunners

isOver还将return 0;放错位置[在循环内]。这应该作为函数中的最后一条语句。如果您使用-Wall进行编译[您应该始终这样做],则编译器(例如control reaches end of non-void function)应该对此进行标记

由此,只有一个";dorc";将被创建(对于第一个符合条件的跑步者)。可能是你想要的,但[AFAICT]你想尝试创建更多的dorc(每个有效的runner为多创建一个)。

此外,编译器标记的错误是因为您正在调用addDorc(race);,但addDorc需要更多的参数。

当您在任何地方执行(例如)race->dorcs[race->numDorcs]->whatever时,遵循代码是非常困难的。

更好的做法(例如):

EntityType *ent = &race->dorcs[race->numDorcs];
ent->whatever = ...;

此外,线程函数可能希望有一个指向其[各自]控制结构的指针(而不是仅传递" ")。


无论如何,我已经重构了您的代码以包含这些更改。我只尝试修复简单代码检查中明显/明显的错误,但没有尝试重新编译或解决逻辑的正确性问题。

因此,还有更多的工作要做,但简化可能会有所帮助。

void
launch(void)
{
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;
initRunners(race);
if (sem_init(&race->mutex,0,1) < 0) {
printf("semaphore initialization errorn");
exit(1);
}
strcpy(race->winner," ");
srand((unsigned)time(NULL));
int i;
for (i = 0;  i < race->numRunners;  ++i) {
RunnerType *run = &race->runners[i];
EntityType *ent = &run->ent;
pthread_create(&ent->thr,NULL,goRunner,ent);
}
race->numDorcs = 0;
}
int
addDorc(RaceInfoType* race,char *avatar,int path,int currPos)
{
if (race->numDorcs == MAX_DORCS) {
printf("Error: Maximum dorcs already reached. n");
return 0;
}
EntityType *ent = malloc(sizeof(*ent));
race->dorcs[race->numDorcs] = ent;
int timmysColumn = ent->currPos;
int haroldsColumn = ent->currPos;
int halfwayColumn = (timmysColumn + haroldsColumn) / 2;
int r = rand()%100;
#if 0
pthread_t dorc;
#endif
if (r <= 30) {
strcpy(ent->avatar,"d");
ent->currPos = 2;
if (r <= 33) {
ent->path = timmysColumn;
} else if (r <= 66) {
ent->path = haroldsColumn;
} else {
ent->path = halfwayColumn;
}
pthread_create(&ent->thr,NULL,goDorc,ent);
}
#if 0
race->numRunners++;
#else
race->numDorcs += 1;
#endif
}
int
isOver(RaceInfoType* race)
{
int i;
for (i = 0;  i < race->numRunners;  ++i) {
#if 0
if ((race->winner != " ") ||
(race->runners[race->numRunners]->dead = 1))
return 1;
#else
RunnerType *run = &race->runners[i];
if ((race->winner != " ") || (run->dead == 1))
return 1;
#endif
addDorc(race);
#if 0
return 0;
#endif
}
#if 1
return 0;
#endif
}
void
initRunners(RaceInfoType* r)
{
addRunner(r,"Timmy","T",10,35,50,0);
addRunner(r,"Harold","H",14,35,50,0);
}
int
addRunner(RaceInfoType* race,char *name,char *avatar,int path,int currPos,
int health,int dead)
{
if (race->numRunners == MAX_RUNNERS) {
printf("Error: Maximum runners already reached. n");
return 0;
}
RunnerType *run = malloc(sizeof(*run));
race->runners[race->numRunners] = run;
strcpy(run->name,name);
EntityType *ent = &run->ent;
strcpy(ent->avatar,avatar);
ent->path = path;
ent->currPos = currPos;
run->health = health;
run->dead = dead;
race->numRunners++;
return 1;
}

更新:

我注意到在addDorc()中,您将pthread_t dorc;放在if语句中。不过,我不太明白我的if语句实际上应该检查什么。

我忘了提及/解释。我用预处理器条件(例如)包装了你的/旧代码和我的/新代码:

#if 0
// old code
#else
// new code
#endif

cpp阶段之后,编译器将看到// new code内容。这样做是一个教学工具,可以[在可能的情况下]显示你有什么代码,而我用什么代码替换了它。这样做是为了显示更改,而不是完全重写。

如果我们从不#define NEVERWAS定义NEVERWAS,那么上面的块将等价于:

#ifdef NEVERWAS
// old code ...
#else
// new code
#endif

它还会像我在原始代码中那样位于if(r <= 30)部分下吗?

是的,希望现在,它更清楚了。#if是一个包含/排除代码的cpp指令(就好像您用这种方式编辑过一样)。但是;真实的";if是一个实际的可执行语句,它在运行时[和以前一样]进行评估,因此不需要更改。

我的另一个担忧是,函数中的任何地方似乎都没有使用dorc,因为您编写的pthread_create(&ent->thr,NULL,goDorc,ent);似乎使用了ent

这是正确的。它是而不是使用/定义的,并且值进入ent->thr。正如您所拥有的,pthread_create设置的pthread_t值将丢失[当dorc超出范围时]。因此,除非它被保存在某个半永久性的地方(例如ent->thr),否则以后将无法进行pthread_join调用。

最新更新