Как я могу получить и сравнить значения результатов из потоков? - PullRequest
0 голосов
/ 07 мая 2018

Для задания я пытаюсь сделать игру «камень-ножницы-бумага» в 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 голосов
/ 07 мая 2018

С 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...