需要在C中对数组的一维进行排序并存储顺序

fnvucqvd  于 2023-01-04  发布在  其他
关注(0)|答案(1)|浏览(108)

我可能需要两个数组来存储值,并快速访问正在排序的值。
例如,float scan_fraction[4][2]作为主数组,int fraction_order[4]作为订单存储,这样我就可以使用订单数组快速访问具有最高值的方向。
在第一维中,我存储方向信息,如fraction[FR_LEFT][VALUE]fraction[FR_LEFT][FR_ENABLED]
在第二维中,我存储了一个float和另一个float(但可以使用int),后者告诉我们方向是启用的还是有条件启用的。
所以最后我可能会用一个结构体来做这个,如果有人也能给我一个例子来做这个,我会很感激的。
这是我得到的

void monster_jump(edict_t *self)
{
    if(!(self->monsterinfo.aiflags & AI_JUMPDODGE) && !(self->monsterinfo.aiflags & AI_JUMPDODGEPROJ))
        return;
    if (!self->groundentity)
        return;

    vec3_t left, right;
    vec3_t  jump_dir = { 0 };
    vec3_t  back, front;

    float scan_fraction[NUM_J_DIRS][2] =
    {
        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f

    };

    int fraction_order[NUM_J_DIRS] =
    {
        0, 0, 0, 0
    };

    int i = 0, each_tr_incomplete = 0, num_fullyenabled = 0, no_random_dir = 1, random_count = 0;

    if (self->monsterinfo.aiflags & AI_JUMPDODGEPROJ && self->monsterinfo.jump_ent)
    {
        
            VectorSubtract(self->s.origin, self->monsterinfo.jump_ent->s.origin, jump_dir);
            gi.bprintf(PRINT_HIGH, "monster_jump: should jump away from projectile!\n");
            jump_dir[2] *= 0.25;
            VectorNormalize(jump_dir);
            vec3_t end;
            VectorMA(self->s.origin, 128, jump_dir, end);
            trace_t tr = gi.trace(self->s.origin, NULL, NULL, end, self, MASK_SHOT);
            if (tr.fraction != 1)
            {
                VectorInverse(jump_dir);
                jump_dir[0] *= 1 + (crandom() * 0.25);
                jump_dir[0] *= 1 + (crandom() * 0.25);
                VectorNormalize(jump_dir);
                gi.bprintf(PRINT_HIGH, "monster_jump: should jump away from projectile!, path is blocked, so go randomly towards projectile\n");
            }
            //else
                //gi.bprintf(PRINT_HIGH, "monster_jump: should jump away from projectile!\n");

    }
    else
    {
        gi.bprintf(PRINT_HIGH, "monster_jump: should jump away from danger!\n");
        scan_fraction[FRAC_LEFT][FR_VAL] = scan_dir(self, SCAN_LEFT, 128, left); 
        scan_fraction[FRAC_RIGHT][FR_VAL] = scan_dir(self, SCAN_RIGHT, 128, right);
        scan_fraction[FRAC_BACK][FR_VAL] = scan_dir(self, SCAN_BACKWARDS, 128, back);
        scan_fraction[FRAC_FORWARD][FR_VAL] = scan_dir(self, SCAN_FORWARD, 128, front);
        gi.bprintf(PRINT_HIGH, "monster_jump: left = %f, right = %f, back = %f, forw = %f!\n", scan_fraction[FRAC_LEFT][FR_VAL], scan_fraction[FRAC_RIGHT][FR_VAL], scan_fraction[FRAC_BACK][FR_VAL], scan_fraction[FRAC_FORWARD][FR_VAL]);
        
        if (scan_fraction[FRAC_LEFT][FR_VAL] != COMPLETE_TR_FRACTION && scan_fraction[FRAC_RIGHT][FR_VAL] != COMPLETE_TR_FRACTION && scan_fraction[FRAC_BACK][FR_VAL] != COMPLETE_TR_FRACTION && scan_fraction[FRAC_FORWARD][FR_VAL] != COMPLETE_TR_FRACTION)
            each_tr_incomplete = 1;

        if (scan_fraction[FRAC_LEFT][FR_VAL] == COMPLETE_TR_FRACTION)
        {
            num_fullyenabled++;
            scan_fraction[FRAC_LEFT][FR_ENABLED] = ENABLED_FULLY;
        }
        if (scan_fraction[FRAC_RIGHT][FR_VAL] == COMPLETE_TR_FRACTION)
        {
            num_fullyenabled++;
            scan_fraction[FRAC_RIGHT][FR_ENABLED] = ENABLED_FULLY;
        }
        if (scan_fraction[FRAC_BACK][FR_VAL] == COMPLETE_TR_FRACTION)
        {
            num_fullyenabled++;
            scan_fraction[FRAC_BACK][FR_ENABLED] = ENABLED_FULLY;
        }
        if (scan_fraction[FRAC_FORWARD][FR_VAL] == COMPLETE_TR_FRACTION)
        {
            num_fullyenabled++;
            scan_fraction[FRAC_FORWARD][FR_ENABLED] = ENABLED_FULLY;
        }

        if (self->monsterinfo.aiflags & AI_JUMPATTACK && scan_fraction[FRAC_FORWARD][FR_VAL] > 1.0f) //let's skip this for now
        {
            self->monsterinfo.aiflags &= ~AI_JUMPATTACK;
            gi.bprintf(PRINT_HIGH, "monster_jump: should jump forward!\n");
            //goto jump_attack;
            VectorSubtract(self->s.origin, front, jump_dir);
        }
        else
        {
            gi.bprintf(PRINT_HIGH, "monster_jump: starting qsort!\n");
            size_t element_count = sizeof scan_fraction / sizeof scan_fraction[0]; // or NUM_J_DIRS
            size_t element_size = sizeof scan_fraction[0];
            qsort(scan_fraction, element_count, element_size, cmp2);
            for (i = 0; i < NUM_J_DIRS; i++)
            {
                gi.bprintf(PRINT_HIGH, "monster_jump: running qsort! i = %i, \n", i);
                
                fraction_order[i] = i;
                if (each_tr_incomplete)
                {
                    gi.bprintf(PRINT_HIGH, "monster_jump: each trace was incomplete\n", i);
                    scan_fraction[i][FR_ENABLED] = ENABLED_CONDITIONALLY;

                }
                else if (scan_fraction[i][FR_VAL] > 0.85f)
                    scan_fraction[i][FR_ENABLED] = ENABLED_FULLY;
                    
            }
        
            gi.bprintf(PRINT_HIGH, "monster_jump: ended qsort! %f %f %f %f\n", scan_fraction[fraction_order[0]][FR_VAL], scan_fraction[fraction_order[1]][FR_VAL], scan_fraction[fraction_order[2]][FR_VAL], scan_fraction[fraction_order[3]][FR_VAL]);
            
            if (num_fullyenabled) //there is at least one direction that can be used
            {
                full_traces:
                random_count++;
                gi.bprintf(PRINT_HIGH, "monster_jump: choosing from full traces, num = %i!\n", random_count);
                if (random_count >= RANDOM_FR_MAX_COUNT)
                    goto random_direction;
                
                switch(fraction_order[rand() % num_fullyenabled])
                {
                case FRAC_LEFT:
                    if (scan_fraction[FRAC_LEFT][FR_ENABLED] != ENABLED_FULLY)
                    {
                        gi.bprintf(PRINT_HIGH, "monster_jump: LEFT is disabled, retry\n");
                        goto full_traces;
                    }
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP LEFT(FULL + RANDOM)\n");
                    VectorSubtract(self->s.origin, right, jump_dir);
                    break;
                case FRAC_RIGHT:
                    if (scan_fraction[FRAC_RIGHT][FR_ENABLED] != ENABLED_FULLY)
                    {
                        gi.bprintf(PRINT_HIGH, "monster_jump: RIGHT is disabled, retry\n");
                        goto full_traces;
                    }       
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP RIGHT(FULL + RANDOM)\n");
                    VectorSubtract(self->s.origin, left, jump_dir);
                    break;
                case FRAC_BACK:
                    if (scan_fraction[FRAC_BACK][FR_ENABLED] != ENABLED_FULLY)
                    {
                        gi.bprintf(PRINT_HIGH, "monster_jump: BACK is disabled, retry\n");
                        goto full_traces;
                    }
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP BACK(FULL + RANDOM)\n");
                    VectorSubtract(self->s.origin, front, jump_dir);
                    break;
                case FRAC_FORWARD:
                    if (scan_fraction[FRAC_FORWARD][FR_ENABLED] != ENABLED_FULLY)
                    {
                        gi.bprintf(PRINT_HIGH, "monster_jump: FORWARD is disabled, retry\n");
                        goto full_traces;
                    }
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP FRONT(FULL + RANDOM)\n");
                    VectorSubtract(self->s.origin, back, jump_dir);
                    break;
                }
            }
            else if (no_random_dir)
            {
                
            sorted_traces:

                random_count++;
                gi.bprintf(PRINT_HIGH, "monster_jump: choosing from sorted, num = %i!\n", random_count);
                if (random_count >= RANDOM_FR_MAX_COUNT)
                    goto random_direction;

                switch (fraction_order[0])
                {
                case FRAC_LEFT:
                    if (!scan_fraction[FRAC_LEFT][FR_ENABLED])
                        goto sorted_traces;
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP LEFT(sorted + RANDOM)\n");
                    VectorSubtract(self->s.origin, right, jump_dir);
                    break;
                case FRAC_RIGHT:
                    if (!scan_fraction[FRAC_RIGHT][FR_ENABLED])
                        goto sorted_traces;
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP RIGHT(sorted + RANDOM)\n");
                    VectorSubtract(self->s.origin, left, jump_dir);
                    break;
                case FRAC_BACK:
                    if (!scan_fraction[FRAC_BACK][FR_ENABLED])
                        goto sorted_traces;
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP BACK(sorted + RANDOM)\n");
                    VectorSubtract(self->s.origin, front, jump_dir);
                    break;
                case FRAC_FORWARD:
                    if (!scan_fraction[FRAC_FORWARD][FR_ENABLED])
                        goto sorted_traces;
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP FRONT(sorted + RANDOM)\n");
                    VectorSubtract(self->s.origin, back, jump_dir);
                    break;
                }
            }
            else
            {
                random_direction:
                gi.bprintf(PRINT_HIGH, "monster_jump: choosing from random dir!\n");
            
                switch (rand() % 4)
                {
                case FRAC_LEFT:
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP LEFT(RANDOM)\n");
                    VectorSubtract(self->s.origin, right, jump_dir);
                    break;
                case FRAC_RIGHT:
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP RIGHT(RANDOM)\n");
                    VectorSubtract(self->s.origin, left, jump_dir);
                    break;
                case FRAC_BACK:
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP BACK(RANDOM)\n");
                    VectorSubtract(self->s.origin, front, jump_dir);
                    break;
                case FRAC_FORWARD:
                    gi.bprintf(PRINT_HIGH, "monster_jump: JUMP FRONT(RANDOM)\n");
                    VectorSubtract(self->s.origin, back, jump_dir);
                    break;
                }
            }
        }
        VectorNormalize(jump_dir);
    }
    
    VectorMA(self->velocity, 300 + (100 * random()), jump_dir, self->velocity);

    self->velocity[2] += 150 + random() * 50;
    self->monsterinfo.jump_ent = NULL;
    self->monsterinfo.aiflags &= ~AI_JUMPDODGEPROJ;
    self->monsterinfo.aiflags &= ~AI_JUMPDODGE;


    gi.sound(self, CHAN_AUTO, gi.soundindex(va("player/step%i.wav", rand() % 5)), 1, ATTN_IDLE, 0);
    gi.sound(self, CHAN_AUTO, gi.soundindex(va("player/step%i.wav", rand() % 5)), 1, ATTN_IDLE, 0.05f);
}

