[因為我不懂啊]-什么是狀態(tài)機編程(設(shè)計模式)(3)

上一篇文章寫完之后晰韵,我一直在想做一個游戲示例链瓦,想將之前學(xué)到的狀態(tài)機模式運用在其中拆魏。然而一直遇到各種奇怪的bug(之后寫出來),所以一直沒有完成這件事。而且加之自己又犯懶了渤刃,所以我決定做一件更簡單的事拥峦,以更容易接近的目標(biāo)來引誘懶的不行的自己。


廢話說完溪掀,來說正經(jīng)事了事镣。前幾天認(rèn)真看了一篇 博客-游戲狀態(tài)機(侵立刪),覺得挺不錯的揪胃,建議盆友們認(rèn)真看一看璃哟。

實現(xiàn)一個UI切換示例

為比較心急的伙伴放一個示例的Github鏈接

讀完博客之后,之前計劃的示例貌似有了頭緒喊递,(廢話型)總結(jié)出來随闪,實現(xiàn)一個游戲狀態(tài)機結(jié)構(gòu)需要進行如下幾步:

  1. 分析示例(需求),劃分狀態(tài)骚勘。
  2. 找出需求中的狀態(tài)铐伴、事件
  3. 寫一個狀態(tài)轉(zhuǎn)換表俏讹,使得需求更加明確当宴。
  4. 寫一個控制類,包含狀態(tài)轉(zhuǎn)換方法泽疆,作為所有狀態(tài)的根户矢,所有的狀態(tài)在這個根之上切換。
  5. 寫一個狀態(tài)基類殉疼,然后派生出需要的狀態(tài)類梯浪。
  6. 在每個狀態(tài)類中,寫好需要的事件瓢娜,以及事件發(fā)生的處理(就是進行狀態(tài)轉(zhuǎn)換)挂洛。

分析需求,劃分狀態(tài)

我要做一個簡單的UI切換示例眠砾,所以簡述需求就是: 打開程序進入主界面虏劲,主界面中點擊開始游戲,進入游戲界面褒颈,游戲界面中點擊結(jié)束游戲伙单,進入結(jié)算界面,結(jié)算界面可以點擊回到主界面哈肖,進入主界面,也可以點擊重新開始游戲念秧,再次進入游戲界面淤井。

找出狀態(tài)和事件

從需求描述來看,狀態(tài)有三個:

  1. 主界面
  2. 游戲界面
  3. 結(jié)算界面

事件有四個:

  1. 主界面->點擊開始游戲按鈕
  2. 游戲界面->點擊游戲結(jié)束按鈕
  3. 結(jié)算界面->點擊回到主頁按鈕
  4. 結(jié)算界面->點擊重新游戲按鈕

狀態(tài)轉(zhuǎn)換表

然后(裝模作樣的)畫了一個狀態(tài)轉(zhuǎn)換表:

狀態(tài) 事件 下一狀態(tài)
主界面 點擊開始游戲 游戲界面
游戲界面 點擊游戲結(jié)束 結(jié)算界面
結(jié)算界面 點擊回到主界面 主界面
點擊重新游戲 游戲界面

寫一個控制類

之前一篇文章中有提到過的,在Cocos2d-x游戲開發(fā)中币狠,剛好使用Scene來作為控制器游两,由Scene來控制各層的出現(xiàn)和消失。

這里貼出Scene的源碼(完整的源文件漩绵,包括了后續(xù)步驟才會出現(xiàn)的狀態(tài)基類贱案,以及派生的狀態(tài)類):
QFLGameTwoScene.hpp

//
//  QFLGameTwoScene.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#ifndef QFLGameTwoScene_hpp
#define QFLGameTwoScene_hpp

#include <stdio.h>
#include "cocos2d.h"
#include "QFLGameTwoStateBase.hpp"

class QFLGameTwoScene : public cocos2d::Scene   
{
CC_CONSTRUCTOR_ACCESS:
    QFLGameTwoScene();
    virtual ~QFLGameTwoScene();
    virtual bool init();
    CREATE_FUNC(QFLGameTwoScene);
    
public:
    void addUI();               //添加UI,黑色背景
    void initGame();            //初始化游戲止吐,進入一個初始狀態(tài)
    void addEventListener();    //添加事件監(jiān)聽宝踪,需要切換狀態(tài)時通過發(fā)送自定義事件來實現(xiàn)
    
