-1

我正在尝试编写一个代码来模拟一个circle拥有一把剑的固定大小的人。最接近当前的“活人”index将被淘汰,剑将传给下一个活人(在被杀死的人之后),依此类推。

我希望它在没有链表的情况下编写。

示例: 一组 3 人: arr[0] = 1, arr[1] = 1, arr[2] = 1

第一回合:

  • arr[0] KILLS arr[1] and the sword gets PASSED to arr[2]

第一回合后的元素值:

arr[0] = 1, arr[1] = 0, arr[2] = 1

第二回合:

  • arr[2] KILLS arr[0] and stays the last player

第二回合后的元素值:

arr[0] = 0, arr[1] = 0, arr[2] = 1

  • arr[2]'s index gets returned by the main function.

我想到的是:

  • 大批
  • 将所有元素的值设置为1
  • 每次循环检查if (1 == arr[i])
  • 设置一个标志来确定是杀死还是只是将剑传给这个家伙。
  • 返回当前索引,指示这是最后一个活着的玩家的索引。

例如,假设我们组中有 5 个人: [1] [1] [1] [1] [1]

第一轮

give_sword = 0

i = 0不进入第一个if是因为give_sword不是1。它进入 second if,并使用该函数找到最近的活人findClosestLivingPerson并获取他的索引并将他的值设置为0(==杀死最近的活人)。它设置give_sword1

减少players_counter并检查是否只剩下一名玩家。如果不是,则继续循环。

这是我的代码:

#include <stdio.h>

int findClosestLivingPerson(int arr[], int index, int group_size);


int main (int argc, char *argv[])
{
    
    int group_size = 0, players_counter = 0;
    int i = 0, give_sword = 0;
    int arr[100] = {0};
    
    printf("Enter group size: \n");
    scanf("%d",&group_size);
    
    for (i = 0; i < group_size; i++)
    {
         arr[i] = 1;
    }
   
    players_counter = group_size;
    
        for (i = 0; i < group_size; (i+1) % group_size)
        {
            if (1 == arr[i])
            {
                if(1 == give_sword) /* should give sword, not to kill */
                {
                    give_sword = 0;
                }
                else /* should be killed */
                {
                    arr[findClosestLivingPerson(arr,i, group_size)] = 0;
                    give_sword = 1;
                    --players_counter;
                    if (players_counter == 1)
                    { 
                        break;
                    }
                }
            }
        }
    printf("Winner is %d ",i);
    return 0;
}

int findClosestLivingPerson(int arr[], int index, int group_size)
{
    for (; index < group_size; (index+1) % group_size)
    {
        if (arr[index] == 1)
        return index;
    }
    return 0;
}

编译器说:

在函数'main'中:last_man.c:23:43:警告:没有效果的语句[-Wunused-value] 23 | 对于 (i = 0; i < group_size; (i+1) % group_size)

last_man.c:在函数“findClosestLivingPerson”中:last_man.c:49:42:警告:声明无效 [-Wunused-value] 49 | for (; index < group_size; (index+1) % group_size)

(index+1) % group_size是为了在这个数组中循环。

4

3 回答 3

3

正如编译器所说,(i+1) % group_size没有效果。它计算i和一之和的余数。之后,它对结果没有任何作用。

语句的第三部分for只是一个被评估的表达式。它不会自动更新循环索引或做任何其他事情。如果你想让它更新i,你必须写一个作业,比如i = (i+1) % group_size.

于 2021-02-27T23:53:12.253 回答
2

我认为您误解了for循环的工作原理。

格式应该是这样的:

for( initialization, condition, iteration )

例子:

for( int i = 0; i < size; i = i + 1 )

(i + 1) % group_size不是迭代(它没有将结果分配给 i ),您真正想要做的是

i = ( i + 1 ) % group_size;

同样适用于第二个警告。

于 2021-02-28T00:01:15.000 回答
1

我会建议一种不同的方法。让我们以一种能产生漂亮代码的方式来做这件事。

struct actor {
    int label;
    struct actor *next;
};

使用这个结构,我们可以创建一个很好的链表并循环它:

int n = 5;
int i;

struct actor *actors = calloc(n, sizeof *actors);
for (i = 0; i < n - 1; i++) {
    actors[i].label = i;
    actors[i].next = &actors[i+1];
}
actors[i].label = i;
actors[i].next = &actors[0];

好的,现在我们可以分配第一个杀手:

struct actor *k = actors;

我们还需要一个kill函数:

struct actor *kill(struct actor *a)
{
    if (a->next != a) {
        printf("%d kills %d\n", a->label, a->next->label);
        a->next = a->next->next;
    } else {
        printf("%d is last man standing\n", a->label);
        a->next = NULL;
    }
    return a->next;
}

这是做什么的:它从循环链表中删除下一个人(因为那是被杀死的那个人)。下一个人的查找时间始终相同。

一切就绪后,我们就可以开始狂欢了:

while (k) {
    k = kill(k);
}

无论如何,这不是完美的代码,但它是一个很好的例子,说明如果你在设置上付出一点努力,你可以如何使算法变得非常简单。

于 2021-02-28T00:22:44.800 回答