-1

私は、circle1 本の剣を持っている固定サイズの人々をシミュレートするコードを作成しようとしています。現在に最も近い「生きている人」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

2 番目のターン:

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

2 ターン目以降の要素の値:

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]

第 1 ラウンド:

give_sword = 0

i = 0ifではありませんので最初は入りませgive_sword1。2 番目の に入り、if関数を使用して最も近い生きている人物を見つけ、findClosestLivingPersonそのインデックスを取得して値を0(== 最も近い生きている人物を殺す) に設定します。に設定give_sword1ます。

を減らし、players_counterプレイヤーが 1 人しか残っていないかどうかを確認します。そうでない場合は、ループを続行します。

これは私のコードです:

#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 | for (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

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 に答える