    //切換狀態(tài)的函數(shù)
    void ChangeState(GameTwoState* pState);
    
private:
    GameTwoState* m_pCurrentState;  //當(dāng)前狀態(tài)
};

#endif /* QFLGameTwoScene_hpp */

QFLGameTwoScene.cpp

//
//  QFLGameTwoScene.cpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#include "QFLGameTwoScene.hpp"

#include "QFLTools/QFLHelper.hpp"

//基類
#include "QFLGameTwoStateBase.hpp"

//狀態(tài)類
#include "QFLGameTwoMainLayer.hpp"
#include "QFLGameTwoGameLayer.hpp"
#include "QFLGameTwoResultLayer.hpp"

USING_NS_CC;

QFLGameTwoScene::QFLGameTwoScene()
{
    
}

QFLGameTwoScene::~QFLGameTwoScene()
{
    
}
bool QFLGameTwoScene::init()
{
    if (!Scene::init()) {
        return false;
    }
    else {
        this->addUI();
        this->addEventListener();
        this->initGame();
        return true;
    }
}

void QFLGameTwoScene::addUI()
{
    //黑色背景
    auto pLayer = QFL_HELPER->getColorfulLayer();
    QFL_HELPER->addNoTouchListener(pLayer);
    this->addChild(pLayer);
}

void QFLGameTwoScene::initGame()
{
    //進入一個初始狀態(tài)
    log("游戲開始");
    m_pCurrentState = QFLGameTwoMainLayer::create();
    m_pCurrentState->Enter(this);
}

void QFLGameTwoScene::addEventListener()
{
    Director::getInstance()->getEventDispatcher()->addCustomEventListener(GameTwoEvent::Main_Start, [=](EventCustom* pEvent){
        log("[Event]->Main_Start");
        this->ChangeState(QFLGameTwoGameLayer::create());
    });
    Director::getInstance()->getEventDispatcher()->addCustomEventListener(GameTwoEvent::Game_Over, [=](EventCustom* pEvent){
        log("[Event]->Game_Over");
        this->ChangeState(QFLGameTwoResultLayer::create());
    });
    Director::getInstance()->getEventDispatcher()->addCustomEventListener(GameTwoEvent::Result_Home, [=](EventCustom* pEvent){
        log("[Event]->Result_Home");
        this->ChangeState(QFLGameTwoMainLayer::create());
    });
    Director::getInstance()->getEventDispatcher()->addCustomEventListener(GameTwoEvent::Result_Replay, [=](EventCustom* pEvent){
        log("[Event]->Result_Replay");
        this->ChangeState(QFLGameTwoGameLayer::create());
    });
}

void QFLGameTwoScene::ChangeState(GameTwoState *pState)
{
    //舊狀態(tài)退出
    m_pCurrentState->Exit(this);
    
    //保存新狀態(tài)
    m_pCurrentState = pState;
    
    //新狀態(tài)進入
    m_pCurrentState->Enter(this);
}

QFLTools/QFLHelper.hpp 這個文件是作為一個工具類存在的,本示例所有源碼在我的Github

上面可以看到碍扔,Scene中主要包含了:

  1. void ChangeState(GameTwoState* pState);用于狀態(tài)切換
  2. GameTwoState* m_pCurrentState;用于記錄當(dāng)前狀態(tài)
  3. void addEventListener();用于監(jiān)聽切換狀態(tài)事件
  4. void initGame();用于進入初始狀態(tài)

包含了以上內(nèi)容瘩燥,本示例中的這個Scene就能起到控制器的作用了。

寫一個狀態(tài)基類

狀態(tài)基類是很有必要的不同,為了達到各個同級狀態(tài)都能通過同一個控制器來進行狀態(tài)轉(zhuǎn)換的目標(biāo)厉膀,各個狀態(tài)類進行切換時必須有一套統(tǒng)一的流程。
這里貼出本示例中狀態(tài)基類的源碼:
QFLGameTwoStateBase.hpp

//
//  QFLGameTwoStateBase.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#ifndef QFLGameTwoStateBase_hpp
#define QFLGameTwoStateBase_hpp

