首先,这是作业。我必须编写Pit版本的代码。就我而言,服务器为每个客户端分发9张卡。游戏规则不是很重要,因为我的问题恰好发生在我试图向一个客户提供9张卡时。 p>
我使用共享内存来存储游戏的信息(状态,连接的玩家数量......)和客户的牌。
这是我对共享内存的表示。信息是struct
,每张卡都是enum
的一部分。
这是我的问题:我有一个函数initialize_pit()
,它使用shm_open()
,ftruncate()
和mmap()
初始化共享内存。在这个函数之后,接下来会有一个指针:
然后我将服务器上的卡片随机播放到共享内存中,我显示它们(它完美无缺!),我允许客户获取各自的卡片。就我而言,只有一个客户。
客户端能够获取并打印游戏的信息,例如游戏的状态(位于共享内存中),但它尝试获取的所有卡都是0
( default int value,imo)。
我无法理解,因为:
我几乎尝试了一切,我真的无法理解发生了什么。抱歉我的英语不好,我希望我已经清楚了。
提前感谢您的帮助。如果我的问题出现问题,请告诉我。
pit_utilities.h
#define MIN_OFFER 1
#define MAX_OFFER 4
#define NB_TYPES 7
#define MAX_CARDS 9
#define MIN_PLAYERS 3
#define MAX_PLAYERS 7
#define CLIENT 0
#define SERVER 1
/*
Enum représentant une carte du jeu
*/
typedef enum {
WHEAT,
BARLEY,
CORN,
RYE,
OATS,
HAY,
FLAX
} Card;
extern const Card card_map[NB_TYPES];
extern const char* card_string[NB_TYPES];
/*
Enum représentant les états du jeu
*/
typedef enum {
LOADING,
GETTING_CARDS,
PLAYING
} GameState;
/*
Structure représentant un set de cartes (une offre)
*/
typedef struct {
Card set[NB_TYPES];
int quantity;
} CardSet;
/*
Structure représentant les informations de la partie
*/
typedef struct {
int max_players;
int connected;
GameState state;
} GameInfo;
void initialize_pit(GameInfo** infos, Card** cards, CardSet** offers, int role);
pit_utilities.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include "pit_utilities.h"
const Card card_map[NB_TYPES] = { WHEAT, BARLEY, CORN, RYE, OATS, HAY, FLAX };
const char* card_string[NB_TYPES] = { "WHEAT", "BARLEY", "CORN", "RYE", "OATS", "HAY", "FLAX" };
void initialize_pit(GameInfo** infos, Card** cards, CardSet** offers, int role)
{
//Créer la mémoire partagée de la bonne taille, puis le partager avec mmap
int mem_fd = shm_open("pit", O_CREAT|O_RDWR, S_IRUSR | S_IWUSR);
int mem_length = sizeof(Card) * MAX_CARDS * (*infos)->max_players + sizeof(GameInfo);
ftruncate(mem_fd, mem_length);
void* memory = mmap(NULL, mem_length, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, 0);
//récupère pointeur
GameInfo* infos_p = (GameInfo*) memory;
//stocke la structure en mémoire partagée
if(role == SERVER)
*infos_p = **infos;
//modifie le pointeur donné en signature pour qu'il pointe désormais vers la structure en mémoire partagée
*infos = infos_p;
*cards = (Card *)(++infos_p);
*offers = (CardSet*) *cards;
}
server.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <ctype.h>
#include "pit_utilities.h"
void shuffle(Card *array, size_t n);
char *usage = "Usage : ./server [NB_JOUEURS] (3 < NB_JOUEURS < 7)";
void shuffle(Card *array, size_t n) {
if(n > 1) {
size_t i;
for(i = 0; i < n - 1; i++) {
size_t j = i + rand() / (RAND_MAX / (n - i) + 1);
Card t = array[j];
array[j] = array[i];
array[i] = t;
}
}
}
int main(int argc, char *argv[])
{
srand(time(NULL));
//Initialiser données du jeu
if(argc != 2 || !isdigit(argv[1][0])) {
printf("%s\n", usage);
exit(EXIT_FAILURE);
}
int max_players = atoi(argv[1]);
if(max_players < MIN_PLAYERS || max_players > MAX_PLAYERS) {
printf("%s\n", usage);
exit(EXIT_FAILURE);
}
//1. Initialiser la mémoire
GameInfo* infos = &(GameInfo){max_players, 0, LOADING};
Card* cards;
CardSet* offers;
initialize_pit(&infos, &cards, &offers, SERVER);
printf("Chargement de la mémoire ok!\n");
//2. Remplir la mémoire de cartes puis autoriser les clients à récupérer leurs mains
int i, cards_count = infos->max_players * MAX_CARDS;
for(i = 0; i < cards_count; i++)
cards[i] = card_map[i % NB_TYPES];
shuffle(cards, cards_count);
printf("\nNombre de joueurs max : %d\n", infos->max_players);
printf("Nombre de joueurs courant : %d\n", infos->connected);
printf("Etat du jeu : %d\n\n", infos->state);
for(i = 0; i < cards_count; i++)
printf("%7s\t%s", card_string[cards[i]], ((i + 1) % MAX_CARDS == 0) ? "\n" : "");
infos->state = GETTING_CARDS;
printf("\nEtat du jeu : %d\n", infos->state);
//3. Lancer le jeu
while(1){}
return 0;
}
client.c
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <ctype.h>
#include "pit_utilities.h"
void show_hand(Card* cards, int index);
char* actions_menu =
"ACTIONS:\
-------\
offrir [QUANTITE][RESSOURCE][...]\
voir\
prendre [NUMERO]";
int player_nb;
void show_hand(Card* cards, int index)
{
int count[NB_TYPES] = { 0 };
int i;
for(i = 0; i < MAX_CARDS; i++)
count[cards[index+i]]++;
printf("\nVotre main:\n");
for(i = 0; i < MAX_CARDS; i++)
{
if(count[index+i] > 0)
printf("%d %s\n", count[index+i], card_string[cards[i]]);
}
}
int main(int argc, char *argv[])
{
GameInfo* infos;
Card* cards;
CardSet* offers;
printf("Lancement du client...");
initialize_pit(&infos, &cards, &offers, CLIENT);
printf("Chargement terminé.\n");
//Vérifications préalables sur l'état du jeu
if(infos->max_players == infos->connected)
{
printf("La partie est déjà pleine!\n");
exit(EXIT_FAILURE);
}
else if(infos->state != LOADING && infos->state != GETTING_CARDS)
{
printf("La partie a déjà démarré!\n");
exit(EXIT_FAILURE);
}
//Ajout à la partie
player_nb = 0;
//Attente de la distribution des cartes
printf("En attente de la distribution des cartes...\n");
while(infos->state != GETTING_CARDS)
{
sleep(1);
}
//Récupération des cartes
show_hand(cards, NB_TYPES * player_nb);
int i;
for(i = 0; i < MAX_CARDS * (infos->max_players); i++)
printf("%7s\t%s", card_string[cards[i]], ((i + 1) % MAX_CARDS == 0) ? "\n" : "");
//Attente du début de la partie
printf("En attente du lancement de la partie...\n");
fflush(stdout);
while(infos->state != PLAYING)
{
sleep(1);
}
//Menu
show_hand(cards, NB_TYPES * player_nb);
printf("%s", actions_menu);
}