编写C程序,使用Linux中的IPC机制,完成 “石头、剪子、布”的游戏;
时间: 2024-05-13 14:16:10 浏览: 293
好的,下面是使用Linux中的IPC机制编写石头剪子布游戏的C程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <time.h>
#define SHM_KEY 0x123456
#define SEM_KEY 0x654321
#define SEM_NUM 0
#define PLAYER1 0
#define PLAYER2 1
#define TIE 2
typedef struct {
int player1_score;
int player2_score;
int game_round;
int player1_choice;
int player2_choice;
} game_info;
void init_game(game_info *game) {
game->player1_score = 0;
game->player2_score = 0;
game->game_round = 0;
game->player1_choice = -1;
game->player2_choice = -1;
}
int get_player_choice() {
int choice;
printf("请输入你的选择(石头-0,剪子-1,布-2):");
scanf("%d", &choice);
return choice;
}
void print_result(int result) {
switch (result) {
case PLAYER1:
printf("player1 获胜!\n");
break;
case PLAYER2:
printf("player2 获胜!\n");
break;
case TIE:
printf("平局!\n");
break;
default:
break;
}
}
int judge(int player1_choice, int player2_choice) {
if (player1_choice == player2_choice) {
return TIE;
} else if ((player1_choice == 0 && player2_choice == 1) ||
(player1_choice == 1 && player2_choice == 2) ||
(player1_choice == 2 && player2_choice == 0)) {
return PLAYER1;
} else {
return PLAYER2;
}
}
int main() {
int sem_id, shm_id;
game_info *game;
struct sembuf sem_op;
pid_t pid;
/* 创建信号量 */
sem_id = semget(SEM_KEY, 1, IPC_CREAT | 0666);
if (sem_id < 0) {
perror("semget error");
exit(1);
}
/* 初始化信号量 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 创建共享内存 */
shm_id = shmget(SHM_KEY, sizeof(game_info), IPC_CREAT | 0666);
if (shm_id < 0) {
perror("shmget error");
exit(1);
}
/* 把共享内存映射到当前进程 */
game = (game_info *) shmat(shm_id, NULL, 0);
if (game == (void *) -1) {
perror("shmat error");
exit(1);
}
/* 初始化游戏信息 */
init_game(game);
pid = fork();
if (pid < 0) {
perror("fork error");
exit(1);
} else if (pid == 0) {
/* 子进程为 player1 */
while (1) {
/* 等待 player2 完成选择 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
printf("player1:\n");
/* 获取 player1 的选择 */
game->player1_choice = get_player_choice();
/* 通知 player2 已完成选择 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 等待 player2 完成选择 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 判断胜负 */
int result = judge(game->player1_choice, game->player2_choice);
if (result == PLAYER1) {
game->player1_score++;
} else if (result == PLAYER2) {
game->player2_score++;
}
print_result(result);
/* 通知 player2 已完成判断 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 判断是否达到游戏结束条件 */
game->game_round++;
if (game->game_round == 3) {
printf("player1 得分:%d,player2 得分:%d\n", game->player1_score, game->player2_score);
break;
}
}
} else {
/* 父进程为 player2 */
while (1) {
/* 等待 player1 完成选择 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
printf("player2:\n");
/* 获取 player2 的选择 */
game->player2_choice = get_player_choice();
/* 通知 player1 已完成选择 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 等待 player1 完成判断 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = -1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 判断胜负 */
int result = judge(game->player1_choice, game->player2_choice);
if (result == PLAYER1) {
game->player1_score++;
} else if (result == PLAYER2) {
game->player2_score++;
}
print_result(result);
/* 通知 player1 已完成判断 */
sem_op.sem_num = SEM_NUM;
sem_op.sem_op = 1;
sem_op.sem_flg = 0;
if (semop(sem_id, &sem_op, 1) < 0) {
perror("semop error");
exit(1);
}
/* 判断是否达到游戏结束条件 */
game->game_round++;
if (game->game_round == 3) {
printf("player1 得分:%d,player2 得分:%d\n", game->player1_score, game->player2_score);
break;
}
}
}
/* 把共享内存从当前进程分离 */
if (shmdt(game) < 0) {
perror("shmdt error");
exit(1);
}
/* 删除共享内存 */
if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
perror("shmctl error");
exit(1);
}
/* 删除信号量 */
if (semctl(sem_id, SEM_NUM, IPC_RMID) < 0) {
perror("semctl error");
exit(1);
}
return 0;
}
```
程序中使用了共享内存和信号量两种IPC机制。
共享内存用于存储游戏信息,包括每个玩家的得分、当前游戏回合数、每个玩家的选择等。父进程和子进程都可以访问共享内存中的数据。
信号量用于同步父进程和子进程的执行。每个玩家在选择和判断胜负时都需要等待另一个玩家完成操作后才能进行。因此,使用了一个二元信号量来实现进程的同步。
程序的执行流程如下:
1. 创建共享内存和信号量,初始化游戏信息。
2. 父进程fork一个子进程,子进程为 player1,父进程为 player2。
3. player1 和 player2 交替进行游戏,每个玩家完成选择后等待另一个玩家完成选择,然后进行判断胜负,并更新游戏信息。
4. 当游戏回合数达到3时,输出每个玩家的得分,并退出程序。
5. 删除共享内存和信号量。
阅读全文