#include <stdio.h>
#include "cocos2d.h"

//State的基類
class GameTwoState
{
public:
    virtual ~GameTwoState() {}
    virtual void Enter(cocos2d::Scene* pLayer) = 0;
    virtual void Execute() = 0;
    virtual void Exit(cocos2d::Scene* pLayer) = 0;
};

#define SC(__type__) static const __type__
//游戲中的事件(通過事件來進行狀態(tài)切換)
namespace GameTwoEvent {
    SC(std::string) Main_Start      = "Event_Main_Start";   //[Main]開始游戲的事件
    SC(std::string) Game_Over       = "Event_Game_Over";    //[Game]結(jié)束游戲的事件
    SC(std::string) Result_Home     = "Event_Result_Home";  //[Result]結(jié)算界面回主頁
    SC(std::string) Result_Replay   = "Event_Result_Replay";//[Result]結(jié)算界面重新開始
}

#endif /* QFLGameTwoStateBase_hpp */

這個源文件中包含了:

  1. class GameTwoState 狀態(tài)基類
  2. virtual void Enter(cocos2d::Scene* pLayer) = 0;狀態(tài)進入的處理
  3. virtual void Execute() = 0;本狀態(tài)執(zhí)行的方法
  4. virtual void Exit(cocos2d::Scene* pLayer) = 0;狀態(tài)退出的處理
  5. namespace GameTwoEvent包含狀態(tài)轉(zhuǎn)換事件的namespace

所有的派生狀態(tài)類都會include這個文件二拐,實現(xiàn)虛基類GameTwoState中的方法服鹅,所以所有的狀態(tài)類都有統(tǒng)一的切換流程:

  1. last_state->exit
  2. current_state->enter
  3. current_state->execute

而且在完成某個事件,需要進行狀態(tài)轉(zhuǎn)換時百新,可以通過發(fā)送自定義事件來完成消息的傳遞企软,自定義事件名放在這里也是為了方便起見。

每個狀態(tài)類中寫好需要的事件及處理

這里直接貼出幾個State的源碼了吟孙,其中包含注釋澜倦,廢話就不重復(fù)再寫了:

MainState源碼

QFLGameTwoMainLayer.hpp

//
//  QFLGameTwoMainLayer.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#ifndef QFLGameTwoMainLayer_hpp
#define QFLGameTwoMainLayer_hpp

#include <stdio.h>
#include "cocos2d.h"
#include "QFLGameTwoStateBase.hpp"

class QFLGameTwoMainLayer : public cocos2d::Layer, public GameTwoState
{
public:
    QFLGameTwoMainLayer();
    virtual ~QFLGameTwoMainLayer();
    virtual bool init() override;
    CREATE_FUNC(QFLGameTwoMainLayer);
    
    //實現(xiàn)StateBase的狀態(tài)切換所需方法
    void Enter(cocos2d::Scene* pLayer) override;
    void Execute() override;
    void Exit(cocos2d::Scene* pLayer) override;
    
private:
    void addUI();   //添加背景UI,添加按鈕等
};

#endif /* QFLGameTwoMainLayer_hpp */

QFLGameTwoMainLayer.cpp

//
//  QFLGameTwoMainLayer.cpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#include "QFLGameTwoMainLayer.hpp"

#include "QFLTools/QFLHelper.hpp"

USING_NS_CC;

QFLGameTwoMainLayer::QFLGameTwoMainLayer()
{
    
}

QFLGameTwoMainLayer::~QFLGameTwoMainLayer()
{
    
}

bool QFLGameTwoMainLayer::init()
{
    if (!Layer::init()) {
        return false;
    }
    else {
        this->addUI();
        return true;
    }
}

void QFLGameTwoMainLayer::Enter(cocos2d::Scene* pLayer)
{
    log("<Enter>\t\t->MainLayer");
    
    //添加到Scene中
    pLayer->addChild(this);
    
    //執(zhí)行各種事件
    this->Execute();
}

void QFLGameTwoMainLayer::Execute()
{
    log("<Execute>\t->MainLayer");  //執(zhí)行內(nèi)容只是打印一個Log
}

void QFLGameTwoMainLayer::Exit(cocos2d::Scene* pLayer)
{
    log("<Exit>\t\t->MainLayer\n");
    
    //移除
    this->removeFromParentAndCleanup(true);
}

