这是我的代码:
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
//全屏
this->setWindowState(windowState()^Qt::WindowFullScreen);
this->setLayout(ui->mainLayout);
ui->mainLayout->setStretchFactor(ui->listWidget,1);
ui->mainLayout->setStretchFactor(ui->stackedWidget,8);
this->setStyleSheet("QWidget{background-color:black;}");
ui->listWidget->setStyleSheet("QListWidget{background-color:black;border:2px solid green}");
ui->stackedWidget->setStyleSheet("QStackedWidget{background-color:black;border:2px solid green}");
ui->page->setLayout(ui->menuLayout);
//网络部分初始化
xAddr=getLocHostIp();
is_started=false;
tcpPort=28692;
udpPort=28692;
udpSocket=new QUdpSocket(this);
udpSocket->bind(udpPort,QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);
tcpServer=new QTcpServer(this);
tcpServer->listen(QHostAddress::Any,tcpPort);
tcpSocket=new QTcpSocket(this);
//~网络部分初始化
init_select();
init_list();
//连接
connect(ui->exitButton,&QPushButton::clicked,this,[=](){
this->close();
});
connect(ui->startButton,&QPushButton::clicked,this,&Widget::start);
connect(udpSocket,&QUdpSocket::readyRead,this,&Widget::udp_listen);
connect(tcpSocket,&QTcpSocket::readyRead,this,&Widget::tcp_listen);
}
void Widget::init_select(){
btngrp=new QButtonGroup(this);
ui->blue->setStyleSheet("QPushButton:checked{border:2px solid green;}");
ui->brown->setStyleSheet("QPushButton:checked{border:2px solid green;}");
ui->gray->setStyleSheet("QPushButton:checked{border:2px solid green;}");
ui->yellow->setStyleSheet("QPushButton:checked{border:2px solid green;}");
ui->blue->setCheckable(true);
ui->brown->setCheckable(true);
ui->gray->setCheckable(true);
ui->yellow->setCheckable(true);
btngrp->addButton(ui->blue);
btngrp->addButton(ui->brown);
btngrp->addButton(ui->gray);
btngrp->addButton(ui->yellow);
btngrp->setExclusive(true);
}
void Widget::init_list(){
ui->listWidget->addItem("欢迎你啊,这个游戏叫做MAZE,");
ui->listWidget->addItem("界面简单粗糙,也算是为了一种风格。");
ui->listWidget->addItem("游戏中,你陷入一个无法离开的迷宫,");
ui->listWidget->addItem("没有出口,没有自由,");
ui->listWidget->addItem("但是可以让另一位迷路的人死去。");
ui->listWidget->addItem("操作:");
ui->listWidget->addItem("四个方向键↑↓←→:行走");
ui->listWidget->addItem("Z:射击");
ui->listWidget->addItem("记得在右侧选择自己的模样。");
}
void Widget::add_list(QString str){
ui->listWidget->addItem(str);
}
void Widget::start(){
//blue-1 brown-2 gray-3 yellow-4
int chara=0;
chara=(ui->blue->isChecked()?1:(ui->brown->isChecked()?2:(ui->gray->isChecked()?3:(ui->yellow->isChecked()?4:0))));
if(chara==0){
add_list("你还没有选择自己的模样。");
return;
}
xChara=chara;
is_started=true;
QDataStream stream(&msg,QIODevice::WriteOnly);
type=0;
stream<<type<<xAddr<<chara; //msgType:0
udpSocket->writeDatagram(msg,QHostAddress::Broadcast,udpPort);
timer.start(3000);
connect(&timer,&QTimer::timeout,this,&Widget::msg_timeout);
}
void Widget::msg_timeout(){
switch(type){
case 0: //探测
add_list("还未搜寻到局域网内玩家,请稍等");
udpSocket->writeDatagram(msg,QHostAddress::Broadcast,udpPort);
break;
}
}
void Widget::udp_listen(){
if(is_started){
int msgType;
while(udpSocket->hasPendingDatagrams()){
rec.clear();
rec.resize(udpSocket->pendingDatagramSize());
udpSocket->readDatagram(rec.data(),rec.size());
}
QDataStream rea(&rec,QIODevice::ReadOnly);
rea>>msgType;
switch(msgType){
case 0:{
rea>>yAddr>>yChara;
if(yAddr!=xAddr){
if(timer.isActive())timer.stop();
disconnect(&timer,&QTimer::timeout,this,&Widget::msg_timeout);
// //反馈对方
// udpSocket->writeDatagram(msg,QHostAddress::Broadcast,udpPort);
QString sentence;
sentence="与"+yAddr.toString()+"连接成功,开始游戏";
add_list(sentence);
}
break;
}
}
}
}
void Widget::connect_to(){
tcpSocket->connectToHost(yAddr,tcpPort);
QDataStream wri(&msg,QIODevice::WriteOnly);
wri<<0<<xAddr;
}
void Widget::tcp_listen(){
rec.clear();
rec=tcpSocket->readAll();
int msgType;
QDataStream rea(&rec,QIODevice::ReadOnly);
rea>>msgType;
switch(msgType){
case 0:{ //对方响应消息
rea>>yAddr;
QString sentence;
sentence="与"+yAddr.toString()+"连接成功,开始游戏";
add_list(sentence);
ui->stackedWidget->setCurrentIndex(1);
generate_res();
}
}
}
void Widget::generate_res(){
}
QString Widget::getLocHostIp(){
QList<QHostAddress> addrlist=QNetworkInterface::allAddresses();
foreach(QHostAddress addr,addrlist){
if(addr.protocol()==QAbstractSocket::IPv4Protocol){
return addr.toString();
}
}
return 0;
}
Widget::~Widget()
{
delete ui;
}
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QUdpSocket>
#include<QTcpServer>
#include<QTcpSocket>
#include<QButtonGroup>
#include<QHostAddress>
#include<QNetworkInterface>
#include<QTimer>
#include"maze.hpp"
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
public slots:
void start();
private:
Ui::Widget *ui;
QTimer timer;
//网络部分
QHostAddress xAddr;
QHostAddress yAddr;
QByteArray msg;
QByteArray rec;
bool is_started;
int tcpPort;
int udpPort;
QUdpSocket* udpSocket;
QTcpServer* tcpServer;
QTcpSocket* tcpSocket;
void udp_listen();
QString getLocHostIp();
void tcp_listen();
//~网络部分
//选角色部分
int xChara;
int yChara;
QButtonGroup* btngrp;
void init_select();
//~选角色部分
//list部分
void init_list();
void add_list(QString str);
//~list部分
//计时器
int type;
void msg_timeout();
//建立连接
void connect_to();
void generate_res();
//游戏地图
Maze maze;
};
#endif // WIDGET_H
maze.cpp
#ifndef _MAZE_HPP_
#define _MAZE_HPP_
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <map>
#include <set>
using namespace std;
class Maze {
public:
Maze(int row = 0, int col = 0);
void connect(int i, int j);
void disconnect(int i, int j);
vector<int> connected(int i) const; // 修改为接收一个参数
vector<int> surrounded(int i) const; // 修改为接收一个参数
int Row() const;
int Col() const;
bool isConnected(int i, int j) const;
private:
int row;
int col;
vector<vector<int> > neighbor;
vector<vector<int> > surround;
};
Maze::Maze(int row, int col) {
this->row = row;
this->col = col;
for (int i = 0; i < col * row; i++) {
vector<int> tmp(row * col, 0);
neighbor.push_back(tmp);
surround.push_back(tmp);
}
for (int i = 0; i < col * row; i++) {
if ((i - 1) % col != 0)
surround[i][i - 1] = 1; // 左邻居,排除第一列
if ((i + 1) % col != 0)
surround[i][i + 1] = 1; // 右邻居,排除最后一列
if (i - col >= 0)
surround[i][i - col] = 1; // 上邻居
if (i + col < row * col)
surround[i][i + col] = 1; // 下邻居
}
}
void Maze::connect(int i, int j) {
neighbor[i][j] = 1;
neighbor[j][i] = 1;
}
void Maze::disconnect(int i, int j) {
neighbor[i][j] = 0;
neighbor[j][i] = 0;
}
vector<int> Maze::connected(int i) const { // 修正为单参数函数
vector<int> result;
for (int t = 0; t < row * col; t++) {
if (neighbor[i][t] == 1) {
result.push_back(t);
}
}
return result;
}
vector<int> Maze::surrounded(int i) const { // 修正为单参数函数
vector<int> result;
for (int t = 0; t < row * col; t++) {
if (surround[i][t] == 1) {
result.push_back(t);
}
}
return result;
}
int Maze::Row() const {
return row;
}
int Maze::Col() const {
return col;
}
bool Maze::isConnected(int i, int j) const {
vector<int> con = this->connected(i);
auto it = find(con.begin(), con.end(), j);
if (it != con.end()) {
return true;
} else {
return false;
}
}
void showMaze(const Maze &m) {
//自左上角向右下角显示
int row = m.Row();
int col = m.Col();
for (int i = 0; i < col; i++) {
cout << "_ ";
}
cout << endl;
for (int r = 0; r < row; r++) {
cout << "|";
for (int c = 0; c < col; c++) {
if (m.isConnected(r * col + c, (r + 1)* col + c)) {
cout << " ";
} else {
cout << "_";
}
if (m.isConnected(r * col + c, r * col + c + 1)) {
cout << " ";
} else {
cout << "|";
}
}
cout << endl;
}
}
namespace DFS {
enum color {
white,
gray,
black
};
Maze generate(int row, int col) {
Maze result(row, col);
vector<color> record(row * col, white);
vector<int> current;
current.reserve(static_cast<size_t>(row * col));
record[0] = gray;
current.push_back(0);
while (current.size() != 0) {
int index = current.back();
vector<int> sur = result.surrounded(index);
// 过滤掉非法的邻居,防止超出边界
sur.erase(remove_if(sur.begin(), sur.end(), [&](int n) {
int x = n % col;
int y = n / col;
return (x == 0 && index % col == col - 1) || // 右
(y == 0 && index / col == row - 1) || // 下
(x == col - 1 && index % col == 0) || // 左
(y == row - 1 && index / col == 0); // 上
}), sur.end());
random_shuffle(sur.begin(), sur.end(), [](vector<int>::difference_type n)->vector<int>::difference_type{
return rand() % n;
});
int i = 0;
bool found = false;
for (; i < sur.size(); i++) {
if (record[sur[i]] == white) {
current.push_back(sur[i]);
result.connect(index, sur[i]);
record[sur[i]] = gray;
found = true;
break;
}
}
if (!found) {
current.pop_back();
record[index] = black;
}
}
return result;
}
}
namespace RandomKruskal {
class UnionFind {
public:
UnionFind(int n);
int find(int n);
void connect(int i, int j);
bool connected(int i, int j);
private:
vector<int>set;
};
UnionFind::UnionFind(int n) {
for (int i = 0; i < n; i++) {
set.push_back(i);
}
}
int UnionFind::find(int n) {
if (set[n] == n) {
return n;
} else {
set[n] = find(set[n]);
return set[n];
}
}
void UnionFind::connect(int i, int j) {
set[find(i)] = find(j);
}
bool UnionFind::connected(int i, int j) {
if (find(i) == find(j)) {
return true;
} else {
return false;
}
}
Maze generate(int row, int col) {
Maze maze(row, col);
UnionFind set(row * col);
vector<pair<int, int>>edges;
for (int i = 0; i < row * col; i++) {
vector<int>v = maze.surrounded(i);
for (vector<int>::iterator it = v.begin(); it != v.end(); it++) {
if (i < *it)
edges.push_back(make_pair(i, *it));
}
}
random_shuffle(edges.begin(), edges.end(), [ = ](vector<int>::difference_type n)->vector<int>::difference_type{
return rand() % n;
});
for (vector<pair<int, int>>::iterator it = edges.begin(); it != edges.end(); it++) {
if (!set.connected(it->first, it->second)) {
set.connect(it->first, it->second);
maze.connect(it->first, it->second);
}
}
return maze;
}
}
namespace RandomPrim {
Maze generate(int row, int col) {
Maze result(row, col);
vector<bool>U(row * col, false);
U[0] = true;
set<pair<int, int>>edges;
edges.insert(make_pair(0, 1));
edges.insert(make_pair(0, col));
int current = 0;
while (!edges.empty()) {
int pos = rand() % edges.size();
set<pair<int, int>>::iterator edge = edges.begin();
advance(edge, pos);
int f = edge->first;
int s = edge->second;
current = (!U[f]) ? f : ((!U[s]) ? s : 0);
result.connect(f, s);
U[current] = true;
//更新edges
vector<int>sur = result.surrounded(current);
for (vector<int>::iterator it = sur.begin(); it != sur.end(); it++) {
f = (current > *it ? *it : current);
s = (current < *it ? *it : current);
pair<int, int>path = make_pair(f, s);
if (!U[f] || !U[s]) {
edges.insert(path);
} else {
edges.erase(edges.find(path));
}
}
}
return result;
}
}
#endif
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
出现first defined here问题,是为什么