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

news2024/11/19 4:22:49

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

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

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

目录

  • 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 运行结果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1687366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在未来你将何去何从?

在数字化的浪潮中&#xff0c;信息技术行业无疑是推动全球经济和社会发展的重要动力。随着科技的不断迭代与进步&#xff0c;云计算、大数据、人工智能&#xff08;AI&#xff09;、物联网&#xff08;IoT&#xff09;、5G通信和区块链等技术已经深入到我们生活的每一个角落&am…

Python调用科大讯飞在线语音合成API --内附完整项目

一&#xff0c;注册讯飞账号&#xff0c;并实名制。 讯飞开放平台-以语音交互为核心的人工智能开放平台 (xfyun.cn) 二、找到音频合成&#xff0c;按页面提示申请免费试用。 在线语音合成_免费试用-讯飞开放平台 (xfyun.cn) 三、申请免费使用后&#xff0c;找到API信息如下…

数据仓库ETL

小白的数据仓库学习笔记 2024/5/20 18:25 文章目录 ETLdim打开创建项目&#xff08;选这个&#xff0c;这个是做etl的&#xff09;建立元数据的连接同样的&#xff0c;建立与数据仓库的连接新建ssis包序列容器全量etl增量etl建立sql任务双击打开&#xff0c;设置连接、内容 双击…

共享单车(八):数据库

实现后台数据库访问模块的框架&#xff0c;能够实现验证请求并响应&#xff08;支持数据库操作&#xff09;。 数据库设计 class SqlTabel //负责数据库表的创建 { public:SqlTabel(std::shared_ptr<MysqlConnection> sqlconn) :sqlconn_(sqlconn) {}bool CreateUserI…

BeautifulSoup4通过lxml使用Xpath,以及获取(定位)元素和其文本或者属性

环境&#xff1a;win10&#xff0c;python3.8.10 首先需要安装&#xff1a;beautifulsoup4&#xff0c;lxml 使用命令&#xff1a; pip38 install beautifulsoup4 pip38 install lxml 安装完毕后查看一下&#xff1a; 写代码&#xff1a; from bs4 import BeautifulSoup …

5.24机器人基础-入门1

参考书籍&#xff1a;《机器人学导论》John.J.Craig 机器人方面的学习和线性代数、矩阵论部分的学习密切相关&#xff0c;建议先学习线性代数会更好理解此部分内容。虽然学了线代但是能忘的都忘得差不多的我要泪目了。本文主要介绍基础的运动学和动力学区别&#xff0c;正向运…

RocketMQ 架构原理

注册中心 注册中心使用得nameserver, nameserver不会进行频繁的读写&#xff0c;所以整体的性能开销小&#xff0c;稳定性也高。 注册中心没隔10s会扫描一次所有的broker&#xff0c;如果2min没有发送心跳过来&#xff0c;就人为挂了&#xff0c;断开连接。此时会更新topic与队…

IEN在Web3.0中的性能与安全优势

随着Web3.0的快速发展&#xff0c;优化网络基础设施变得至关重要。智能生态网络&#xff08;Intelligent Ecological Network, IEN&#xff09;作为新一代网络架构&#xff0c;在提升性能与增强安全方面展现出巨大潜力。本文将深入探讨IEN在Web3.0中的技术优势&#xff0c;并展…

Linux安装Docker教程(实测可用)

前言 Docker是一个开源的应用容器引擎&#xff0c;它允许开发者将应用程序及其依赖打包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上。以下是对Docker的具体介绍&#xff1a; 技术起源&#xff1a;容器技术起源于程序员对于环境搭建与应用部署效…

data studio连接到虚拟机上的openGauss

参考&#xff1a;使用DataStudio连接本地虚拟机中的opengauss数据库_big data_白日梦想家_胖七七-华为云开发者联盟 本实验虚拟机安装的是CentOS7 数据库版本是&#xff1a;openGauss-5.0.2-CentOS-64bit-all.tar.gz 1.配置pg_hba.conf 首先使用su - omm登录到omm用户&…

FPGA搭积木之按键消抖(改进版)