void QFLGameTwoMainLayer::addUI()
{
    //黑色背景
    auto pLayer = QFL_HELPER->getColorfulLayer();
    QFL_HELPER->addNoTouchListener(pLayer);
    this->addChild(pLayer);
    
    //MainLogo
    auto pLogo = Label::createWithSystemFont("MainLayer", "", 50);
    pLogo->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y + 60));
    this->addChild(pLogo);
    
    //菜單
    auto pMenu = Menu::create();
    pMenu->setPosition(Vec2::ZERO);
    this->addChild(pMenu);
    
    //按鈕杰妓,點擊發(fā)送游戲開始事件
    auto pStart = MenuItemFont::create("Start", [=](cocos2d::Ref* pRef){
        Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(GameTwoEvent::Main_Start);
    });
    pStart->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y - 100));
    pMenu->addChild(pStart);
}

GameState源碼

QFLGameTwoGameLayer.hpp

//
//  QFLGameTwoGameLayer.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#ifndef QFLGameTwoGameLayer_hpp
#define QFLGameTwoGameLayer_hpp

#include <stdio.h>
#include "cocos2d.h"
#include "QFLGameTwoStateBase.hpp"

class QFLGameTwoGameLayer : public cocos2d::Layer, public GameTwoState
{
public:
    QFLGameTwoGameLayer();
    virtual ~QFLGameTwoGameLayer();
    virtual bool init() override;
    CREATE_FUNC(QFLGameTwoGameLayer);
    
    //實現(xiàn)StateBase的狀態(tài)切換所需方法
    void Enter(cocos2d::Scene* pLayer) override;
    void Execute() override;
    void Exit(cocos2d::Scene* pLayer) override;
    
private:
    void addUI();
};

#endif /* QFLGameTwoGameLayer_hpp */

QFLGameTwoGameLayer.cpp

//
//  QFLGameTwoGameLayer.cpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#include "QFLGameTwoGameLayer.hpp"

#include "QFLTools/QFLHelper.hpp"

USING_NS_CC;

QFLGameTwoGameLayer::QFLGameTwoGameLayer()
{
    
}

QFLGameTwoGameLayer::~QFLGameTwoGameLayer()
{
    
}

bool QFLGameTwoGameLayer::init()
{
    if (!Layer::init()) {
        return false;
    }
    else {
        this->addUI();
        return true;
    }
}

void QFLGameTwoGameLayer::addUI()
{
    //黑色背景
    auto pLayer = QFL_HELPER->getColorfulLayer();
    QFL_HELPER->addNoTouchListener(pLayer);
    this->addChild(pLayer);
    
    //GameLogo
    auto pLogo = Label::createWithSystemFont("GameLayer", "", 50);
    pLogo->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y + 60));
    this->addChild(pLogo);
    
    //菜單
    auto pMenu = Menu::create();
    pMenu->setPosition(Vec2::ZERO);
    this->addChild(pMenu);
    
    //按鈕藻治,點擊發(fā)送游戲結(jié)束事件
    auto pOver = MenuItemFont::create("GameOver", [=](cocos2d::Ref* pRef){
        Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(GameTwoEvent::Game_Over);
    });
    pOver->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y - 100));
    pMenu->addChild(pOver);
}

void QFLGameTwoGameLayer::Enter(cocos2d::Scene* pLayer)
{
    log("<Enter>\t\t->GameLayer");
    
    //添加到Scene中
    pLayer->addChild(this);
    
    //執(zhí)行游戲
    this->Execute();
}

void QFLGameTwoGameLayer::Execute()
{
    log("<Execute>\t->GameLayer");
}

void QFLGameTwoGameLayer::Exit(cocos2d::Scene* pLayer)
{
    log("<Exit>\t\t->GameLayer\n");
    
    //移除游戲
    this->removeFromParentAndCleanup(true);
}

ResultState源碼

QFLGameTwoResultLayer.hpp

//
//  QFLGameTwoResultLayer.hpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#ifndef QFLGameTwoResultLayer_hpp
#define QFLGameTwoResultLayer_hpp

#include <stdio.h>
#include "cocos2d.h"
#include "QFLGameTwoStateBase.hpp"

