Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加了网络功能 #1

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion GameModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
enum GameType
{
PERSON,
BOT
BOT,
PERSON_ONLINE
};

// 游戏状态
Expand Down
1 change: 1 addition & 0 deletions QtWuziqi.pro
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#-------------------------------------------------

QT += core gui multimedia
QT += network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# QtWuziqi
Qt 写的五子棋小游戏,带AI和双人对战
Qt 写的五子棋小游戏,带AI和双人对战,现已添加网络功能
# ScreenShot
![](https://github.com/tashaxing/QtWuziqi/raw/master/pic/wuziqi.gif)<br/>
# BlogAddress
Expand Down
84 changes: 84 additions & 0 deletions mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ MainWindow::MainWindow(QWidget *parent)
connect(actionPVE, SIGNAL(triggered()), this, SLOT(initPVEGame()));
gameMenu->addAction(actionPVE);

QAction *actionPVPOL = new QAction("Person VS Person Online", this);
connect(actionPVPOL, SIGNAL(triggered()), this, SLOT(initPVPOLGame()));
gameMenu->addAction(actionPVPOL);

// 开始游戏
initGame();
}
Expand Down Expand Up @@ -82,6 +86,28 @@ void MainWindow::initPVEGame()
update();
}

void MainWindow::initPVPOLGame()
{
// 初始化套接字
tcpSocket = new QTcpSocket(this);

//连接服务器
port = 12345;
serverIP = new QHostAddress();
QString ip = "127.0.0.1";
serverIP->setAddress(ip);
tcpSocket->connectToHost(*serverIP, port);

connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
game_type = PERSON_ONLINE;
game->gameStatus = PLAYING;
game->startGame(game_type);

setMouseTracking(false);

update();
}

void MainWindow::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
Expand Down Expand Up @@ -228,6 +254,10 @@ void MainWindow::mouseMoveEvent(QMouseEvent *event)

void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
if(game_type == PERSON_ONLINE && !game->playerFlag)
{
chessOneByPersonOnline();
}
// 人下棋,并且不能抢机器的棋
if (!(game_type == BOT && !game->playerFlag))
{
Expand Down Expand Up @@ -263,3 +293,57 @@ void MainWindow::chessOneByAI()
update();
}

void MainWindow::chessOneByPersonOnline()
{
// 根据当前存储的坐标下子
// 只有有效点击才下子,并且该处没有子
if (clickPosRow != -1 && clickPosCol != -1 && game->gameMapVec[clickPosRow][clickPosCol] == 0)
{
game->actionByPerson(clickPosRow, clickPosCol);
QSound::play(CHESS_ONE_SOUND);

// 将位置通过套接字发给对手
QString scol = QString::number(clickPosCol, 10);
QString srow = QString::number(clickPosRow, 10);
QString msg = srow + "," + scol + "\n"; // 注意:要加上换行符
//qDebug() << msg;
int length = tcpSocket->write(msg.toLatin1(), msg.length());
tcpSocket->flush();
if(length != msg.length())
{
return;
}
// 重绘
update();
}
}

void MainWindow::dataReceived()
{
QByteArray datagram;
datagram.resize(tcpSocket->bytesAvailable());
tcpSocket->read(datagram.data(), datagram.size());
QString msg = datagram.data();
// 只有第一个开始游戏的玩家才会收到这条消息
if(msg.contains("has"))
{
setMouseTracking(true);
game->playerFlag = false;
//qDebug() << "You are the first one";
return;
}


int row = msg.section(',', 0, 0).toInt();
int col = msg.section(',', 1, 1).toInt();
//qDebug() << "recv:" << row << col;
setMouseTracking(false);

if (row != -1 && col != -1 && game->gameMapVec[row][col] == 0)
{
game->actionByPerson(row, col);
QSound::play(CHESS_ONE_SOUND);
setMouseTracking(true);
}
update();
}
12 changes: 12 additions & 0 deletions mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QHostAddress>
#include "GameModel.h"

class MainWindow : public QMainWindow
Expand All @@ -27,12 +29,22 @@ class MainWindow : public QMainWindow
void initGame();
void checkGame(int y, int x);

int port;
QHostAddress *serverIP;
QTcpSocket *tcpSocket;

private slots:
void chessOneByPerson(); // 人执行
void chessOneByAI(); // AI下棋

void chessOneByPersonOnline(); // 通过网络与好友下棋

void initPVPGame();
void initPVEGame();

void initPVPOLGame();

void dataReceived();
};

#endif // MAINWINDOW_H
7 changes: 7 additions & 0 deletions server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Usage
在Ubuntu环境下可以直接运行:
```shell
./server
```
运行之后就可以开始下网络五子棋了!
若是在其他环境则需要编译server.go
Binary file added server/server
Binary file not shown.
94 changes: 94 additions & 0 deletions server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// See page 254.
//!+

// Chat is a server that lets clients chat with each other.
package main

import (
"bufio"
"fmt"
"log"
"net"
)

//!+broadcaster
type client chan<- string // an outgoing message channel

var (
entering = make(chan client)
leaving = make(chan client)
messages = make(chan string) // all incoming client messages
)

func broadcaster() {
clients := make(map[client]bool) // all connected clients
for {
select {
case msg := <-messages:
// Broadcast incoming message to all
// clients' outgoing message channels.
for cli := range clients {
cli <- msg
}

case cli := <-entering:
clients[cli] = true

case cli := <-leaving:
delete(clients, cli)
close(cli)
}
}
}

//!-broadcaster

//!+handleConn
func handleConn(conn net.Conn) {
ch := make(chan string) // outgoing client messages
go clientWriter(conn, ch)

who := conn.RemoteAddr().String()
messages <- who + " has arrived"
entering <- ch

input := bufio.NewScanner(conn)
for input.Scan() {
messages <- input.Text()
}
// NOTE: ignoring potential errors from input.Err()

leaving <- ch
conn.Close()
}

func clientWriter(conn net.Conn, ch <-chan string) {
for msg := range ch {
fmt.Fprintln(conn, msg) // NOTE: ignoring network errors
}
}

//!-handleConn

//!+main
func main() {
listener, err := net.Listen("tcp", "localhost:12345")
if err != nil {
log.Fatal(err)
}

go broadcaster()
for {
conn, err := listener.Accept()
if err != nil {
log.Print(err)
continue
}
go handleConn(conn)
}
}

//!-main