目录 1.前言 2.回顾之前的设计 3.基于读者思路的设计 4.ModelSim仿真 1.前言 昨天分享的关于FPGA对机械按键消抖的设计&#xff0c;有读者指出了其中的不足&#xff0c;并给出了他的思路。今天就读者的设计思路&#xff0c;来再做一个按键消抖模块。这个程序大概是大学的时…

arping 一键检测网络设备连通性(KALI工具系列二)

目录 1、KALI LINUX简介 2、arping工具简介 3、在KALI中使用arping 3.1 目标主机IP&#xff08;win&#xff09; 3.2 KALI的IP 4、操作示例 4.1 IP测试 4.2 ARP测试 4.3 根据存活情况返回 5、总结 1、KALI LINUX简介 Kali Linux 是一个功能强大、多才多艺的 Linux 发…

建投数据收获客户感谢信

建投数据自2021年提出“以数据为核心的智能科技服务商”&#xff0c;并一直在为“成为国内领先的数字化转型合作伙伴”而努力&#xff0c;在赋能行业客户创造更大价值的同时&#xff0c;也陆续收到来自客户的肯定。 建投数据始终践行“成就客户&#xff0c;创新为要&#xff0…

科技引领乡村振兴新潮流:运用现代信息技术手段,提升农业生产和乡村管理效率,打造智慧化、现代化的美丽乡村

一、引言 随着科技的不断进步&#xff0c;现代信息技术已经渗透到社会的各个领域&#xff0c;成为推动社会发展的重要力量。在乡村振兴战略的背景下&#xff0c;科技的力量同样不容忽视。本文旨在探讨如何运用现代信息技术手段&#xff0c;提升农业生产和乡村管理效率&#xf…

2024 年 电工杯(B题)大学生数学建模挑战赛 | 平衡膳食食谱 | 数学建模完整代码+建模过程全解全析

当大家面临着复杂的数学建模问题时&#xff0c;你是否曾经感到茫然无措&#xff1f;作为2022年美国大学生数学建模比赛的O奖得主&#xff0c;我为大家提供了一套优秀的解题思路&#xff0c;让你轻松应对各种难题。 CS团队倾注了大量时间和心血&#xff0c;深入挖掘解决方案。通…

k8s遇到的错误记录

时隔四年有开始重新鼓捣k8s了&#xff0c;重新安装后遇到的错误记录如下&#xff1a; Error: Package: kubelet-1.14.0-0.x86_64 (kubernetes) Requires: kubernetes-cni 0.7.5 Available: kubernetes-cni-0.3.0.1-0.07a8a2.x86_64 (kubernetes) …

自学有点吃力,需不需要报六西格玛培训班学习?

在追求职业精进和企业管理优化的道路上&#xff0c;六西格玛管理方法论已经成为不少企业和个人的首选。然而&#xff0c;自学六西格玛往往伴随着一系列挑战&#xff0c;让不少学习者感到吃力。面对这样的困境&#xff0c;我们不禁要问&#xff1a;自学有点吃力&#xff0c;到底…

Docker 部署Jenkins

1、运行镜像 docker run --namejenkins \--restartalways \--privilegedtrue \-u root \-p 8080:8080 \-p 50000:50000 \-v /home/docker/jenkins/jenkins_home:/var/jenkins_home \-v /usr/bin/docker:/usr/bin/docker \-v /var/run/docker.sock:/var/run/docker.sock \-e TZ…

二十一、openlayers官网示例Custom Controls解析——自定义控件扩展Control类

官网demo地址&#xff1a; Custom Controls 这个示例讲的是如何自定义控件 首先创建了一个新的类继承了原本的Control&#xff0c;新增了一个button元素&#xff0c;然后调用了super方法将参数传给了父类。 const button document.createElement("button");button.…

《Rust奇幻之旅:从Java和C++开启》第1章Hello world 2/5

讲动人的故事,写懂人的代码 很多程序员都在自学Rust。 🤕但Rust的学习曲线是真的陡,让人有点儿怵头。 程序员工作压力大,能用来自学新东西的时间简直就是凤毛麟角。 📕目前,在豆瓣上有7本Rust入门同类书。它们虽有高分评价,但仍存在不足。 首先,就是它们介绍的Rust新…