本实验可以创建三个进程,其中,一个进程为裁判进程,另外两个进程为选手进程。可 以将“石头、剪子、布”这三招定义为三个整型值。胜负关系:石头〉剪子〉布〉石头。 选手进程按照某种策略(例如,随机产生)出招,交给裁判进程判断大小。 裁判进程将对手的出招和胜负结果通知选手。比赛可以采取多盘(>100盘)定胜负,由 裁判宣布最后结果。每次出招由裁判限定时间,超时判负。 每盘结果可以存放在文件或其他数据结构中。比赛结束,可以打印每盘的胜负情况和总的结 果。 1.设计表示“石头、剪子、布”的数据结构,以及它们之间的大小规则。 2.设计比赛结果的存放方式。 3.选择 IPC 的方法。 4.根据你所选择的 IPC 方法,创建对应的 IPC 资源。 5.完成选手进程。 6. 完成裁判进程。 --以下要求选作: 7.决出班级的前三甲,与另外班级的前三甲比赛,决出年级冠军。 8.如果有兴趣,再把这个实验改造成网络版。即在设计时就要考虑IPC层的封装。
时间: 2023-05-29 21:08:01 浏览: 373
1. 设计数据结构:
```c
// 定义三种出招,用整数表示
#define ROCK 1
#define SCISSORS 2
#define PAPER 3
// 判断胜负的函数
// 返回值:0 - 平局,1 - p1 获胜,2 - p2 获胜
int judge(int p1, int p2) {
if (p1 == p2) {
return 0;
} else if (p1 == ROCK && p2 == SCISSORS || p1 == SCISSORS && p2 == PAPER || p1 == PAPER && p2 == ROCK) {
return 1;
} else {
return 2;
}
}
```
2. 比赛结果的存放方式可以选择将每盘结果存储在一个结构体中,然后将所有结果存储在一个数组中:
```c
// 存储每盘比赛结果的结构体
typedef struct {
int round; // 第几盘比赛
int player1; // 选手1出招
int player2; // 选手2出招
int result; // 比赛结果,0 - 平局,1 - 选手1获胜,2 - 选手2获胜
} GameResult;
// 存储所有比赛结果的数组
GameResult results[100];
```
3. 选择 IPC 的方法可以使用共享内存和信号量。
4. 创建 IPC 资源,包括共享内存和信号量:
```c
// 创建共享内存
int shm_id = shmget(IPC_PRIVATE, sizeof(GameResult) * 100, IPC_CREAT | 0666);
GameResult* shm_ptr = (GameResult*)shmat(shm_id, NULL, 0);
// 创建信号量
int sem_id = semget(IPC_PRIVATE, 2, IPC_CREAT | 0666);
// 初始化信号量的值
semctl(sem_id, 0, SETVAL, 1); // 用于读写共享内存
semctl(sem_id, 1, SETVAL, 0); // 用于通知裁判选手已出招
```
5. 选手进程可以使用随机数生成出招,然后将出招写入共享内存中:
```c
// 生成随机数表示出招
int player = rand() % 3 + 1;
// 写入共享内存
sem_wait(&semaphore[0]); // 等待信号量
shm_ptr->player1 = player;
sem_post(&semaphore[0]); // 发送信号量
sem_post(&semaphore[1]); // 发送信号量通知裁判
```
6. 裁判进程可以从共享内存中读取选手的出招,然后调用判断胜负的函数,将结果写入共享内存:
```c
for (int i = 0; i < 100; i++) {
// 等待选手出招
sem_wait(&semaphore[1]);
// 读取选手出招
sem_wait(&semaphore[0]);
int player1 = shm_ptr->player1;
int player2 = shm_ptr->player2;
sem_post(&semaphore[0]);
// 判断胜负
int result = judge(player1, player2);
// 写入共享内存
sem_wait(&semaphore[0]);
shm_ptr->player2 = player2;
shm_ptr->result = result;
sem_post(&semaphore[0]);
}
```
7. 决出班级的前三甲和决出年级冠军可以在裁判进程中进行,通过统计每个选手的胜利场次来确定排名。
8. 如果要将实验改造成网络版,则需要在设计时考虑 IPC 层的封装。可以使用 socket 编程实现网络通信。选手进程和裁判进程通过网络通信,将出招和比赛结果传递,可以使用 TCP 或 UDP 协议。网络版需要实现的功能和 IPC 版本基本相同,只是需要在通信过程中加上网络协议的部分。
阅读全文