class QFLGameTwoResultLayer : public cocos2d::Layer, public GameTwoState
{
public:
    QFLGameTwoResultLayer();
    virtual ~QFLGameTwoResultLayer();
    virtual bool init() override;
    CREATE_FUNC(QFLGameTwoResultLayer);
    
    //實現(xiàn)StateBase的狀態(tài)切換所需方法
    void Enter(cocos2d::Scene* pLayer) override;
    void Execute() override;
    void Exit(cocos2d::Scene* pLayer) override;
    
private:
    void addUI();
};
#endif /* QFLGameTwoResultLayer_hpp */

QFLGameTwoResultLayer.cpp

//
//  QFLGameTwoResultLayer.cpp
//  QFLTest
//
//  Created by QuFangliu on 16/10/8.
//
//

#include "QFLGameTwoResultLayer.hpp"
#include "QFLTools/QFLHelper.hpp"

USING_NS_CC;

QFLGameTwoResultLayer::QFLGameTwoResultLayer()
{
    
}

QFLGameTwoResultLayer::~QFLGameTwoResultLayer()
{
    
}

bool QFLGameTwoResultLayer::init()
{
    if (!Layer::init()) {
        return false;
    }
    else {
        this->addUI();
        return true;
    }
}

void QFLGameTwoResultLayer::addUI()
{
    //黑色背景
    auto pLayer = QFL_HELPER->getColorfulLayer();
    QFL_HELPER->addNoTouchListener(pLayer);
    this->addChild(pLayer);
    
    //GameLogo
    auto pLogo = Label::createWithSystemFont("ResultLayer", "", 50);
    pLogo->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y + 60));
    this->addChild(pLogo);
    
    //菜單
    auto pMenu = Menu::create();
    pMenu->setPosition(Vec2::ZERO);
    this->addChild(pMenu);
    
    //按鈕,點擊發(fā)送會到主界面事件
    auto pHome = MenuItemFont::create("Home", [=](cocos2d::Ref* pRef){
        Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(GameTwoEvent::Result_Home);
    });
    pHome->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y - 100));
    pMenu->addChild(pHome);
    
    //按鈕巷挥,點擊發(fā)送重新開始游戲事件
    auto pReplay = MenuItemFont::create("Replay", [=](cocos2d::Ref* pRef){
        Director::getInstance()->getEventDispatcher()->dispatchCustomEvent(GameTwoEvent::Result_Replay);
    });
    pReplay->setPosition(Vec2(SCREEN_CENTER.x, SCREEN_CENTER.y - 150));
    pMenu->addChild(pReplay);
}

void QFLGameTwoResultLayer::Enter(cocos2d::Scene* pLayer)
{
    log("<Enter>\t\t->ResultLayer");
    
    //添加到Scene中
    pLayer->addChild(this);
    
    //執(zhí)行游戲
    this->Execute();
}

void QFLGameTwoResultLayer::Execute()
{
    log("<Execute>\t->ResultLayer");
}

void QFLGameTwoResultLayer::Exit(cocos2d::Scene* pLayer)
{
    log("<Exit>\t\t->ResultLayer\n");
    
    //移除游戲
    this->removeFromParentAndCleanup(true);
}

到這里桩卵,上面所提到的步驟全部進行完了。這個UI切換的狀態(tài)機示例也就完成了倍宾。


運行效果

在AppDelegate.cpp中雏节,直接進入Scene中:

auto pScene = QFLGameTwoScene::create();
director->runWithScene(pScene);

進入主界面:

MainState.jpeg

此時的Log:

游戲開始
<Enter> ->MainLayer
<Execute> ->MainLayer

點擊Start,進入游戲界面:

GameState.jpeg

此時的Log:

游戲開始
<Enter> ->MainLayer
<Execute> ->MainLayer
[Event]->Main_Start

<Exit> ->MainLayer
<Enter> ->GameLayer
<Execute> ->GameLayer

點擊Over高职,進入結(jié)算界面:

ResultState.jpeg

此時的Log:

游戲開始
<Enter> ->MainLayer
<Execute> ->MainLayer
[Event]->Main_Start
<Exit> ->MainLayer

<Enter> ->GameLayer
<Execute> ->GameLayer
[Event]->Game_Over
<Exit> ->GameLayer

