• 基于Qt的在线抢答系统


    目录

    Server客户端

    Server.pro

    tcpserver.h

    thread.h

    tcpsocket.h

    db.h

    user.h

    myserver.h

    ------------------

    tcpserver.cpp

    thread.cpp

    tcpsocket.cpp

    db.cpp

    user.cpp

    myserver.cpp

    main.cpp

    Client客户端

    Client.pro

    register.h

    login.h

    communicate.h

    brainstorm.h

    ------------------

    register.cpp

    login.cpp

    communicate.cpp

    brainstorm.cpp

    main.cpp


    1. 开发环境/工具: Linux,QT,libevent库,Mysql数据库,jsoncpp库。
    2. 基于 Qt 平台:分别在 windows 和 Linux 下构建客户端和服务器,实现“头脑 风暴”                            在线对战小游戏。
    3. 实现功能:实现了用户注册、用户登录、排位匹配对战答题、个人训练答题、段位记                      录系统、段位匹配系统等功能。

    Server服务器端

    Server.pro

    补上需要的代码:

    1. CONFIG += console c++11
    2. #jsoncpp
    3. LIBS +=-L/usr/local/lib -levent -lpthread -lmysqlclient -ljson

    tcpserver.h

    1. #ifndef TCPSERVER_H
    2. #define TCPSERVER_H
    3. #include"thread.h"
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include"tcpsocket.h"
    11. class TcpSocket;
    12. //Tcp服务器的基类
    13. class TcpServer
    14. {
    15. friend class TcpSocket;
    16. public:
    17. TcpServer(int threadNum=8);
    18. int listen(int port, const char *ip=NULL);
    19. //服务器开始运行
    20. void start();
    21. protected:
    22. //监听回调函数,有客户端连接的时候会调用
    23. static void listenCb(struct evconnlistener *, evutil_socket_t fd, struct sockaddr *clientAdd, int socklen, void *data);
    24. //监听处理函数
    25. void listenEvent(evutil_socket_t fd, struct sockaddr_in *clientAdd);
    26. //--------虚函数,去具体处理客户端的逻辑--------
    27. //客户端连接事件
    28. virtual void connectEvent(TcpSocket *){}
    29. //客户端可读事件
    30. virtual void readEvent(TcpSocket *){}
    31. //客户端可写事件
    32. virtual void writeEvent(TcpSocket *){}
    33. //客户端可读事件
    34. virtual void closeEvent(TcpSocket *,short){}
    35. private:
    36. int m_threadNum;//线程个数
    37. Thread *m_threadPool;//线程池
    38. struct event_base *m_base;
    39. struct evconnlistener *m_listener;//监听客户端的连接(事件)。类似于监听套接字。
    40. int m_nextThread; //记录下一个线程的下标
    41. };
    42. #endif // TCPSERVER_H

    thread.h

    1. #ifndef THREAD_H
    2. #define THREAD_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. class Thread
    11. {
    12. public:
    13. Thread();
    14. void start();//线程运行
    15. //获取事件集合
    16. struct event_base *getBase();
    17. protected:
    18. //在类的内部调用回调函数就要变成静态,加static
    19. static void* worker(void*);//线程的工作函数
    20. static void pipeRead(evutil_socket_t,short,void *);//管道可读
    21. void run(); //线程的逻辑处理函数
    22. private:
    23. struct event_base *m_base;//事件集合
    24. pthread_t m_threadId; //线程ID
    25. int m_pipeReadFd; //管道的读端
    26. int m_pipeWriteFd; //管道的写端
    27. struct event m_pipeEvent; //管道事件
    28. };
    29. #endif // THREAD_H

    tcpsocket.h

    1. #ifndef TCPSOCKET_H
    2. #define TCPSOCKET_H
    3. #include"tcpserver.h"
    4. #include
    5. class TcpServer;
    6. //通信类,负责与客户端进行通信
    7. class TcpSocket
    8. {
    9. public:
    10. TcpSocket(TcpServer *tcpServer, struct bufferevent *bev, char *ip, u_int16_t port);
    11. //可读事件的回调函数
    12. static void readEventCb(struct bufferevent *bev,void *etc);
    13. //可写事件的回调函数
    14. static void writeEventCb(struct bufferevent *bev,void *etc);
    15. //异常事件的回调函数
    16. static void closeEventCb(struct bufferevent *bev,short what,void *etc);
    17. char *getIp();//获取IP地址
    18. u_int16_t getPort();//获取端口
    19. //从客户端读数据
    20. int readDate(void *data, int size);
    21. //向客户端写数据
    22. int writeDate(const void *data, int size);
    23. void setUserName(std::string name);
    24. std::string getUserName();
    25. private:
    26. static TcpServer *m_tcpServer;//服务器类对象。需要初始化
    27. struct bufferevent *m_bev;//通信用的句柄,用来与客户端通信
    28. char *m_ip; //客户端的IP地址
    29. u_int16_t m_port; //客户端的端口
    30. std::string _userName;//当前使用他这个用户
    31. };
    32. #endif // TCPSOCKET_H

    db.h

    1. #ifndef DB_H
    2. #define DB_H
    3. #include"mysql/mysql.h"
    4. #include
    5. #include
    6. #include
    7. class DB
    8. {
    9. public:
    10. DB(const char *host,const char *userName,const char *passwd,const char *dbName);
    11. //执行数据库语句
    12. bool db_exec(const char *sql);
    13. //数据库查询
    14. //[in] sql 查询语句
    15. //[out] outJson 查询结果到json变量中
    16. bool db_select(const char *sql,Json::Value &outJson);
    17. private:
    18. std::mutex _mutex;//数据库句柄互斥锁
    19. MYSQL *_mysql;//数据库
    20. };
    21. #endif // DB_H

    user.h

    1. #ifndef USER_H
    2. #define USER_H
    3. #include
    4. #include"tcpsocket.h"
    5. class User
    6. {
    7. public:
    8. User(std::string n,std::string p,int rank,TcpSocket *s);
    9. TcpSocket *getSocket();
    10. const char *getName();
    11. int getRank();
    12. void setRank(int rank);
    13. private:
    14. std::string _userName; //用户名
    15. std::string _passwd; //用户密码
    16. int _rank; //rank分数
    17. TcpSocket *_s; //通信类套接字
    18. };
    19. #endif // USER_H

    myserver.h

    1. #ifndef MYSERVER_H
    2. #define MYSERVER_H
    3. #include"tcpserver.h"
    4. #include
    5. #include"db.h"
    6. #include
    7. #include
    8. #include"../common.h"
    9. #include
    10. #include
    11. #include"user.h"
    12. #define DEBUG
    13. //#define QUESTION_NUM 5
    14. class MyServer:public TcpServer//继承
    15. {
    16. public:
    17. MyServer();
    18. void connectEvent(TcpSocket *);
    19. void readEvent(TcpSocket *);
    20. void writeEvent(TcpSocket *);
    21. void closeEvent(TcpSocket *s, short);
    22. private:
    23. //发送数据
    24. void writeData(TcpSocket *s,const Json::Value &inJson);
    25. //用户注册
    26. void Register(TcpSocket *s,const Json::Value &inJson);
    27. //用户登录
    28. void Login(TcpSocket *s,const Json::Value &inJson);
    29. //获取个人训练题目
    30. void get_SingleQuestion(TcpSocket *s);
    31. //进行排位
    32. void Rank(TcpSocket *s);
    33. //rank 回答一道问题
    34. void rankAnswerOneQuestion(TcpSocket *s,const Json::Value &inJson);
    35. //开始对决
    36. void startRank(TcpSocket *first,TcpSocket *second);
    37. //rank结果
    38. void rankResult(TcpSocket *s, const Json::Value &inJson);
    39. //初始化rank积分对照表
    40. void initRankMap();
    41. private:
    42. std::shared_ptr _log;//记录日志的句柄
    43. DB* _db;//数据库句柄
    44. //键是用户名,值是用户指针
    45. std::mutex _userLock;//锁_Users
    46. std::map _users; //在线用户列表
    47. //key : rank积分
    48. //值 : 对应的段位说明
    49. std::map<int,std::string> _rankMap; //rank积分比对表
    50. //key : rank积分
    51. //value : 参与rank的用户socket句柄
    52. std::mutex _rankLock;
    53. std::map<int,TcpSocket*> _rankQueue; //等待排位的队列
    54. };
    55. #endif // MYSERVER_H

    ---------------------------------------------------------------------------------------------------------------------------------

    tcpserver.cpp

    1. #include "tcpserver.h"
    2. TcpServer::TcpServer(int threadNum):m_nextThread(0)//下标初始化为0
    3. {
    4. if(threadNum<=0)
    5. {
    6. printf("threadNum<=0");
    7. exit(-1);
    8. }
    9. m_threadNum=threadNum;
    10. m_threadPool=new Thread[threadNum];
    11. if(m_threadPool==NULL)
    12. {
    13. printf("create threadPool error\n");
    14. exit(-1);
    15. }
    16. m_base=event_base_new();
    17. if(!m_base)
    18. {
    19. printf("Could not initialize libevent!\n");
    20. exit(-1);
    21. }
    22. }
    23. //evutil_socket_t fd: 与客户端通信的文件描述符
    24. //struct sockaddr *clientAdd: 客户端的IP地址,地址信息。
    25. void TcpServer::listenCb(struct evconnlistener *,evutil_socket_t fd,struct sockaddr *clientAdd,int ,void *data)
    26. {
    27. TcpServer *p=(TcpServer*)data;
    28. p->listenEvent(fd,(struct sockaddr_in *)clientAdd);
    29. }
    30. void TcpServer::listenEvent(evutil_socket_t fd,struct sockaddr_in *clientAdd)
    31. {
    32. char *ip =inet_ntoa(clientAdd->sin_addr);//客户端的IP地址
    33. uint16_t port=ntohs(clientAdd->sin_port);//客户端的使用的端口
    34. //从线程池中选择一个线程去处理客户端的请求
    35. //以论寻的方式选择线程
    36. struct event_base *base=m_threadPool[m_nextThread].getBase();
    37. m_nextThread=(m_nextThread+1) % m_threadNum;
    38. //base监测fd
    39. struct bufferevent *bev=bufferevent_socket_new(base,fd,BEV_OPT_CLOSE_ON_FREE);
    40. if(!bev)
    41. {
    42. fprintf(stderr,"Error constructing bufferevent!");
    43. event_base_loopbreak(base);
    44. return;
    45. }
    46. //创建一个对象
    47. TcpSocket *s=new TcpSocket(this,bev,ip,port);
    48. //单独封装一个类负责和客户端的通信
    49. bufferevent_setcb(bev,s->readEventCb,s->writeEventCb,s->closeEventCb,s);
    50. bufferevent_enable(bev,EV_WRITE);//打开是否可写
    51. bufferevent_enable(bev,EV_READ);//打开是否可读
    52. bufferevent_enable(bev,EV_SIGNAL);
    53. //调用客户端连接函数
    54. connectEvent(s);
    55. }
    56. int TcpServer::listen(int port,const char *ip)
    57. {
    58. struct sockaddr_in sin;
    59. memset(&sin,0,sizeof(sin));
    60. sin.sin_family=AF_INET;
    61. sin.sin_port=htons(port);
    62. if(ip!=NULL)
    63. inet_aton(ip,&sin.sin_addr);
    64. m_listener=evconnlistener_new_bind(m_base,listenCb,this,LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,-1,(struct sockaddr*)&sin,sizeof(sin));
    65. if(!m_listener)
    66. {
    67. printf("Could not create a listener!\n");
    68. return -1;
    69. }
    70. //开启线程池
    71. for(int i=0;i
    72. {
    73. m_threadPool[i].start();
    74. printf("线程 %d 启动\n",i+1);
    75. }
    76. return 0;
    77. }
    78. void TcpServer::start()
    79. {
    80. event_base_dispatch(m_base);
    81. evconnlistener_free(m_listener);
    82. event_base_free(m_base);
    83. printf("done\n");
    84. }

    thread.cpp

    1. #include "thread.h"
    2. Thread::Thread()
    3. {
    4. m_base=event_base_new();
    5. if(!m_base)
    6. {
    7. printf("Couldn't creat an event_base:exiting\n");
    8. exit(-1);
    9. }
    10. //在构造函数里创建管道
    11. int fd[2];
    12. if (pipe(fd) == -1)
    13. {
    14. perror("fork");
    15. exit(-1);
    16. }
    17. //管道的读写端
    18. m_pipeReadFd=fd[0];
    19. m_pipeWriteFd=fd[1];
    20. //让管道事件监听管道的读端
    21. //如果监听到,管道的读端有数据可读
    22. //EV_READ:监听管道是否有可读事件
    23. //EV_PERSIST:让事件永久有效,不然读完一次下次就不监听了
    24. //pipeRead:管道事件来了之后自动调用这个函数,类似于槽函数
    25. event_set(&m_pipeEvent,m_pipeReadFd,EV_READ | EV_PERSIST,pipeRead,this);
    26. //将事件添加到m_base集合中
    27. event_base_set(m_base,&m_pipeEvent);
    28. //开始事件的监听
    29. event_add(&m_pipeEvent,0);
    30. }
    31. void Thread::pipeRead(int, short, void *)
    32. {
    33. }
    34. void Thread::start()
    35. {
    36. //创建线程
    37. pthread_create(&m_threadId,NULL,worker,this);
    38. //线程分离
    39. pthread_detach(m_threadId);
    40. }
    41. void* Thread::worker(void* arg)
    42. {
    43. Thread* p=(Thread*)arg;
    44. p->run(); //
    45. return NULL;
    46. }
    47. void Thread::run()
    48. {
    49. /*测试用的
    50. while(1)
    51. {
    52. printf("thread:%d\n",m_threadId);
    53. sleep(2);
    54. }
    55. */
    56. //printf("%d:start\n",m_threadId);
    57. //监听base事件集合
    58. //dispatch是一个死循环,一直监听。用来处理事件,类似于qt的exec()
    59. //如果m_base集合是空的,则event_base_dispatch不运行会立马返回
    60. //初始化的时候需要给m_base添加一个事件,让它不空
    61. event_base_dispatch(m_base);
    62. event_base_free(m_base);
    63. //printf("%d:done\n",m_threadId);
    64. }
    65. struct event_base *Thread::getBase()
    66. {
    67. return m_base;
    68. }

    tcpsocket.cpp

    1. #include "tcpsocket.h"
    2. TcpServer *TcpSocket::m_tcpServer=NULL;
    3. TcpSocket::TcpSocket(TcpServer *tcpServer,struct bufferevent *bev,char *ip,u_int16_t port)
    4. {
    5. m_tcpServer=tcpServer;
    6. m_bev=bev;
    7. m_ip=ip;
    8. m_port=port;
    9. }
    10. //可读事件的回调函数
    11. void TcpSocket::readEventCb(struct bufferevent *,void *etc)
    12. {
    13. TcpSocket *s=(TcpSocket*)etc;
    14. m_tcpServer->readEvent(s);
    15. }
    16. //可写事件的回调函数
    17. void TcpSocket::writeEventCb(struct bufferevent *,void *etc)
    18. {
    19. TcpSocket *s=(TcpSocket*)etc;
    20. m_tcpServer->writeEvent(s);
    21. }
    22. //异常事件的回调函数
    23. void TcpSocket::closeEventCb(struct bufferevent *,short what,void *etc)
    24. {
    25. TcpSocket *s=(TcpSocket*)etc;
    26. m_tcpServer->closeEvent(s,what);
    27. delete s;
    28. }
    29. char *TcpSocket::getIp()
    30. {
    31. return m_ip;
    32. }
    33. u_int16_t TcpSocket::getPort()
    34. {
    35. return m_port;
    36. }
    37. //从客户端读数据
    38. int TcpSocket::readDate(void *data,int size)
    39. {
    40. return bufferevent_read(m_bev,data,size);
    41. }
    42. //向客户端写数据
    43. int TcpSocket::writeDate(const void *data,int size)
    44. {
    45. return bufferevent_write(m_bev,data,size);
    46. }
    47. void TcpSocket::setUserName(std::string name)
    48. {
    49. _userName=name;
    50. }
    51. std::string TcpSocket::getUserName()
    52. {
    53. return _userName;
    54. }

    db.cpp

    1. #include "db.h"
    2. DB::DB(const char *host, const char *userName, const char *passwd, const char *dbName)
    3. {
    4. //初始化数据库句柄
    5. _mysql =mysql_init(NULL);
    6. if(_mysql==NULL)
    7. {
    8. spdlog::get("BrainStorm")->error("mysql_init error\n");
    9. exit(-1);
    10. }
    11. //连接数据库
    12. MYSQL *con=mysql_real_connect(_mysql,host,userName,passwd,dbName,0,NULL,0);
    13. if(con==NULL)
    14. {
    15. spdlog::get("BrainStorm")->error("连接数据库失败:{}",mysql_error(_mysql));
    16. exit(-1);
    17. }
    18. _mysql=con;
    19. //设置字符集
    20. int ret=mysql_query(_mysql,"set names utf8");//设置中文
    21. if(ret!=0)
    22. {
    23. spdlog::get("BrainStorm")->error("设置字符集失败:%s",mysql_error(_mysql));
    24. exit(-1);
    25. }
    26. }
    27. bool DB::db_exec(const char *sql)
    28. {
    29. std::unique_lock loc(_mutex);//智能锁,数据库句柄上锁
    30. int ret=mysql_query(_mysql,sql);
    31. if(ret!=0)
    32. {
    33. spdlog::get("BrainStorm")->error("mysql_query error:%s",mysql_error(_mysql));
    34. return false;
    35. }
    36. return true;
    37. }
    38. bool DB::db_select(const char *sql,Json::Value &outJson)
    39. {
    40. std::unique_lock loc(_mutex);//智能锁,数据库句柄上锁
    41. int ret=mysql_query(_mysql,sql);
    42. if(ret!=0)
    43. {
    44. spdlog::get("BrainStorm")->error("mysql_query error:%s",mysql_error(_mysql));
    45. return false;
    46. }
    47. //从mysql服务器下载查询结果
    48. MYSQL_RES *sql_res=mysql_store_result(_mysql);
    49. if(sql_res==NULL)
    50. {
    51. if(mysql_errno(_mysql)==0)
    52. {
    53. return true;
    54. }
    55. else
    56. {
    57. spdlog::get("BrainStorm")->error("mysql_store_result error:%s",mysql_error(_mysql));
    58. }
    59. }
    60. //看字段,先看有多少列,
    61. MYSQL_ROW row;//从结果集中一行一行获取
    62. unsigned int num_fields=mysql_num_fields(sql_res);//获取列数
    63. MYSQL_FIELD *fetch_field=mysql_fetch_field(sql_res);//获取表头(字段)
    64. //一行一行的获取数据结构
    65. while(row=mysql_fetch_row(sql_res))//然后就要填这个数据结构
    66. {
    67. for(unsigned int i=0;i
    68. {
    69. outJson[fetch_field[i].name].append(row[i]);
    70. }
    71. }
    72. //获取完把结构给删掉
    73. mysql_free_result(sql_res);
    74. return true;
    75. }

    user.cpp

    1. #include "user.h"
    2. User::User(std::string n,std::string p,int rank,TcpSocket *s)
    3. :_userName(n),_passwd(p),_rank(rank),_s(s)
    4. {
    5. }
    6. TcpSocket *User::getSocket()
    7. {
    8. return _s;
    9. }
    10. const char *User::getName()
    11. {
    12. return _userName.c_str();
    13. }
    14. int User::getRank()
    15. {
    16. return _rank;
    17. }
    18. void User::setRank(int rank)
    19. {
    20. if(rank<=0)
    21. rank=0;
    22. _rank=rank;
    23. }

    myserver.cpp

    1. #include "myserver.h"
    2. MyServer::MyServer()
    3. {
    4. //日志
    5. #ifdef DEBUG//向控制台写
    6. _log=spdlog::stdout_color_mt("console");
    7. #else
    8. _log=spdlog::rotating_logger_mt("BrainStorm","BrainStorm",1024*1024*5,3);
    9. _log->flush_on(spdlog::level::info);
    10. #endif
    11. //_log->info("11111111111");//写在控制台
    12. _db=new DB(NULL,"xiaowang","xiaowang","BrainStorm");
    13. initRankMap();
    14. }
    15. void MyServer::connectEvent(TcpSocket *s)
    16. {
    17. _log->info("有一个新的连接[{}:{}]\n",s->getIp(),s->getPort());
    18. //printf("客户端连接%s","端口连接%s",s->getIp(),s->getPort());
    19. }
    20. void MyServer::readEvent(TcpSocket *s)
    21. {
    22. char buf[1024]={0};
    23. while(1)
    24. {
    25. int len=0;
    26. s->readDate(&len,sizeof(len));
    27. if(len<=0)
    28. break;
    29. s->readDate(buf,len);
    30. //数据解析
    31. Json::Value root;
    32. Json::Reader reader;//json解析器
    33. if(!reader.parse(buf,root))
    34. {
    35. _log->error("json数据解析失败");
    36. return;
    37. }
    38. int cmd=root["cmd"].asInt();
    39. switch (cmd)
    40. {
    41. case REGISTER:
    42. Register(s,root);
    43. break;
    44. case LOGIN:
    45. Login(s,root);
    46. break;
    47. case SINGLE_QUESTION:
    48. get_SingleQuestion(s);
    49. break;
    50. case RANK:
    51. Rank(s);
    52. break;
    53. case ANSWER:
    54. rankAnswerOneQuestion(s,root);
    55. break;
    56. case RANKRESULT:
    57. rankResult(s,root);
    58. break;
    59. default:
    60. break;
    61. }
    62. }
    63. }
    64. void MyServer::writeEvent(TcpSocket *)
    65. {
    66. }
    67. void MyServer::closeEvent(TcpSocket *s,short)
    68. {
    69. //将用户从 等待 rank 的列表中删除
    70. {
    71. std::unique_lock _lock(_rankLock);
    72. int rank=_users[s->getUserName()]->getRank();
    73. auto it=_rankQueue.find(rank);//然后从队列里面去找他
    74. if(it != _rankQueue.end())
    75. _rankQueue.erase(it);
    76. }
    77. //printf("客户端退出,ip:%s,端口:%d\n",s->getIp(),s->getPort());
    78. //_log->error("用户{}[{}:{}] logout",userName,s->getIp(),s->getPort());
    79. std::unique_lock _lock(_userLock);
    80. std::map::iterator it=_users.begin();
    81. while(it!=_users.end())
    82. {
    83. if(it->second->getSocket()==s)
    84. {
    85. _users.erase(it);
    86. _log->info("用户{}[{}:{}] logout",it->second->getName(),s->getIp(),s->getPort());
    87. break;
    88. //移除完之后释放User
    89. delete it->second;
    90. return;
    91. }
    92. it++;
    93. }
    94. _log->info("用户{}[{}:{}] logout",s->getIp(),s->getPort());
    95. }
    96. void MyServer::writeData(TcpSocket *s,const Json::Value &inJson)
    97. {
    98. std::string data=inJson.toStyledString();
    99. s->writeDate(data.c_str(),data.length());
    100. }
    101. void MyServer::Register(TcpSocket *s,const Json::Value &inJson)
    102. {
    103. std::string userName=inJson["userName"].asString();
    104. std::string passwd=inJson["passwd"].asString();
    105. //检测用户是否已经存在
    106. char sql[100]={0};
    107. sprintf(sql,"select *from user where name='%s' and passwd='%s'",userName.c_str(),passwd.c_str());
    108. int result=OK;
    109. Json::Value outJson;
    110. bool ret=_db->db_select(sql,outJson);
    111. if(!ret)
    112. {
    113. result=ERROR;
    114. _log->error("Register select user error");
    115. }
    116. if(outJson.isMember("name")) //用户存在,表明已经做过了
    117. result=USEREXIST;
    118. else
    119. {
    120. sprintf(sql,"insert into user(name,passwd,rank) values('%s','%s',0)",userName.c_str(),passwd.c_str());
    121. bool ret=_db->db_exec(sql);
    122. if(!ret)
    123. {
    124. result=ERROR;
    125. _log->error("Register insert user error");
    126. }
    127. else
    128. _log->info("Register user={} succeed",userName);
    129. }
    130. //最后整合数据
    131. Json::Value json;
    132. json ["cmd"]=REGISTER;
    133. json ["result"]=result;
    134. writeData(s,json);
    135. }
    136. void MyServer::Login(TcpSocket *s,const Json::Value &inJson)
    137. {
    138. std::string userName=inJson["userName"].asString();
    139. std::string passwd=inJson["passwd"].asString();
    140. int rank=0;
    141. //检测用户是否已经登录
    142. char sql[100]={0};
    143. sprintf(sql,"select *from user where name='%s' and passwd='%s'",userName.c_str(),passwd.c_str());
    144. int result=OK;
    145. Json::Value outJson;
    146. bool ret=_db->db_select(sql,outJson);
    147. if(!ret)
    148. {
    149. result=ERROR;
    150. _log->error("Login select user error");
    151. }
    152. if(outJson.isMember("name")) //用户存在,表明已经注册了
    153. {
    154. std::unique_lock _lock(_userLock);//先上一把锁
    155. if(_users.find(userName)!=_users.end())//用户已经登录
    156. result=USERLOGIN;
    157. else
    158. {
    159. int i=0;
    160. rank=atoi(outJson["rank"][i].asString().c_str());
    161. User* user=new User(userName,passwd,rank,s);
    162. _users.insert(make_pair(userName,user));//用户创建完,把他放进列表里,user为指针
    163. _log->info("用户{}[{}:{}] login",userName,s->getIp(),s->getPort());
    164. s->setUserName(userName);
    165. }
    166. }
    167. else
    168. result=NAMEORPASSWD;
    169. //最后整合数据
    170. Json::Value json;
    171. json ["cmd"] =LOGIN;
    172. json ["result"] =result;
    173. json ["userName"]=userName;
    174. json ["rank"] =_rankMap[rank];
    175. writeData(s,json);
    176. }
    177. void MyServer::get_SingleQuestion(TcpSocket *s)
    178. {
    179. char sql[100]={0};
    180. sprintf(sql,"select * from question order by rand() limit %d",QUESTION_NUM);
    181. int result=OK;
    182. Json::Value outJson;
    183. bool ret=_db->db_select(sql,outJson);
    184. if(!ret || outJson["question"].size()!=QUESTION_NUM)
    185. {
    186. result=ERROR;
    187. _log->error("get_SingleQuestion select question error");
    188. }
    189. Json::Value json;
    190. json ["cmd"] =SINGLE_QUESTION;
    191. json ["result"] =result;
    192. json ["question"]=outJson;
    193. _log->info("用户{}[{}:{}] 获取题目: {}\n",s->getUserName(),s->getIp(),s->getPort(),json.toStyledString());
    194. //服务器把数据发送给客户端
    195. writeData(s,json);
    196. }
    197. void MyServer::startRank(TcpSocket *first,TcpSocket *second)
    198. {
    199. char sql[100]={0};
    200. sprintf(sql,"select * from question order by rand() limit %d",QUESTION_NUM);
    201. int result=OK;
    202. Json::Value outJson;
    203. bool ret=_db->db_select(sql,outJson);
    204. if(!ret || outJson["question"].size()!=QUESTION_NUM)
    205. {
    206. result=ERROR;
    207. _log->error("startRank select question error");
    208. }
    209. Json::Value json;
    210. json ["cmd"] =RANK;
    211. json ["result"] =result;
    212. json ["question"]=outJson;
    213. //first user
    214. json ["enemyName"] =second->getUserName();
    215. json ["enemyRank"] =_rankMap[_users[second->getUserName()]->getRank()];
    216. json ["enemyScore"]=0;
    217. writeData(first,json);
    218. //second user
    219. json ["enemyName"] =first->getUserName();
    220. json ["enemyRank"] =_rankMap[_users[first->getUserName()]->getRank()];
    221. writeData(second,json);
    222. _log->info(" 获取 rank 题目: {}\n",json.toStyledString());
    223. }
    224. void MyServer::Rank(TcpSocket *s)
    225. {
    226. TcpSocket *other=NULL;//对手
    227. int rank=_users[s->getUserName()]->getRank();//当前用户 rank 积分
    228. std::unique_lock lock(_rankLock);
    229. //查找同一段位的对手
    230. std::map<int,TcpSocket*>::iterator it=_rankQueue.find(rank);
    231. if(it!=_rankQueue.end())//找到了
    232. {
    233. other=it->second;
    234. _rankQueue.erase(it);
    235. }
    236. else
    237. {
    238. //查找其他段位的选手 积分差值的绝对值小于5的都可以进行对决
    239. for(int i=0;i<=5;i++)
    240. {
    241. it=_rankQueue.find(rank+i);
    242. if(it!=_rankQueue.end())
    243. {
    244. other=it->second;
    245. _rankQueue.erase(it);
    246. break;
    247. }
    248. it=_rankQueue.find(rank-i);
    249. if(it!=_rankQueue.end())
    250. {
    251. other=it->second;
    252. _rankQueue.erase(it);
    253. break;
    254. }
    255. }
    256. }
    257. _log->info("rank 分数:{}",rank);
    258. if(other==NULL)//没有匹配到用户
    259. {
    260. _rankQueue.insert(std::make_pair(rank,s));
    261. _log->info("当前等候 rank 人数:{}",_rankQueue.size());
    262. }
    263. else//找到
    264. {
    265. //开始对决
    266. startRank(s,other);
    267. }
    268. }
    269. void MyServer::rankAnswerOneQuestion(TcpSocket *s,const Json::Value &inJson)
    270. {
    271. std::string enemyName=inJson["enemyName"].asString();
    272. User *user=_users[enemyName];
    273. Json::Value json;
    274. json ["cmd"] =ANSWER;
    275. json ["enemyscore"] =inJson["score"].asInt();
    276. json ["enemyQuestionId"]=inJson["questionId"].asInt();
    277. writeData(user->getSocket(),json);
    278. }
    279. void MyServer::rankResult(TcpSocket *s,const Json::Value &inJson)
    280. {
    281. std::unique_lock lock(_userLock);
    282. User *user=_users[s->getUserName()];
    283. int score =inJson["score"].asInt();
    284. int enemyscore=inJson["enemyscore"].asInt();
    285. if(score
    286. user->setRank(user->getRank()-1);
    287. else if(score>enemyscore)
    288. user->setRank(user->getRank()+1);
    289. Json::Value json;
    290. json ["cmd"] =RANKRESULT;
    291. json ["newRank"] =_rankMap[user->getRank()];
    292. writeData(s,json);//发送给客户端
    293. }
    294. void MyServer::initRankMap()
    295. {
    296. char buf[100]={0};
    297. int rank=0;
    298. int num=0;
    299. for(int i=0;i<100;i++)
    300. {
    301. if(i<9)
    302. {
    303. rank=i/3;
    304. num=i%3;
    305. sprintf(buf,"青铜%d %d颗星",3-rank,num+1);
    306. }
    307. else if(9<=i && i<18)
    308. {
    309. rank=(i-9)/3;
    310. num=(i-9)%3;
    311. sprintf(buf,"白银%d %d颗星",3-rank,num+1);
    312. }
    313. else if(9<=i && i<18)
    314. {
    315. rank=(i-9)/4;
    316. num=(i-9)%4;
    317. sprintf(buf,"黄金%d %d颗星",4-rank,num+1);
    318. }
    319. else if(18<=i && i<34)
    320. {
    321. rank=(i-18)/4;
    322. num=(i-18)%4;
    323. sprintf(buf,"铂金%d %d颗星",4-rank,num+1);
    324. }
    325. else if(34<=i && i<50)
    326. {
    327. rank=(i-34)/5;
    328. num=(i-34)%5;
    329. sprintf(buf,"钻石%d %d颗星",5-rank,num+1);
    330. }
    331. else if(50<=i && i<75)
    332. {
    333. rank=(i-50)/5;
    334. num=(i-50)%5;
    335. sprintf(buf,"星曜%d %d颗星",5-rank,num+1);
    336. }
    337. _rankMap.insert(std::make_pair(i,buf));
    338. }
    339. /*
    340. for(int i=0;i<100;i++)
    341. {
    342. std::cout<
    343. }
    344. */
    345. }

    main.cpp

    1. #include
    2. #include"thread.h"
    3. #include"tcpserver.h"
    4. #include"myserver.h"
    5. using namespace std;
    6. int main1()
    7. {
    8. Thread *pt1=new Thread;
    9. Thread *pt2=new Thread;
    10. pt1->start();
    11. pt2->start();
    12. while(1)
    13. {
    14. printf("1111\n");
    15. sleep(1);
    16. }
    17. return 0;
    18. }
    19. int main2()
    20. {
    21. TcpServer s;
    22. s.listen(9999);
    23. s.start();
    24. return 0;
    25. }
    26. int main()
    27. {
    28. MyServer s;
    29. s.listen(9999);
    30. s.start();
    31. return 0;
    32. }

    Client客户端

    Client.pro

    补上需要的代码:

    1. QT += core gui network

    register.h

    1. #ifndef REGISTER_H
    2. #define REGISTER_H
    3. #include
    4. #include
    5. #include"communicate.h"
    6. #include"../common.h"
    7. namespace Ui {
    8. class Register;
    9. }
    10. class Register : public QDialog
    11. {
    12. Q_OBJECT
    13. public:
    14. explicit Register(Communicate *com,QWidget *parent = 0);
    15. ~Register();
    16. private slots:
    17. void on_RegNButton_clicked();
    18. void on_BackButton_clicked();
    19. void rstResult(int);
    20. private:
    21. Ui::Register *ui;
    22. Communicate *_com;
    23. };
    24. #endif // REGISTER_H

    login.h

    1. #ifndef WIDGET_H
    2. #define WIDGET_H
    3. #include
    4. #include"register.h"
    5. #include"communicate.h"
    6. namespace Ui {
    7. class Widget;
    8. }
    9. class Widget : public QWidget
    10. {
    11. Q_OBJECT
    12. public:
    13. explicit Widget(QWidget *parent = 0);
    14. ~Widget();
    15. private slots:
    16. void on_LogButton_clicked();
    17. void on_RegButton_clicked();
    18. void login(QJsonObject json);
    19. private:
    20. Ui::Widget *ui;
    21. Communicate *_com;//通信类指针,负责和服务器通信
    22. };
    23. #endif // WIDGET_H

    communicate.h

    1. #ifndef COMMUNICATE_H
    2. #define COMMUNICATE_H
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include"../common.h"
    8. #include
    9. class Communicate : public QObject
    10. {
    11. Q_OBJECT
    12. public:
    13. explicit Communicate(QObject *parent = nullptr);
    14. void writeData(const QJsonObject &json);
    15. signals:
    16. void rstResult(int );
    17. void login(QJsonObject json);
    18. void receiveSingleQuestion(QJsonObject json);
    19. void Rank(QJsonObject json);
    20. public slots:
    21. void readData();
    22. private:
    23. QTcpSocket s;
    24. };
    25. #endif // COMMUNICATE_H

    brainstorm.h

    1. #ifndef BRAINSTORM_H
    2. #define BRAINSTORM_H
    3. #include
    4. #include"communicate.h"
    5. #include
    6. #include
    7. namespace Ui {
    8. class BrainStorm;
    9. }
    10. class BrainStorm : public QDialog
    11. {
    12. Q_OBJECT
    13. public:
    14. explicit BrainStorm(Communicate *_com,QJsonObject &json,QWidget *parent = 0);
    15. ~BrainStorm();
    16. private:
    17. //单人训练,从服务器获取题目
    18. void getSingleQuestion();
    19. //单人训练设置问题
    20. void SingleSetQuestion();
    21. //单人训练答题
    22. void SingleAnswerQuestion(int select);
    23. //设置得分
    24. void setEnemyScore();
    25. void setSelfScore();
    26. //--------------------------------------------------------
    27. //rank设置问题
    28. void rankSetQuestion();
    29. //rank结果
    30. void rankSetResult(QJsonObject &json);
    31. //rank答题
    32. void RankAnswerQuestion(int select);
    33. private slots:
    34. void on_RankButton_clicked();
    35. void on_SingleButton_clicked();
    36. void on_SingleBack_clicked();
    37. void on_SingleStart_clicked();
    38. //单人训练从服务器接收到题目
    39. void receiveSingleQuestion(QJsonObject json);
    40. //个人训练计时器
    41. void SingleTimerOut();
    42. void on_OverBack_clicked();
    43. void on_SingleButtonA_clicked();
    44. void on_SingleButtonB_clicked();
    45. void on_SingleButtonC_clicked();
    46. void on_SingleButtonD_clicked();
    47. //----------------------------------------------------------------------
    48. //接受排位
    49. void Rank(QJsonObject json);
    50. //排位计时器
    51. void RankTimerOut();
    52. void on_RankButtonA_clicked();
    53. void on_RankButtonB_clicked();
    54. void on_RankButtonC_clicked();
    55. void on_RankButtonD_clicked();
    56. void on_overButton_clicked();
    57. private:
    58. Ui::BrainStorm *ui;
    59. Communicate *_com; //通信类指针,负责和服务器通信
    60. QJsonObject _singleQuestion;
    61. int _currentSingleQuestion;//当前回答哪一个问题的下标
    62. QTimer _singleTimer; //个人训练定时器
    63. int _singleSec; //个人训练答题时间
    64. int _singleScore; //个人训练得分
    65. //----------------------Rank---------------------
    66. QJsonObject _rankQuestion; //rank的题
    67. QString _enemyName;//对手的名字
    68. QString _enemyRank;//对手的段位
    69. int _enemyScore; //对手的得分
    70. int _rankSec; //rank 答题计时
    71. int _myScore; //自己的得分
    72. QString _userName;//自己的名字
    73. QString _userRank;//自己的段位
    74. int _currentRankQuestion;//当前回答哪一个问题的下标
    75. int _enemyRankQuestion;//对手当前回答问题的下标
    76. QTimer _rankTimer; //排位定时器
    77. };
    78. #endif // BRAINSTORM_H

    ---------------------------------------------------------------------------------------------------------------------------------

    register.cpp

    1. #include "register.h"
    2. #include "ui_register.h"
    3. #include
    4. Register::Register(Communicate *com,QWidget *parent) :
    5. QDialog(parent),
    6. ui(new Ui::Register)
    7. {
    8. ui->setupUi(this);
    9. _com=com;
    10. connect(_com,SIGNAL(rstResult(int)),this,SLOT(rstResult(int)));
    11. }
    12. Register::~Register()
    13. {
    14. delete ui;
    15. }
    16. void Register::on_RegNButton_clicked()
    17. {
    18. QString userName=ui->UserlineEdit->text();
    19. QString passwd=ui->PasswdlineEdit->text();
    20. //发送注册信息
    21. QJsonObject json;
    22. json["cmd"]=REGISTER;
    23. json["userName"]=userName;
    24. json["passwd"]=passwd;
    25. //给服务器发送数据
    26. _com->writeData(json);
    27. }
    28. void Register::rstResult(int ret)
    29. {
    30. switch (ret)
    31. {
    32. case OK:
    33. QMessageBox::information(this,"注册","注册成功");
    34. break;
    35. case ERROR:
    36. QMessageBox::critical(this,"注册","注册失败,未知错误");
    37. break;
    38. case USEREXIST:
    39. QMessageBox::critical(this,"注册","注册失败,用户存在");
    40. break;
    41. default:
    42. break;
    43. }
    44. }
    45. void Register::on_BackButton_clicked()
    46. {
    47. close();
    48. }

    login.cpp

    1. #include "login.h"
    2. #include "ui_widget.h"
    3. #include"register.h"
    4. #include
    5. #include"brainstorm.h"
    6. #include"../common.h"
    7. Widget::Widget(QWidget *parent) :
    8. QWidget(parent),
    9. ui(new Ui::Widget)
    10. {
    11. ui->setupUi(this);
    12. _com=new Communicate();
    13. connect(_com,SIGNAL(login(QJsonObject)),this,SLOT(login(QJsonObject)));
    14. }
    15. Widget::~Widget()
    16. {
    17. delete ui;
    18. }
    19. void Widget::on_LogButton_clicked()
    20. {
    21. QString userName=ui->UserlineEdit->text();
    22. QString passwd=ui->PasswdlineEdit->text();
    23. //将登录信息发送给服务器
    24. QJsonObject json;
    25. json["cmd"]=LOGIN;
    26. json["userName"]=userName;
    27. json["passwd"]=passwd;
    28. //给服务器发送数据
    29. _com->writeData(json);
    30. }
    31. void Widget::login(QJsonObject json)
    32. {
    33. int result=json["result"].toInt();
    34. switch (result)
    35. {
    36. case OK:
    37. {
    38. this->hide();
    39. BrainStorm *dlg=new BrainStorm(_com,json);
    40. dlg->show();
    41. dlg->setAttribute(Qt::WA_DeleteOnClose);//属性,把new出来的自己销毁
    42. break;
    43. }
    44. case ERROR:
    45. QMessageBox::critical(this,"登录","登录失败,未知错误");
    46. break;
    47. case USERLOGIN:
    48. QMessageBox::critical(this,"登录","登录失败,不允许重复登录");
    49. break;
    50. case NAMEORPASSWD:
    51. QMessageBox::critical(this,"登录","用户名或密码错误");
    52. break;
    53. default:
    54. break;
    55. }
    56. }
    57. void Widget::on_RegButton_clicked()
    58. {
    59. this->hide();
    60. Register reg(_com);
    61. reg.exec();
    62. this->show();
    63. }

    communicate.cpp

    1. #include "communicate.h"
    2. #include
    3. Communicate::Communicate(QObject *parent) : QObject(parent)
    4. {
    5. //连接服务器
    6. s.connectToHost(QHostAddress("***.***.***.***"),****);
    7. connect(&s,SIGNAL(readyRead()),this,SLOT(readData()));
    8. }
    9. void Communicate::readData()
    10. {
    11. QByteArray data;
    12. while(s.bytesAvailable())
    13. {
    14. data +=s.readAll();//读完
    15. }
    16. //数据解析
    17. QJsonDocument dt=QJsonDocument::fromJson(data);//通过QJsonDocument转换成json字符串
    18. if(dt.isNull())//没有读到数据
    19. {
    20. return;
    21. }
    22. QJsonObject root=dt.object();//拿到json这样的一个对象
    23. //具体的逻辑处理
    24. int cmd=root["cmd"].toInt();
    25. switch (cmd)
    26. {
    27. case REGISTER:
    28. emit rstResult(root["result"].toInt());//发给注册那一端
    29. break;
    30. case LOGIN:
    31. emit login(root);//发给注册那一端
    32. break;
    33. case SINGLE_QUESTION:
    34. emit receiveSingleQuestion(root["question"].toObject());
    35. break;
    36. case RANK:
    37. emit Rank(root);
    38. break;
    39. case ANSWER:
    40. emit Rank(root);
    41. break;
    42. case RANKRESULT:
    43. emit Rank(root);
    44. break;
    45. default:
    46. break;
    47. }
    48. }
    49. void Communicate::writeData(const QJsonObject &json)
    50. {
    51. QJsonDocument d(json);
    52. QByteArray sendData=d.toJson();
    53. int len=sendData.size();
    54. s.write((char *)&len,sizeof(int));//发送数据长度
    55. s.write(sendData);//发送数据
    56. }

    brainstorm.cpp

    1. #include "brainstorm.h"
    2. #include "ui_brainstorm.h"
    3. BrainStorm::BrainStorm(Communicate *com, QJsonObject &json, QWidget *parent) :
    4. QDialog(parent),
    5. ui(new Ui::BrainStorm)
    6. {
    7. ui->setupUi(this);
    8. _com=com;
    9. _userName=json["userName"].toString();
    10. _userRank=json["rank"].toString();
    11. connect(&_singleTimer,SIGNAL(timeout()),this,SLOT(SingleTimerOut()));
    12. connect(&_rankTimer,SIGNAL(timeout()),this,SLOT(RankTimerOut()));
    13. connect(_com,SIGNAL(receiveSingleQuestion(QJsonObject)),this,SLOT(receiveSingleQuestion(QJsonObject)));
    14. connect(_com,SIGNAL(Rank(QJsonObject)),this,SLOT(Rank(QJsonObject)));
    15. }
    16. BrainStorm::~BrainStorm()
    17. {
    18. delete ui;
    19. }
    20. //进入个人训练赛
    21. void BrainStorm::on_SingleButton_clicked()
    22. {
    23. ui->stackedWidget->setCurrentWidget(ui->SingleMenu);
    24. }
    25. //个人训练计时器
    26. void BrainStorm::SingleTimerOut()
    27. {
    28. --_singleSec;
    29. if(_singleSec==0)
    30. {
    31. ui->Singleresult->setText("回答错误");
    32. QString str=QString("本次得分:%1").arg(_singleScore);
    33. ui->Singlescore->setText(str);
    34. _singleTimer.stop();
    35. ui->stackedWidget->setCurrentWidget(ui->SingleScore);
    36. }
    37. ui->lcdNumber->display(_singleSec);
    38. }
    39. //单人训练,从服务器获取题目
    40. void BrainStorm::getSingleQuestion()
    41. {
    42. QJsonObject json;
    43. json["cmd"]=SINGLE_QUESTION;
    44. _com->writeData(json);
    45. }
    46. //单人训练设置问题
    47. void BrainStorm::SingleSetQuestion()
    48. {
    49. //题目结束
    50. if(_currentSingleQuestion==QUESTION_NUM)
    51. {
    52. ui->Singleresult->setText("恭喜全部答对");
    53. QString str=QString("本次得分:%1").arg(_singleScore);
    54. ui->Singlescore->setText(str);
    55. ui->stackedWidget->setCurrentWidget(ui->SingleScore);
    56. _singleTimer.stop();
    57. return;
    58. }
    59. ui->SingleQuestion->setText(_singleQuestion["question"].toArray().at(_currentSingleQuestion).toString());
    60. ui->SingleButtonA->setText(_singleQuestion["selectionA"].toArray().at(_currentSingleQuestion).toString());
    61. ui->SingleButtonB->setText(_singleQuestion["selectionB"].toArray().at(_currentSingleQuestion).toString());
    62. ui->SingleButtonC->setText(_singleQuestion["selectionC"].toArray().at(_currentSingleQuestion).toString());
    63. ui->SingleButtonD->setText(_singleQuestion["selectionD"].toArray().at(_currentSingleQuestion).toString());
    64. }
    65. //单人训练答题
    66. void BrainStorm::SingleAnswerQuestion(int select)
    67. {
    68. //回答正确
    69. if(select==_singleQuestion["answer"].toArray().at(_currentSingleQuestion).toString().toInt())
    70. {
    71. _singleScore +=20*_singleSec;
    72. _currentSingleQuestion++;
    73. SingleSetQuestion(); //设置下一题
    74. _singleSec=10;
    75. _singleTimer.stop();
    76. ui->lcdNumber->display(_singleSec);
    77. _singleTimer.start(1000);
    78. }
    79. else//回答错误
    80. {
    81. ui->Singleresult->setText("回答错误");
    82. QString str=QString("本次得分:%1").arg(_singleScore);
    83. ui->Singlescore->setText(str);
    84. ui->stackedWidget->setCurrentWidget(ui->SingleScore);
    85. _singleTimer.stop();
    86. }
    87. }
    88. //单人训练从服务器接收到题目
    89. void BrainStorm::receiveSingleQuestion(QJsonObject json)
    90. {
    91. _singleQuestion=json;
    92. _singleSec=10;
    93. _currentSingleQuestion=0;
    94. _singleScore=0;
    95. ui->lcdNumber->display(_singleSec);
    96. SingleSetQuestion();
    97. //开启定时器
    98. _singleTimer.start(1000);
    99. ui->stackedWidget->setCurrentWidget(ui->SingleRuning);
    100. }
    101. //从个人训练返回
    102. void BrainStorm::on_SingleBack_clicked()
    103. {
    104. ui->stackedWidget->setCurrentWidget(ui->MainMenu);
    105. }
    106. //个人训练赛开始答题
    107. void BrainStorm::on_SingleStart_clicked()
    108. {
    109. getSingleQuestion();
    110. }
    111. void BrainStorm::on_OverBack_clicked()
    112. {
    113. ui->stackedWidget->setCurrentWidget(ui->MainMenu);
    114. }
    115. void BrainStorm::on_SingleButtonA_clicked()
    116. {
    117. SingleAnswerQuestion(1);
    118. }
    119. void BrainStorm::on_SingleButtonB_clicked()
    120. {
    121. SingleAnswerQuestion(2);
    122. }
    123. void BrainStorm::on_SingleButtonC_clicked()
    124. {
    125. SingleAnswerQuestion(3);
    126. }
    127. void BrainStorm::on_SingleButtonD_clicked()
    128. {
    129. SingleAnswerQuestion(4);
    130. }
    131. //--------------------------------------rank------------------------------------------
    132. //排位赛
    133. void BrainStorm::on_RankButton_clicked()
    134. {
    135. QJsonObject json;
    136. json["cmd"]=RANK;
    137. _com->writeData(json);
    138. //跳到等待页面
    139. ui->stackedWidget->setCurrentWidget(ui->RankWait);
    140. }
    141. void BrainStorm::RankTimerOut()
    142. {
    143. _rankSec--;
    144. if(_rankSec==0)
    145. {
    146. if(ui->RankButtonA->isEnabled())//判断随便一个按钮状态
    147. {
    148. _currentRankQuestion++;
    149. }
    150. rankSetQuestion();
    151. _rankSec=10;
    152. }
    153. ui->lcdNumber_2->display(_rankSec);
    154. }
    155. void BrainStorm::setEnemyScore()
    156. {
    157. QString str=QString("%1(%2):%3").arg(_enemyName,-5).arg(_enemyRank).arg(_enemyScore);
    158. ui->enemyStatus->setText(str);
    159. }
    160. void BrainStorm::setSelfScore()
    161. {
    162. QString str=QString("%1(%2):%3").arg(_userName,-5).arg(_userRank).arg(_myScore);
    163. ui->selfStatus->setText(str);
    164. }
    165. void BrainStorm::rankSetQuestion()
    166. {
    167. ui->RankQuestion->setText(_rankQuestion["question"].toArray().at(_currentRankQuestion).toString());
    168. ui->RankButtonA->setText(_rankQuestion["selectionA"].toArray().at(_currentRankQuestion).toString());
    169. ui->RankButtonB->setText(_rankQuestion["selectionB"].toArray().at(_currentRankQuestion).toString());
    170. ui->RankButtonC->setText(_rankQuestion["selectionC"].toArray().at(_currentRankQuestion).toString());
    171. ui->RankButtonD->setText(_rankQuestion["selectionD"].toArray().at(_currentRankQuestion).toString());
    172. ui->RankButtonA->setEnabled(true);
    173. ui->RankButtonB->setEnabled(true);
    174. ui->RankButtonC->setEnabled(true);
    175. ui->RankButtonD->setEnabled(true);
    176. ui->RankButtonA->setStyleSheet("");
    177. ui->RankButtonB->setStyleSheet("");
    178. ui->RankButtonC->setStyleSheet("");
    179. ui->RankButtonD->setStyleSheet("");
    180. if(_currentRankQuestion==QUESTION_NUM)
    181. {
    182. _rankTimer.stop();
    183. //将结果发给服务器
    184. QJsonObject json;
    185. json["cmd"] =RANKRESULT;
    186. json["score"] =_myScore;
    187. json["enemyName"] =_enemyName;
    188. json["enemyScore"]=_enemyScore;
    189. _com->writeData(json);
    190. }
    191. }
    192. void BrainStorm::rankSetResult(QJsonObject &json)
    193. {
    194. QString newRank=json["newRank"].toString();
    195. if(_myScore==_enemyScore)
    196. ui->rankResult->setText("平局");
    197. else if(_myScore<_enemyScore)
    198. ui->rankResult->setText("失败");
    199. else if(_myScore>_enemyScore)
    200. ui->rankResult->setText("成功");
    201. QString str=QString("%1 ---> %2").arg(_userRank).arg(newRank);
    202. ui->newRank->setText(str);
    203. _userRank=newRank;
    204. ui->stackedWidget->setCurrentWidget(ui->RankResult);
    205. }
    206. void BrainStorm::Rank(QJsonObject json)
    207. {
    208. int cmd=json["cmd"].toInt();
    209. if(cmd==RANK)
    210. {
    211. _rankQuestion=json["question"].toObject();
    212. _enemyName =json["enemyName"].toString();
    213. _enemyRank =json["enemyRank"].toString();
    214. _enemyScore =json["enemyScore"].toInt();
    215. _rankSec=10;
    216. _myScore=0;
    217. ui->lcdNumber_2->display(_rankSec);
    218. _currentRankQuestion=0;
    219. _enemyRankQuestion =0;
    220. setEnemyScore();
    221. setSelfScore();
    222. rankSetQuestion();
    223. _rankTimer.start(1000);
    224. ui->stackedWidget->setCurrentWidget(ui->RankRunning);
    225. }
    226. else if(cmd==ANSWER)//同步答题
    227. {
    228. _enemyScore =json["enemyscore"].toInt();
    229. _enemyRankQuestion=json["enemyQuestionId"].toInt();
    230. setEnemyScore();
    231. if(_currentRankQuestion==_enemyRankQuestion)
    232. {
    233. _rankSec=10;
    234. _rankTimer.stop();
    235. ui->lcdNumber_2->display(_rankSec);
    236. _rankTimer.start(1000);
    237. rankSetQuestion();
    238. }
    239. }
    240. else if(cmd==RANKRESULT)
    241. {
    242. rankSetResult(json);
    243. }
    244. }
    245. void BrainStorm::RankAnswerQuestion(int select)
    246. {
    247. //计算得分
    248. if(select==_rankQuestion["answer"].toArray().at(_currentRankQuestion).toString().toInt())
    249. _myScore +=20*_rankSec;
    250. setSelfScore();
    251. _currentRankQuestion++;
    252. //判断是否跳到下一题
    253. if(_currentRankQuestion==_enemyRankQuestion)
    254. {
    255. _rankSec=10;
    256. _rankTimer.stop();
    257. ui->lcdNumber_2->display(_rankSec);
    258. _rankTimer.start(1000);
    259. rankSetQuestion();
    260. }
    261. QJsonObject json;
    262. json["cmd"] =ANSWER;
    263. json["enemyName"]=_enemyName;
    264. json["score"] =_myScore;
    265. json["questionId"] =_currentRankQuestion;
    266. _com->writeData(json);//发送给服务器
    267. }
    268. void BrainStorm::on_RankButtonA_clicked()
    269. {
    270. ui->RankButtonA->setStyleSheet("background-color:rgb(255, 0, 0)");
    271. ui->RankButtonA->setEnabled(false);
    272. ui->RankButtonB->setEnabled(false);
    273. ui->RankButtonC->setEnabled(false);
    274. ui->RankButtonD->setEnabled(false);
    275. RankAnswerQuestion(1);
    276. }
    277. void BrainStorm::on_RankButtonB_clicked()
    278. {
    279. ui->RankButtonB->setStyleSheet("background-color:rgb(255, 0, 0)");
    280. ui->RankButtonA->setEnabled(false);
    281. ui->RankButtonB->setEnabled(false);
    282. ui->RankButtonC->setEnabled(false);
    283. ui->RankButtonD->setEnabled(false);
    284. RankAnswerQuestion(2);
    285. }
    286. void BrainStorm::on_RankButtonC_clicked()
    287. {
    288. ui->RankButtonC->setStyleSheet("background-color:rgb(255, 0, 0)");
    289. ui->RankButtonA->setEnabled(false);
    290. ui->RankButtonB->setEnabled(false);
    291. ui->RankButtonC->setEnabled(false);
    292. ui->RankButtonD->setEnabled(false);
    293. RankAnswerQuestion(3);
    294. }
    295. void BrainStorm::on_RankButtonD_clicked()
    296. {
    297. ui->RankButtonD->setStyleSheet("background-color:rgb(255, 0, 0)");
    298. ui->RankButtonA->setEnabled(false);
    299. ui->RankButtonB->setEnabled(false);
    300. ui->RankButtonC->setEnabled(false);
    301. ui->RankButtonD->setEnabled(false);
    302. RankAnswerQuestion(4);
    303. }
    304. void BrainStorm::on_overButton_clicked()
    305. {
    306. ui->stackedWidget->setCurrentWidget(ui->MainMenu);
    307. }

    main.cpp

    1. #include "login.h"
    2. #include
    3. int main(int argc, char *argv[])
    4. {
    5. QApplication a(argc, argv);
    6. Widget w;
    7. w.show();
    8. return a.exec();
    9. }

  • 相关阅读:
    Laravel框架 - IOC容器详解
    【STM32 CubeMX】移植u8g2(一次成功)
    fluke dtx-1800测试精度有必要进行原厂校准吗?
    Python接口自动化测试数据驱动DDT使用实战
    架构师之路3. 富士康 - 再也不见
    MySQL性能分析工具的使用
    Hadoop和关系型数据库间的数据传输工具——Sqoop
    中秋节祝福程序源代码分享:土地分类数据阈值筛选和重投影分类
    怎样将例化的uvn test包含在verdi的instance中,并将其中变量加入到dump的波形中(方便verdi追test以及debug)
    SpringBootWeb 篇-入门了解 Apache POI 使用方法
  • 原文地址:https://blog.csdn.net/xaf21/article/details/126525122