如果能从中世纪的东西中走出来就好了:
random_direction: switch (rand() % 4) { case FRAC_LEFT: if (!scan_fraction[FRAC_LEFT][FR_ENABLED]) goto random_direction;
到不使用随机数的东西,以利用一个有一个案件(或案件)从开关禁用。

ncgqoxb0

ncgqoxb01#

OP不想对scan_fraction[]排序,即使代码包含qsort(scan_fraction, ...
相反,OP希望得到排序的东西,可以访问一个不变的scan_fraction[]是一个排序的方式。

  • 创建指向scan_fraction[]的每个元素的指针数组scan_fraction_sorted[]
  • 排序scan_fraction_sorted[]
  • 通过scan_fraction_sorted[]引用按排序顺序显示scan_fraction[]

下面的代码演示了这一点,有点难看--但是有一些东西让OP仔细考虑。

#include <stdio.h>
#include <stdlib.h>
#define NUM_J_DIRS 4

typedef float (d2)[2];

int cmp3(const void *v1, const void *v2) {
  // Code need improvement to well handle Not-a-numbers.
  const d2 **p1 = ( void *) v1;
  const d2 **p2 = ( void *) v2;
  //printf("cmp %g %g\n", p1[0][0][0], p2[0][0][0]);
  return (p1[0][0][0] > p2[0][0][0]) - (p1[0][0][0] < p2[0][0][0]);
}

int main(void) {
  // scan_fraction[] never changes.
  const d2 scan_fraction[NUM_J_DIRS] = { {1.0f, 0.1f}, {0.0f, 0.2f}, {3.0f, 0.3f}, {
      2.0f, 0.4f}};

  const d2 *scan_fraction_sorted[NUM_J_DIRS];

  for (int i = 0; i < NUM_J_DIRS; i++) {
    scan_fraction_sorted[i] = &scan_fraction[i];
  }

  qsort(scan_fraction_sorted, NUM_J_DIRS, sizeof scan_fraction_sorted[0], cmp3);

  for (int i = 0; i < NUM_J_DIRS; i++) {
    printf("%g %g\n", scan_fraction_sorted[i][0][0], scan_fraction_sorted[i][0][1]);
  }

}

产出

0 0.2
1 0.1
2 0.4
3 0.3

相关问题