Linux程序开发(十一):进程与进程间通信设计之趣味猫咪抓老鼠游戏

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊!

喜欢我的博客的话,记得点个红心❤️和小关小注哦!您的支持是我创作的动力!数据源存放在我的资源下载区啦!

Linux程序开发(十一):进程与进程间通信设计之趣味猫咪抓老鼠游戏

题目:猫咪抓老鼠游戏

题目描述:

小明有一只猫咪和几只老鼠,他想编写一个Linux下的C程序来实现猫咪捉老鼠的游戏。具体来说,程序中需要启动两个进程,一个进程代表猫咪,另一个进程代表老鼠。猫咪和老鼠在一个二维平面上移动,猫咪的初始位置随机生成,老鼠的初始位置也随机生成。猫咪和老鼠每次移动时,会随机选择上下左右四个方向之一,然后向该方向移动一个单位距离。如果猫咪和老鼠的位置重合,则猫咪抓住老鼠,游戏结束。
请你编写一个C程序,实现猫咪抓老鼠的游戏。程序需要满足以下要求:
1、猫咪和老鼠的初始位置、移动速度等参数需要在程序运行时由用户输入。
2、程序需要启动两个进程,分别代表猫咪和老鼠。
3、进程间需要通过消息队列进行通信,猫咪和老鼠每次移动后需要将自己的位置信息发送给对方进程。
4、程序需要使用信号量和互斥锁等机制来实现进程间同步和互斥访问共享资源(如二维平面上的位置信息)。
5、程序需在猫咪抓住老鼠或一定时间内未能抓住老鼠时结束,并输出游戏结果。

示例输入:

请输入猫咪和老鼠的移动速度:10
请输入游戏时间(秒):30

示例输出:

猫咪和老鼠的初始位置为:(3, 5) 和 (7, 9)
游戏结束,猫咪抓住了老鼠!

提示:

可使用Linux系统函数fork()来创建进程。
可使用Linux系统函数msgget()、msgsnd()和msgrcv()来创建和使用消息队列。
可使用Linux系统函数sem_init()、sem_wait()、sem_post()和sem_destroy()来创建和使用信号量。
可使用Linux系统函数pthread_mutex_init()、pthread_mutex_lock()、pthread_mutex_unlock()和pthread_mutex_destroy()来创建和使用互斥锁。

解答:

# pthread.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/msg.h>
#include <pthread.h>
#include <semaphore.h> // 添加头文件

#define MSG_TYPE_CAT 1
#define MSG_TYPE_MOUSE 2

// 定义消息结构体
struct Message {
    long type;
    int x;
    int y;
};

// 定义互斥锁和信号量
pthread_mutex_t mutex;
sem_t sem;

// 定义全局变量
int catX, catY, mouseX, mouseY;
int gameResult = 0;

void* catThread(void* arg) {
    key_t* pMsgId = (key_t*)arg; // 修改参数类型为 key_t*
    struct Message msg;

    while (!gameResult) {
        // 猫咪向随机方向移动
        pthread_mutex_lock(&mutex);
        int dx = rand() % 3 - 1;
        int dy = rand() % 3 - 1;
        catX += dx;
        catY += dy;
        if (catX < 0) catX = 0;
        if (catX > 20) catX = 20;
        if (catY < 0) catY = 0;
        if (catY > 20) catY = 20;
        pthread_mutex_unlock(&mutex);

        // 发送猫咪的位置消息给老鼠
        msg.type = MSG_TYPE_CAT;
        msg.x = catX;
        msg.y = catY;
        msgsnd(*pMsgId, &msg, sizeof(msg), 0); // 使用间接寻址操作获取 msgId

        // 等待老鼠的位置消息
        msgrcv(*pMsgId, &msg, sizeof(msg), MSG_TYPE_MOUSE, 0);

        // 判断是否抓住老鼠
        if (msg.x == catX && msg.y == catY) {
            gameResult = 1;
            printf("游戏结束,猫咪抓住了老鼠!\n");
        }

        // 等待一段时间
        usleep(1000000 / *(int*)arg);
    }

    return NULL;
}

void* mouseThread(void* arg) {
    key_t* pMsgId = (key_t*)arg; // 修改参数类型为 key_t*
    struct Message msg;

    while (!gameResult) {
        // 老鼠向随机方向移动
        pthread_mutex_lock(&mutex);
        int dx = rand() % 3 - 1;
        int dy = rand() % 3 - 1;
        mouseX += dx;
        mouseY += dy;
        if (mouseX < 0) mouseX = 0;
        if (mouseX > 20) mouseX = 20;
        if (mouseY < 0) mouseY = 0;
        if (mouseY > 20) mouseY = 20;
        pthread_mutex_unlock(&mutex);

        // 发送老鼠的位置消息给猫咪
        msg.type = MSG_TYPE_MOUSE;
        msg.x = mouseX;
        msg.y = mouseY;
        msgsnd(*pMsgId, &msg, sizeof(msg), 0); // 使用间接寻址操作获取 msgId

        // 等待猫咪的位置消息
        msgrcv(*pMsgId, &msg, sizeof(msg), MSG_TYPE_CAT, 0);

        // 判断是否被猫咪抓住
        if (msg.x == mouseX && msg.y == mouseY) {
            gameResult = 2;
            printf("游戏结束,老鼠被猫咪抓住了!\n");
        }

        // 等待一段时间
        usleep(1000000 / *(int*)arg);
    }

    return NULL;
}

int main() {
    int speed, gameTime;
    pid_t pid;
    key_t msgId;
    pthread_t catTid, mouseTid;

    srand(time(NULL));

    // 获取输入参数
    printf("请输入猫咪和老鼠的移动速度:");
    scanf("%d", &speed);
    printf("请输入游戏时间(秒):");
    scanf("%d", &gameTime);

    // 初始化互斥锁和信号量
    pthread_mutex_init(&mutex, NULL);
    sem_init(&sem, 0, 1);

    // 随机生成猫咪和老鼠的初始位置
    catX = rand() % 21;
    catY = rand() % 21;
    mouseX = rand() % 21;
    mouseY = rand() % 21;

    // 输出初始位置
    printf("猫咪和老鼠的初始位置为:(%d, %d) 和 (%d, %d)\n", catX, catY, mouseX, mouseY);

    // 创建消息队列
    msgId = msgget(IPC_PRIVATE, IPC_CREAT | 0666);
    if (msgId < 0) {
        printf("Failed to create message queue!\n");
        return 1;
    }

    // 创建猫咪进程
    pid = fork();
    if (pid == 0) {
        catThread(&msgId); // 修改函数调用,传递 msgId 变量的指针
        return 0;
    } else if (pid < 0) {
        printf("Failed to create cat process!\n");
        return 1;
    }

    // 创建老鼠进程
    pid = fork();
    if (pid == 0) {
        mouseThread(&msgId); // 修改函数调用,传递 msgId 变量的指针
        return 0;
    } else if (pid < 0) {
        printf("Failed to create mouse process!\n");
        return 1;
    }

    // 等待一段时间
    sleep(gameTime);

    // 结束游戏
    gameResult = 3;

    // 销毁互斥锁和信号量
    pthread_mutex_destroy(&mutex);
    sem_destroy(&sem);

    return 0;
}

截图:

在这里插入图片描述
图 2.1 运行结果图

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卡林神不是猫

如果您觉得有帮助可以鼓励小卡哦

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值