zoukankan      html  css  js  c++  java
  • 本地对弈五子棋(以命名管道进行通信)

    初步的界面如下:

    为了实现不同的窗口、不同进程弈五子棋对弈,就需要在不同进程间的进行通信,我们采用linux底层的命名管道进行通信。

    首先我们要进行管道通信头文件的包含、传输数据的结构定义、数据通信操作的函数定义(代码如下):

     1 #ifndef MESGOPREAT_H
     2 #define MESGOPREAT_H
     3 #include<unistd.h>
     4 #include<sys/types.h>
     5 #include<sys/wait.h>
     6 #include <sys/stat.h>
     7 #include<stdio.h>
     8 #include<stdlib.h>
     9 #include<errno.h>
    10 #include<string.h>
    11 #include <fcntl.h> //O_RDONLY
    12 #include<limits.h> //PIPE_BUF
    13 #include <QtCore>
    14 #define    MAXLINE 4088
    15 #define FILE_MODE (S_IRUSR | S_IWUSR |S_IRGRP | S_IROTH)
    16 #define READ_FIFO "/tmp/fifo.test1" //本端用来打开读
    17 #define WRITE_FIFO "/tmp/fifo.test2"//本端用来打开写
    18 
    19 //另一端如下定义
    20 
    21 //#define WRITE_FIFO "/tmp/fifo.test1" //本端用来打开读
    22 //#define  READ_FIFO"/tmp/fifo.test2"//本端用来打开写
    23 //#define
    24 #define DATASIZE  6
    25 #define MAXMESGDATA (sizeof(struct mymesg) - 2 * sizeof(long))
    26 #define MESGHDRSIZE (sizeof(struct mymesg) - MAXMESGDATA)
    27 
    28 typedef struct mymesg{
    29 
    30     long mesg_type;
    31     long mesg_len_data;
    32     int  data[DATASIZE];
    33 
    34 }Mesg;
    35 Q_DECLARE_METATYPE(Mesg)//用connect函数就需要此宏,和之后的qRegisterMetaType<Mesg>("Mesg");一同使用
    36 ssize_t mesg_send(int ,struct mymesg *);//数据发送
    37 void Mesg_send(int , struct mymesg *);//数据发送
    38 ssize_t mesg_recv(int , struct mymesg *);//数据接收
    39 
    40 #endif // MESGOPREAT_H
    MesgOpreat.h

    下面是这些函数的实现

     1 #include"MesgOpreat.h"
     2 ssize_t mesg_send(int fd, Mesg * mptr){
     3 
     4     return(write(fd, mptr, MESGHDRSIZE + mptr -> mesg_len_data));
     5 
     6 }
     7 ssize_t mesg_recv(int fd, Mesg *mptr){
     8     ssize_t len;
     9     ssize_t n;
    10     if( (n = read(fd, mptr, MESGHDRSIZE)) == 0 ){//读取头部
    11         return 0;
    12     }else if ( n != MESGHDRSIZE){ //头部长度和标准不一致时执行
    13         printf("mesg header expect %d,got %d
    ", MESGHDRSIZE, n );
    14         return 0;
    15     }
    16     if( (len = mptr -> mesg_len_data) > 0){ //在头部中获得传输数据的长度
    17         if( (n = read(fd, mptr-> data, len)) != len){   //只取得头部数据指定的数据的长度数据
    18             printf("mesg data expect %d, got %d
    ", len, n);
    19             return 0;
    20         }
    21     }
    22     return n; //返回的是数据部的长度
    23 
    24 }
    25 void Mesg_send(int fd, Mesg *mptr){
    26     ssize_t n;
    27     if( (n = mesg_send(fd, mptr)) != mptr -> mesg_len_data + MESGHDRSIZE){
    28         printf("mesg send error
    ");
    29         return ;
    30     }
    31 }
    MesgOpreat.cpp

     每一个对弈窗口会因为等待对方发送数据而卡屏,所以我们将这个阻塞的recive操作放在一个单独的线程里,我们自定义了一个类MonitorThread 它是继承QThread

     1 #ifndef MONITORTHREAD_H
     2 #define MONITORTHREAD_H
     3 #include<QDebug>
     4 #include <QThread>
     5 #include "MesgOpreat.h"
     6 
     7 class MonitorThread : public QThread
     8 {
     9     Q_OBJECT
    10 public:
    11         MonitorThread(QObject *parent);
    12         ~MonitorThread();
    13          void run();
    14 
    15 signals:
    16     void dataArived(Mesg);
    17 
    18 protected:
    19 
    20 private:
    21     Mesg mesg;
    22     int readfifo,dummyfd;
    23 };
    24 
    25 #endif // MONITORTHREAD_H
    monitorthread.h

    下面是对MonitorThread类中的一些方法的实现

     1 #include "monitorthread.h"
     2 
     3 MonitorThread::MonitorThread(QObject *parent) :
     4     QThread(parent)
     5 {
     6     start();
     7 }
     8 MonitorThread::~MonitorThread(){
     9     delete this;
    10 }
    11 void MonitorThread::run(){
    12     if( (mkfifo(READ_FIFO, FILE_MODE) < 0) && (errno == EEXIST)){
    13         printf("can't create %s
    ",READ_FIFO);
    14     }
    15     if( (mkfifo(WRITE_FIFO, FILE_MODE) < 0) && (errno == EEXIST)){
    16         printf("can't create %s
    ",WRITE_FIFO);
    17     }
    18     qDebug()<<"b";
    19     int n;
    20     qDebug()<<"d";
    21     readfifo = open(READ_FIFO, O_RDONLY,0);
    22     dummyfd = open(READ_FIFO, O_WRONLY,0);//在这里已经阻塞
    23     qDebug()<<"e";
    24     while((n = mesg_recv(readfifo, &mesg)) > 0){
    25         emit dataArived(mesg);
    26     }
    27 }
    monitorthread.cpp

    主窗体类的定义

     1 #ifndef CLIENTMAINWINDOW_H
     2 #define CLIENTMAINWINDOW_H
     3 #define MAPLENTH 10
     4 #include <QMainWindow>
     5 #include<QPushButton>
     6 #include<QGridLayout>
     7 #include "monitorthread.h"
     8 #include"MesgOpreat.h"
     9 #include<QDebug>
    10 #include<QPoint>
    11 #include<QMessageBox>
    12 class ClientMainWindow : public QMainWindow
    13 {
    14     Q_OBJECT
    15 public:
    16     explicit ClientMainWindow(QWidget *parent = 0);
    17     ~ClientMainWindow(){
    18         delete this;
    19     }
    20 signals:
    21 public slots:
    22     void Mesg_recved(Mesg);
    23     void Chess_left_Clicked();
    24 private://///////////////////////////////////////////////
    25     int flag = 0;
    26     int up_col_count = 0, low_col_count = 0, left_row_count = 0,right_row_count = 0,
    27     left_up_count = 0, right_up_count = 0,  left_low_count = 0, right_low_count = 0 ;
    28     int judge();
    29     void ergodic(int x, int y);
    30     void ergodic_up(int x, int y);//基于某一点向上第归遍历
    31     void ergodic_down(int x, int y);//基于某一点向下第归遍历
    32     void ergodic_left(int x, int y);//基于某一点向左第归遍历
    33     void ergodic_right(int x, int y);//基于某一点向右第归遍历
    34     void ergodic_left_up(int x, int y);//基于某一点向左上第归遍历
    35     void ergodic_left_low(int x, int y);//基于某一点左下第归遍历
    36     void ergodic_right_up(int x, int y);
    37     void ergodic_right_low(int x, int y);
    38     void Count_to_0();
    39     int return_judge(int x, int y);//判断第归结束的标志
    40     /////////////////////////////////////////////////////
    41 
    42     int writefifo;
    43     QPushButton  *button[MAPLENTH][MAPLENTH];
    44     MonitorThread  *thread;
    45     Mesg  mesg;
    46     QGridLayout *layout;
    47     void Init_Button();
    48     int map[MAPLENTH][MAPLENTH] = {};
    49     void StartGame();//创建命名管道与初始打开
    50     void Listen_thread();
    51 };
    52 
    53 #endif // CLIENTMAINWINDOW_H
    clientmainwindow.h

    主窗体类中方法的实现

      1 #include "clientmainwindow.h"
      2 
      3 ClientMainWindow::ClientMainWindow(QWidget *parent) :
      4     QMainWindow(parent)
      5 {
      6     qDebug()<<"a";
      7     this->setGeometry(300,600,494,521);
      8     setWindowFlags(windowFlags()& ~Qt::WindowMaximizeButtonHint);//禁止最大化
      9     setFixedSize(this->width(), this->height());//禁止最大化
     10     StartGame();
     11     qRegisterMetaType<Mesg>("Mesg");
     12     Init_Button();
     13 }
     14 
     15 void  ClientMainWindow:: Chess_left_Clicked(){
     16     qDebug()<<"left";
     17     int p_x,  p_y;
     18     QPoint  Chess_Point;
     19     QPushButton* btn= qobject_cast<QPushButton*>(sender());
     20     Chess_Point = btn->pos();
     21     p_x = (Chess_Point.y() - 13) / 50;
     22     p_y = (Chess_Point.x() - 11) / 48;
     23     qDebug()<<"p_x"<<p_x ;
     24     qDebug()<<"p_y"<<p_y;
     25     if(map[p_x][p_y] != 0){
     26         QMessageBox::about(NULL, "wring", "Occupied");
     27         return;
     28     }
     29     if(flag != 0){
     30         QMessageBox::about(NULL,"woring", "you have inputed");
     31         return;
     32     }
     33     flag = 1;
     34     button[p_x][p_y]->setIcon(QIcon(":/picture/Black.bmp"));
     35     map[p_x][p_y]= 2;
     36     mesg.mesg_type =1;
     37     mesg.mesg_len_data = DATASIZE* sizeof(int);
     38     ergodic(p_x, p_y);
     39     mesg.data[0] = p_x;
     40     mesg.data[1] = p_y;
     41     mesg.data[2]  = up_col_count + low_col_count + 1;
     42     mesg.data[3] = right_row_count + left_row_count + 1;
     43     mesg.data[4] = left_up_count + right_low_count + 1;
     44     mesg.data[5] =  left_low_count + right_up_count + 1;
     45     if( (writefifo = open(WRITE_FIFO, O_WRONLY,0)) < 0){
     46         printf("server open writefifo error: %s
    ",strerror(errno));
     47 
     48     }
     49     Mesg_send( writefifo,  &mesg);  
     50     if(judge()){
     51         QMessageBox::about(NULL, "wiring","YOU are Winer!");
     52         exit(0);
     53     }
     54 }
     55 void ClientMainWindow::StartGame(){
     56 
     57     Listen_thread();
     58 
     59 }
     60 
     61 void ClientMainWindow:: Listen_thread(){
     62     thread = new MonitorThread(this);
     63     connect(thread, SIGNAL(dataArived(Mesg)),
     64             this, SLOT(Mesg_recved(Mesg)));
     65     qDebug()<<"c";
     66 }
     67 
     68 void ClientMainWindow:: Init_Button(){
     69 
     70     layout = new QGridLayout;
     71     int pos_x = 0, pos_y = 0;
     72     for(int row = 0; row < MAPLENTH; row++){
     73         for(int col = 0; col < MAPLENTH; col++){
     74             button[row][col] = new QPushButton(this);
     75             pos_x = 48 * col + 3;
     76             pos_y = 47 * row + 2;
     77             button[row][col]->setGeometry(pos_x,pos_y,40,40); //设置button的坐标与大小
     78             button[row][col]->setMaximumSize(40,40);
     79             button[row][col]->setMinimumSize(40,40);
     80             layout->addWidget(button[row][col],row,col);
     81             QObject::connect(button[row][col],SIGNAL(clicked()),this,SLOT(Chess_left_Clicked()));
     82         }
     83     }
     84     QWidget  * widget = new QWidget(this) ;
     85     this->setCentralWidget(widget) ;
     86     widget->setLayout( layout) ;
     87 }
     88 
     89 
     90 void ClientMainWindow::Mesg_recved(Mesg _mesg){
     91 
     92     mesg = _mesg;//获得的消息
     93     button[mesg.data[0]][mesg.data[1]]->setIcon(QIcon(":/picture/White.bmp"));
     94     map[mesg.data[0]][mesg.data[1] ]= 1;
     95    // ergodic(mesg.data[0], mesg.data[1]);
     96     if(mesg.data[2] >= 5 || mesg.data[3] >= 5 || mesg.data[4]>= 5 || mesg.data[5] >= 5){
     97         QMessageBox::about(NULL, "wiring","Distinnation is Winer!");
     98         exit(0);
     99     }
    100      flag = 0;
    101 }
    102 
    103 
    104 
    105 int ClientMainWindow::judge(){
    106     if( (up_col_count + low_col_count + 1) >= 5 ||
    107             (right_row_count + left_row_count + 1) >= 5||
    108             (left_up_count + right_low_count + 1) >= 5||
    109             (left_low_count + right_up_count + 1) >= 5){
    110         return 1;
    111     }
    112     Count_to_0();
    113     return 0;
    114 }
    115 
    116 int ClientMainWindow::return_judge(int x, int y){//判断第归结束
    117     if(x < 0 || x >= MAPLENTH || y < 0 || y>= MAPLENTH  ){
    118         return 1;
    119     }
    120     return 0;
    121 }
    122 void ClientMainWindow::Count_to_0(){
    123     up_col_count = 0;
    124     low_col_count = 0;
    125     right_row_count = 0;
    126     left_row_count = 0;
    127     left_up_count  = 0;
    128     right_up_count   = 0 ;
    129     left_low_count   = 0;
    130     right_low_count  = 0;
    131 }
    132 
    133 
    134 void ClientMainWindow::ergodic_right_low(int x, int y){
    135     if( return_judge(x,  y)){
    136         return;
    137     }
    138     if(map[x][y]  != 0 && map[x + 1 ][y + 1] == map[x][y]){//向右下遍历right_low
    139         right_low_count++;
    140         ergodic_right_low(x + 1 , y + 1);
    141     }
    142 }
    143 void ClientMainWindow::ergodic_left_low(int x, int y){
    144     if( return_judge(x,  y)){
    145         return;
    146     }
    147     if(map[x][y]  != 0 && map[x + 1 ][y - 1] == map[x][y]){//向左下遍历left_low
    148         left_low_count++;
    149         ergodic_left_low(x + 1 , y - 1);
    150     }
    151 }
    152 void ClientMainWindow::ergodic_right_up(int x, int y){
    153     if( return_judge(x,  y)){
    154         return;
    155     }
    156     if(map[x][y]  != 0 && map[x - 1 ][y + 1] == map[x][y]){//向右上遍历right_up
    157         right_up_count++;
    158         ergodic_right_up(x - 1 , y + 1);
    159     }
    160 }
    161 void ClientMainWindow::ergodic_left_up(int x, int y){
    162     if( return_judge(x,  y)){
    163         return;
    164     }
    165     if(map[x][y]  != 0 && map[x - 1 ][y - 1] == map[x][y]){//向左上遍历left_up
    166         left_up_count++;
    167         ergodic_left_up(x - 1 , y - 1);
    168     }
    169 }
    170 void ClientMainWindow::ergodic_right(int x, int y){
    171     if( return_judge(x,  y)){
    172         return;
    173     }
    174     if(map[x][y]  != 0 && map[x][y + 1] == map[x][y]){//向右遍历right
    175         right_row_count++;
    176         ergodic_right(x , y + 1);
    177     }
    178 }
    179 void ClientMainWindow::ergodic_left(int x, int y){
    180     if( return_judge(x,  y)){
    181         return;
    182     }
    183     if(map[x][y]  != 0 && map[x][y - 1] == map[x][y]){//向左遍历left
    184         left_row_count++;
    185         ergodic_left(x , y - 1);
    186     }
    187 }
    188 void ClientMainWindow::ergodic_down(int x, int y){
    189     if( return_judge(x,  y)){
    190         return;
    191     }
    192     if(map[x][y] != 0  && map[x + 1][y] == map[x][y]){
    193         low_col_count++;
    194         ergodic_down(x + 1,  y);
    195     }
    196 }
    197 void ClientMainWindow::ergodic_up(int x, int y){
    198     if( return_judge(x,  y)){
    199         return;
    200     }
    201     if(map[x][y] != 0 && map[x-1][y] == map[x][y]){//向上查询up
    202         up_col_count++;
    203         ergodic_up(x - 1,  y);
    204     }
    205 }
    206 void ClientMainWindow::ergodic(int x, int y){  //各个方向进行分治第归遍历
    207     ergodic_up( x,  y);//向上
    208     ergodic_down( x,  y);//向下
    209     ergodic_left(x, y);  //向左
    210     ergodic_right(x, y);
    211     ergodic_left_up( x,  y);
    212     ergodic_left_low( x,  y);
    213     ergodic_right_up(x,  y);
    214     ergodic_right_low(x,  y);
    215 }
    clientmainwindow.cpp

    另一端只需要改变  MesgOpreat.h中的宏READ_FIFO和WRITE_FIFO交换一下就可以与此端通信

  • 相关阅读:
    高质量动漫实时画质增强器Anime4K在mpv上的配置
    grep中正则表达式使用尖括号表示一个单词
    虚拟机复制的linux无法联网,解决Bringing up interface eth0: Device eth0 does not seem to be present, delaying initialization.
    Linux将动态IP改为静态IP
    回车、换行的区别
    栈的链接存储
    栈的顺序存储
    冒泡排序
    插入排序
    双向循环链表
  • 原文地址:https://www.cnblogs.com/sangzaohaishui/p/3923062.html
Copyright © 2011-2022 走看看