本地对弈五子棋(以命名管道进行通信)

 

初步的界面如下:

为了实现不同的窗口、不同进程弈五子棋对弈,就需要在不同进程间的进行通信,我们采用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\n", 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\n", 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\n");
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\n",READ_FIFO);
14     }
15     if( (mkfifo(WRITE_FIFO, FILE_MODE) < 0) && (errno == EEXIST)){
16         printf("can't create %s\n",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\n",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交换一下就可以与此端通信

 

posted @ 2014-08-19 21:03  木白木又寸  阅读(432)  评论(0编辑  收藏  举报