如何从线程中检索和比较结果值?

时间:2018-05-07 08:05:17

标签: c pthreads

对于作业,我试图用C线进行摇滚剪刀游戏,使用pthreads并专注于障碍。

它应该有一个用户定义的玩家数量和轮数。随之而来的是基本的石头剪刀规则。对于每个击败另一个的线程/玩家,它会为他增加一个分数,并且对于每个领带,rng决定谁将获得分数(不考虑公平性,这主要是关注障碍)。最后,我应该提出一个胜利者。

e.g. 5 players, 2 rounds. They played: Rock(0), Rock(0), Scissors(2), Paper(1), Paper(1).

Round 1:

Player 1 tied with Player 2, beat Player 3 and lost to Player 4 and 5
Player 2 tied with Player 1, beat player 3 and lost to Player 4 and 5
Player 3 lost to Player 1 and 2 and beat Player 4 and 5
Player 4 beat Player 1 and 2, lost to Player 3 and tied with Player 5
Player 5 beat Player 1 and 2, lost to Player 3 and tied with Player 4

End score would be: 
Player 1: 2 (RNG has chosen him)
Player 2: 1
Player 3: 2
Player 4: 2
Player 5: 3 (RNG has chosen him)

Round 2

...

Player 1: 4 (round 1: 2 + round 2: 2)
Player 2: 2 (1+1)
Player 3: 5 (2+3)
Player 4: 4 (2+2)
Player 5: 5 (3+2)

Winner: Player 3 (RNG)

我认为我设法完成了线程和屏障的事情,但我无法想出一种做得分的方法。我可以以一种有条不紊的方式检索线程结果,但我无法确定如何跟踪并与n个玩家和结果进行比较

以下是代码:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_barrier_t barrier;

void* game(void *id) {
    int player = *(int*)id;
    int random = (int)(void*)(&player);
    int play = random % 3;
    if (play == 0) {
        printf("Player %d: played Rock \n", player);
    }
    if (play == 1) {
        printf("Player %d: played Paper \n", player);
    }
    if (play == 2) {
        printf("Player %d: played Scissors \n", player);
    }

    pthread_barrier_wait(&barrier);

    return (void *)play;
}


int main() {
    system("cls");
    int PLAYERS;
    printf("Players: \n");
    scanf("%d", &PLAYERS);
    printf("\n");
    int i, j;
    pthread_t id[PLAYERS];
    int num_id[PLAYERS];
    void *play;

    pthread_barrier_init(&barrier, NULL, PLAYERS + 1);

    for (i=0; i < PLAYERS; i++) {
        num_id[i] = i;
        pthread_create(&id[i], NULL, game, &num_id[i]);
    }

    pthread_barrier_wait(&barrier);

    for (i=0; i < PLAYERS; i++) {
        pthread_join(id[i], &play);
        printf("The hand of %d was %d\n", i, play); //printf debug
    }

    pthread_barrier_destroy(&barrier);

    return 0;
}

仍然没有回合,因为它仍然是WIP 最好的方法是什么?

1 个答案:

答案 0 :(得分:0)

来自man pthread_join

int pthread_join(pthread_t thread, void **retval);
If retval is not NULL, then pthread_join() copies the exit status of
       the target thread (i.e., the value that the target thread supplied to
       pthread_exit(3)) into the location pointed to by retval

您从每个play返回game()变量值,但是将其保存到同一个变量中,只需将其保存到数组中即可。

int main() {
    system("cls");
    int PLAYERS;
    printf("Players: \n");
    scanf("%d", &PLAYERS);
    printf("\n");
    int i, j;
    // using VLA from C99 isn't that much reliable, so i decided to use malloc here
    // pthread_t id[PLAYERS];
    pthread_t *id = malloc(sizeof(*id)*PLAYERS);
    // int num_id[PLAYERS];
    int *num_id = malloc(sizeof(*num_id)*PLAYERS);
    // void *play[PLAYERS];
    int *play = malloc(sizeof(*play)*PLAYERS);
    // maybe think of a structure here? 
    // struct player { pthread_t *id; int num_id; int play; } *players = malloc(sizeof(*players)*PLAYERS);

    pthread_barrier_init(&barrier, NULL, PLAYERS + 1);

    for (i=0; i < PLAYERS; i++) {
        num_id[i] = i;
        pthread_create(&id[i], NULL, game, &num_id[i]);
    }

    pthread_barrier_wait(&barrier);

    for (i=0; i < PLAYERS; i++) {
        pthread_join(id[i], (void*)&play[i]);
    }

    pthread_barrier_destroy(&barrier);

    for (i=0; i < PLAYERS; i++) {
        printf("The hand of %d was %d\n", i, play[i]);
    }
    // you want to compare first hand with second one?
    if (play[0] == play[1]) {
         printf("First two hands were the same.\n");
    }

    free(id);
    free(num_id);
    free(play);

    return 0;
}

但我认为更好的方法是将指针传递给一些定义的结构作为线程的参数,如下所示:

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

struct player_s {
  pthread_t *id;
  int num_id; 
  int play;
};

pthread_barrier_t barrier;

void* game(void *arg0) {
    struct player_s *p = arg0;
    assert(p != NULL);
    int player = p->num_id;
    int random = player; // this is not random ;)
    int play = random % 3;
    if (play == 0) {
        printf("Player %d: played Rock \n", player);
    }
    if (play == 1) {
        printf("Player %d: played Paper \n", player);
    }
    if (play == 2) {
        printf("Player %d: played Scissors \n", player);
    }

    pthread_barrier_wait(&barrier);

    p->play = play; // save play variable

    return NULL;
}


int main() {
    system("cls");
    int PLAYERS;
    printf("Players: \n");
    scanf("%d", &PLAYERS);
    printf("\n");
    int i, j;
    struct player_s *players = malloc(sizeof(*players)*PLAYERS);
    assert(players != NULL);

    pthread_barrier_init(&barrier, NULL, PLAYERS + 1);

    for (i=0; i < PLAYERS; i++) {
        players[i].num_id = i;
        pthread_create(&players[i].id, NULL, game, &players[i]);
    }

    pthread_barrier_wait(&barrier);

    for (i=0; i < PLAYERS; i++) {
        pthread_join(players[i].id, NULL);
    }

    pthread_barrier_destroy(&barrier);

    for (i=0; i < PLAYERS; i++) {
         printf("The hand of %d was %d\n", i, players[i].play);
    }
    // you want to compare first hand with second one?
    if (players[0].play == players[1].play) {
         printf("First two hands were the same.\n");
    }
    // compare first hand with all the others regardless of the array size
    for(i = 0; i < PLAYERS; ++i) {
        printf("The first hand was %d and the %d hand played %d, so they ", players[0].play, i, players[i].play);
        if (players[0].play != players[i].play) {
            printf("differ!\n");
        } else {
            printf("are the same!\n");
        }
    }
    free(players);

    return 0;
}