Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
First release
  • Loading branch information
X1aomu committed Apr 3, 2019
2 parents 7d0af42 + 1ee0612 commit 9c83a95
Show file tree
Hide file tree
Showing 17 changed files with 162 additions and 102 deletions.
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,22 @@ target_wrapper.*

# QtCreator CMake
CMakeLists.txt.user*

# CMake
CMakeLists.txt.user
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps

# CMake automoc
/*_autogen

# compilation database
compile_commands.json
14 changes: 14 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
language: cpp

dist: xenial

addons:
apt:
update: true

before_install:
- sudo apt-get install -y qt5-default

script:
- cmake .
- make -j2
36 changes: 36 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.1...3.14)

if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()

project(QReversi)

find_package(Qt5Widgets REQUIRED)

set(CMAKE_CXX_STANDARD 11)

set(CMAKE_INCLUDE_CURRENT_DIR ON)

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)

set(SOURCES
main.cc
core/battle.cc
core/gameplay.cc
core/players/ai.cc
core/players/human.cc
core/players/virtualplayer.cc
ui/mainwindow.cc
ui/newgamedialog.cc
ui/checkerboard/boardlayout.cc
ui/checkerboard/checkerboardwidget.cc
ui/checkerboard/boardgrid.cc
ui/newgamedialog.ui
resources.qrc
)

add_executable(qreversi ${SOURCES})
target_link_libraries(qreversi Qt5::Widgets)
61 changes: 0 additions & 61 deletions QReversi.pro

This file was deleted.

3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# QReversi
[![Build Status](https://travis-ci.org/X1aomu/QReversi.svg)](https://travis-ci.org/X1aomu/QReversi)
[![GitHub release](https://img.shields.io/github/X1aomu/QReversi.svg)](https://github.com/X1aomu/QReversi/releases)

A Qt-based reversi game
44 changes: 20 additions & 24 deletions core/battle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
Battle::Battle(QObject *parent)
: QObject(parent),
m_gamePlay(this),
m_blackAiPlayer(std::make_shared<class Ai>("", this)),
m_whiteAiPlayer(std::make_shared<class Ai>("", this)),
m_playerBlack(nullptr),
m_playerWhile(nullptr)
{
Expand All @@ -16,7 +18,7 @@ Battle::Battle(QObject *parent)

Battle::~Battle()
{
cleanup();

}

bool Battle::isBattleRunning()
Expand All @@ -29,7 +31,7 @@ Battle::PlayerColor Battle::currentPlayerColor()
return m_gamePlay.getCurrentPlayerColor();
}

VirtualPlayer *Battle::getPlayer(Battle::PlayerColor playerColor)
std::shared_ptr<VirtualPlayer> Battle::getPlayer(Battle::PlayerColor playerColor)
{
if (playerColor == PlayerColor::Black)
{
Expand All @@ -44,59 +46,53 @@ VirtualPlayer *Battle::getPlayer(Battle::PlayerColor playerColor)

void Battle::startNewBattle(Battle::PlayerType blackPlayerType, Battle::PlayerType whitePlayerType, QString blackPlayerName, QString whitePlayerName)
{
cleanup();
endBattle();

switch (blackPlayerType) {
case Human:
m_playerBlack = new class Human(blackPlayerName, this);
m_playerBlack = std::make_shared<class Human>(blackPlayerName, this);
break;
case Ai:
m_playerBlack = new class Ai(blackPlayerName, this);
dynamic_cast<class Ai*>(m_playerBlack)->setGame(&m_gamePlay);
m_playerBlack = m_blackAiPlayer;
m_playerBlack->setName(blackPlayerName);
dynamic_cast<class Ai&>(*m_playerBlack).setGame(&m_gamePlay);
break;
}
switch (whitePlayerType) {
case Human:
m_playerWhile = new class Human(whitePlayerName, this);
m_playerWhile = std::make_shared<class Human>(whitePlayerName, this);
break;
case Ai:
m_playerWhile = new class Ai(whitePlayerName, this);
dynamic_cast<class Ai*>(m_playerWhile)->setGame(&m_gamePlay);
m_playerWhile = m_whiteAiPlayer;
m_playerWhile->setName(whitePlayerName);
dynamic_cast<class Ai&>(*m_playerWhile).setGame(&m_gamePlay);
break;
}

// 连接信号
connect(m_playerBlack, &VirtualPlayer::sigMoved, &m_gamePlay, &GamePlay::slotMove);
connect(m_playerWhile, &VirtualPlayer::sigMoved, &m_gamePlay, &GamePlay::slotMove);
connect(m_playerBlack.get(), &VirtualPlayer::sigMoved, &m_gamePlay, &GamePlay::slotMove);
connect(m_playerWhile.get(), &VirtualPlayer::sigMoved, &m_gamePlay, &GamePlay::slotMove);

m_gamePlay.slotStartNewGame();
emit sigBattleStarted();
emit sigChanged();
}

void Battle::endBattle()
{
m_gamePlay.reset();
cleanup();
emit sigChanged();
}

void Battle::slotHumanMove(GamePlay::Position position)
{
VirtualPlayer* playerToMove = m_gamePlay.getCurrentPlayerColor() == PlayerColor::Black ? m_playerBlack : m_playerWhile;
if (class Human* humanPlayer = dynamic_cast<class Human*>(playerToMove))
auto playerToMove = m_gamePlay.getCurrentPlayerColor() == PlayerColor::Black ? m_playerBlack : m_playerWhile;
if (class Human* humanPlayer = dynamic_cast<class Human*>(playerToMove.get()))
{
humanPlayer->slotMoveTo(position);
}
}

void Battle::cleanup()
{
delete m_playerBlack;
delete m_playerWhile;
m_playerBlack = nullptr;
m_playerWhile = nullptr;
}

void Battle::gamePlayCheckerBoardChangedHandler(GamePlay::CheckerBoard currentBoard)
{
emit sigCheckerBoardChanged(currentBoard);
Expand All @@ -105,6 +101,8 @@ void Battle::gamePlayCheckerBoardChangedHandler(GamePlay::CheckerBoard currentBo

void Battle::gamePlayPlayerChangedHandler(Battle::PlayerColor playerColor)
{
emit sigPlayerChanged(playerColor);
emit sigChanged();
// 通知玩家下子
if (playerColor == PlayerColor::Black)
{
Expand All @@ -114,8 +112,6 @@ void Battle::gamePlayPlayerChangedHandler(Battle::PlayerColor playerColor)
{
m_playerWhile->slotNextMove(m_gamePlay.getCheckerBoard(), playerColor);
}
emit sigPlayerChanged(playerColor);
emit sigChanged();
}

void Battle::gamePlayGameOverHandler(Battle::PlayerColor winner)
Expand Down
12 changes: 8 additions & 4 deletions core/battle.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#ifndef ROUND_H
#define ROUND_H

#include <memory>

#include "core/gameplay.h"
#include "core/players/virtualplayer.h"
#include "core/players/ai.h"

#include <QObject>

Expand Down Expand Up @@ -38,7 +41,7 @@ class Battle : public QObject
/// \param playerColor 玩家颜色,
/// 需为 #GamePlay::Black 或 #GamePlay::White 。
/// \return 下子方 \p playerColor 对应的玩家。如果没有对战则为 nullptr。
VirtualPlayer *getPlayer(PlayerColor playerColor);
std::shared_ptr<VirtualPlayer> getPlayer(PlayerColor playerColor);

/// \brief 开始对战。
/// \param blackPlayerType 黑方的玩家类型。
Expand Down Expand Up @@ -87,10 +90,11 @@ public slots:

private:
GamePlay m_gamePlay;
VirtualPlayer *m_playerBlack;
VirtualPlayer *m_playerWhile;
std::shared_ptr<VirtualPlayer> m_blackAiPlayer;
std::shared_ptr<VirtualPlayer> m_whiteAiPlayer;
std::shared_ptr<VirtualPlayer> m_playerBlack;
std::shared_ptr<VirtualPlayer> m_playerWhile;

void cleanup();
void gamePlayCheckerBoardChangedHandler(GamePlay::CheckerBoard currentBoard);
void gamePlayPlayerChangedHandler(PlayerColor playerColor);
void gamePlayGameOverHandler(PlayerColor winner);
Expand Down
2 changes: 2 additions & 0 deletions core/gameplay.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ size_t GamePlay::tryMove(GamePlay::Position pos, PlayerColor playerColor, bool r

bool GamePlay::playerCanMove(GamePlay::PlayerColor playerColor)
{
if (!m_running)
return false;
for (size_t row = 0; row != kBoardRows; ++row)
{
for (size_t col = 0; col != kBoardColumns; ++col)
Expand Down
28 changes: 21 additions & 7 deletions core/players/ai.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,32 @@
#include <ctime>
#include <vector>
#include <random>
#include <chrono>
#include <thread>
#include <memory>

#include <QTimer>
#include <QEventLoop>

#include "core/gameplay.h"

Ai::~Ai()
{
}

void Ai::slotNextMove(const GamePlay::CheckerBoard &game, GamePlay::PlayerColor playerColor)
{
Q_UNUSED(game);
Q_UNUSED(game)

if (m_game == nullptr)
return;

std::this_thread::sleep_for(std::chrono::milliseconds(200));
// 设置延时,同时不失去主进程的响应
QTimer t;
QEventLoop eventLoop;
t.setSingleShot(true);
t.setTimerType(Qt::PreciseTimer);
connect(&t, &QTimer::timeout, &eventLoop, &QEventLoop::quit);
t.start(1000);
eventLoop.exec();

std::vector<GamePlay::Position> availPositions;
for (size_t row = 0; row != GamePlay::kBoardRows; ++row)
Expand All @@ -31,9 +45,9 @@ void Ai::slotNextMove(const GamePlay::CheckerBoard &game, GamePlay::PlayerColor
if (availPositions.empty())
return;

std::random_device r;
std::default_random_engine randomEngine(r());
std::mt19937 rng;
rng.seed(time(nullptr));
std::uniform_int_distribution<size_t> randomDist(0, availPositions.size() - 1);

emit sigMoved(availPositions.at(randomDist(randomEngine)));
emit sigMoved(availPositions.at(randomDist(rng)));
}
3 changes: 3 additions & 0 deletions core/players/ai.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef AI_H
#define AI_H

#include <mutex>

#include "core/players/virtualplayer.h"
#include "core/gameplay.h"

Expand All @@ -13,6 +15,7 @@ class Ai : public VirtualPlayer

public:
using VirtualPlayer::VirtualPlayer;
~Ai() override;

/// \brief 设置游戏
void setGame(GamePlay* game);
Expand Down
5 changes: 5 additions & 0 deletions core/players/virtualplayer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ VirtualPlayer::VirtualPlayer(QString name, QObject *parent)
{

}

VirtualPlayer::~VirtualPlayer()
{

}
4 changes: 4 additions & 0 deletions core/players/virtualplayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ class VirtualPlayer : public QObject
/// \param name 名字。
/// \param parent 父控件。
explicit VirtualPlayer(QString name, QObject *parent = nullptr);
virtual ~VirtualPlayer();

/// \brief 获取名字。
/// \return 玩家的名字。
QString getName() { return m_name; }
/// \brief 设置名字。
/// \return 玩家的名字。
void setName(const QString &name) { m_name = name; }

public slots:
/// \brief 通知玩家下子。
Expand Down
Loading

0 comments on commit 9c83a95

Please sign in to comment.