<Enter> ->ResultLayer
<Execute> ->ResultLayer

點擊Replay钩乍,重新進入游戲界面:
此時的Log:

游戲開始
<Enter> ->MainLayer
<Execute> ->MainLayer
[Event]->Main_Start
<Exit> ->MainLayer

<Enter> ->GameLayer
<Execute> ->GameLayer
[Event]->Game_Over
<Exit> ->GameLayer

<Enter> ->ResultLayer
<Execute> ->ResultLayer
[Event]->Result_Replay
<Exit> ->ResultLayer

<Enter> ->GameLayer
<Execute> ->GameLayer

點擊Over,再次進入結(jié)算界面怔锌,然后在結(jié)算界面點擊Home寥粹,回到主界面
上面的兩次操作完成后变过,Log如下:

游戲開始
<Enter> ->MainLayer
<Execute> ->MainLayer
[Event]->Main_Start
<Exit> ->MainLayer

<Enter> ->GameLayer
<Execute> ->GameLayer
[Event]->Game_Over
<Exit> ->GameLayer

<Enter> ->ResultLayer
<Execute> ->ResultLayer
[Event]->Result_Replay
<Exit> ->ResultLayer

<Enter> ->GameLayer
<Execute> ->GameLayer
[Event]->Game_Over
<Exit> ->GameLayer

<Enter> ->ResultLayer
<Execute> ->ResultLayer
[Event]->Result_Home
<Exit> ->ResultLayer

<Enter> ->MainLayer
<Execute> ->MainLayer


總結(jié)

這里用FSM實現(xiàn)UI切換示例只是眾多方法中的一種,暫時還沒有去比較它們的優(yōu)劣涝涤。(使用markdown編輯器的經(jīng)驗值+1)

例如:在狀態(tài)基類文件中媚狰,添加一個狀態(tài)枚舉類型enum StateTypevoid ChangeState轉(zhuǎn)換狀態(tài)時不再傳遞一個GameTwoState *pState指針阔拳,而是傳遞一個狀態(tài)枚舉值StateType崭孤,這種方法在某些情況下很有效。

例如:不用在void Enter中傳入一個cocos2d::Scene* pLayer指針糊肠,而是在void ChangeState中生成新的狀態(tài)類辨宠,并addChild到Scene中。不用在void Exit中傳入一個cocos2d::Scene* pLayer指針罪针,直接使用removeFromParentAndClean方法就能從Scene中刪除彭羹。

可能性多種多樣,如果有小伙伴比較過這些方法泪酱。求留言告知派殷,求分享經(jīng)驗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末墓阀,一起剝皮案震驚了整個濱河市毡惜,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌斯撮,老刑警劉巖经伙,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異勿锅,居然都是意外死亡帕膜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門溢十,熙熙樓的掌柜王于貴愁眉苦臉地迎上來垮刹,“玉大人,你說我怎么就攤上這事张弛』牡洌” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵吞鸭,是天一觀的道長寺董。 經(jīng)常有香客問我,道長刻剥,這世上最難降的妖魔是什么遮咖? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮造虏,結(jié)果婚禮上御吞,老公的妹妹穿的比我還像新娘踢械。我一直安慰自己,他們只是感情好魄藕,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著撵术,像睡著了一般背率。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嫩与,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天寝姿,我揣著相機與錄音,去河邊找鬼划滋。 笑死饵筑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的处坪。 我是一名探鬼主播根资,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼同窘!你這毒婦竟也來了玄帕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤想邦,失蹤者是張志新(化名)和其女友劉穎裤纹,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體丧没,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡鹰椒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了呕童。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漆际。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖拉庵,靈堂內(nèi)的尸體忽然破棺而出灿椅,到底是詐尸還是另有隱情,我是刑警寧澤钞支,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布茫蛹,位于F島的核電站,受9級特大地震影響烁挟,放射性物質(zhì)發(fā)生泄漏婴洼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一撼嗓、第九天 我趴在偏房一處隱蔽的房頂上張望柬采。 院中可真熱鬧欢唾,春花似錦、人聲如沸粉捻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽肩刃。三九已至祟霍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盈包,已是汗流浹背沸呐。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留呢燥,地道東北人崭添。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像叛氨,于是被迫代替她去往敵國和親呼渣。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容