36_泛型编程与模板

泛型编程

作用:某些算法跟类型没关系,代码逻辑一样,就数据类型不一样

模板

作用

让编译器自动写函数

实现

类型参数化,调用函数的时候声明传入的类型。Add<TYPE>(1, 2)

语法

1.单个模板参数

template<class TYPE>

TYPE add(TYPE value1, TYPE value2)

{

Return value1 + value2;

}

2.多个模板参数

Template<typename t1, typename t2, typename t3>

T3 del(t1 value1, t2 value2)

{

Return value1 – value2;

}

注意

    1. 没有实例化模板的时候不参与编译
    2. 同类型模板只实例化一次
    3. 写模板的时候记得先实例化测试一次
    4. 支持用户自定义类型,需要重载运算符
    5. 传递类类型的时候传递引用

模板实例化

显式实例化

int a = add<int>(1, 2);

隐式实例化

add(1.23, 23.4)

模板特列 / 特化

template<> char* add(char* p1, char* p2)

{

Return strcpy(p1, p2);

}

模板类型默认类型

Template<typename t1 = int, typename t2 = int, typename t3 = int>

T3 del(t1 value1, t2 value2)

{

Return value1 – value2;

}

模板重载

只有参数个数不同才能重载

类模板

语法

Template<typename TYPE>

Class A

{

Public:

A(TYPE a) {m_T = a; } ;

Private:

TYPE m_T;

}

使用

A<int> a;

注意

  1. 类模板只能显示实例化
  2. 类的成员函数作模板
  3. 类的数据成员作模板
  4. 类模板实现不能分开文件

特化

  1. 成员函数特化
  2. 数据成员特化
  3. 类特化

继承

  1. 模板继承

友元模板

 

作业

1. 使用函数模版一个比较两数大小的函数,支持各种数据类型
2. 使用函数模版一个求偶数的函数,支持各种数据类型
3. 使用函数模版一个求闰年的函数,支持各种数据类型
4. 使用函数模版一个求平方的函数,支持各种数据类型
5. 使用函数模版一个求三角形的面积的函数,支持各种数据类型
6. 使用函数模版一个绝对值的函数,支持各种数据类型
7. 使用类模版实现一个支持各种数据类型的智能指针
8. 使用类模版实现一个支持各种数据类型的带引用计数智能指针
9. 使用类模版实现一个Compare类,提供各种基本数据类型比较和运算(加法,减法)的方法
10.用宏实现模板功能,分别输出
void main()
{
ADD(int)(1,2);
ADD(float)(1.0f,2.2f);
ADD(int)(10,20);
ADD(char*)(“hello”,”wolrd”);
}

 //Compare.h
#pragma once

template 
class CCompare
{
public:
    static bool isSame(T1& value1, T2& value2);
    static bool isBigThan(T1& value1, T2& value2);
    static bool isSmallThan(T1& value1, T2& value2);
    static bool isNotSame(T1& value1, T2& value2);
    static bool isBigThanAndSame(T1& value1, T2& value2);
    static bool isSmallThanAndSame(T1& value1, T2& value2);
    //static T1 addTwoValue(T1&)
};

template 
bool CCompare::isSame(T1& value1, T2& value2)
{
    if (value1 == value2)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool CCompare::isBigThan(T1& value1, T2& value2)
{
    if (value1 > value2)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool CCompare::isSmallThan(T1& value1, T2& value2)
{
    if (value1 < value2)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool CCompare::isNotSame(T1& value1, T2& value2)
{
    if (value1 == value2)
    {
        return false;
    }
    else
    {
        return true;
    }
}

template 
bool CCompare::isBigThanAndSame(T1& value1, T2& value2)
{
    if (isBigThan(value1, value2) == true
        ||
        isSame(value1, value2) == true
        )
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool CCompare::isSmallThanAndSame(T1& value1, T2& value2)
{
    if (isSmallThan(value1, value2) == true
        ||
        isSame(value1, value2) == true
        )
    {
        return true;
    }
    else
    {
        return false;
    }
}
 //SmartPointer.h
#pragma once

template 
class CSmartPointer
{
public:
    CSmartPointer();
    CSmartPointer(const T value);
    CSmartPointer(CSmartPointer& obj);
    ~CSmartPointer();
    void setValue(const T value);
    T getValue() const;
    CSmartPointer& operator++(); //前置++
    const CSmartPointer& operator++(int); //后置++
    template 
    CSmartPointer& operator=(const T2& obj);
    template 
    CSmartPointer& operator+(const CSmartPointer& obj);
    template 
    CSmartPointer& operator-(const CSmartPointer& obj);
    template 
    CSmartPointer& operator*(const CSmartPointer& obj);
    template 
    CSmartPointer& operator/(const CSmartPointer& obj);
    template 
    CSmartPointer& operator%(const CSmartPointer& obj);
private:
    void setUseCount(const int count);
    int getUserCount() const;
private:
    T *m_pType;
    int *m_piUseCount;
};

template 
CSmartPointer::CSmartPointer()
{
    m_pType = nullptr;
    setUseCount(1);
}

template 
CSmartPointer::~CSmartPointer()
{
    if (getUserCount() == 1)
    {
        if (m_pType != nullptr)
        {
            delete m_pType;
        }
    }
}

template
void CSmartPointer::setValue(const T value)
{
    *m_pType = value;
}


template 
CSmartPointer::CSmartPointer(const T value)
{
    m_pType = new T[1];
    setValue(value);
}

template
CSmartPointer::CSmartPointer(CSmartPointer& obj)
{
    setUseCount(getUserCount() + 1);
    obj->m_piUseCount = this->m_piUseCount;
    obj->m_pType = this->m_pType;
}


template
T CSmartPointer::getValue() const
{
    return *m_pType;
}

template
template
CSmartPointer& CSmartPointer::operator+(const CSmartPointer& obj)
{
    CSmartPointer *pSp = new CSmartPointer(this->getValue() + obj.getValue());

    return *pSp;
}

template
template
CSmartPointer& CSmartPointer::operator-(const CSmartPointer& obj)
{
    CSmartPointer *pSp = new CSmartPointer(this->getValue() - obj.getValue());
    return *pSp;
}

template
template
CSmartPointer& CSmartPointer::operator*(const CSmartPointer& obj)
{
    CSmartPointer *pSp = new CSmartPointer(this->getValue() * obj.getValue());
    return *pSp;
}


template
template
CSmartPointer& CSmartPointer::operator/(const CSmartPointer& obj)
{
    CSmartPointer *pSp = new CSmartPointer(this->getValue() / obj.getValue());
    return *pSp;
}

template
template
CSmartPointer& CSmartPointer::operator%(const CSmartPointer& obj)
{
    CSmartPointer *pSp = new CSmartPointer(this->getValue() % obj.getValue());
    return *pSp;
}

template
CSmartPointer& CSmartPointer::operator++()
{
    ++(*m_pType);
    return *this;
}

template
const CSmartPointer& CSmartPointer::operator++(int)
{
    ++(*m_pType);
    return *this;
}

template
void CSmartPointer::setUseCount(const int count)
{
    m_piUseCount = new int[1];
}

template
int CSmartPointer::getUserCount() const
{
    return *m_piUseCount;
}

template
template
CSmartPointer& CSmartPointer::operator=(const T2& obj)
{
    *m_pType = obj;
}


 //test1.cpp
//1. 使用函数模版一个比较两数大小的函数,支持各种数据类型

#include 
#include 
#include "SmartPointer.h"
#include "Compare.h"

using namespace std;

template 
bool getMax(TYPE value1, TYPE value2)
{
    if (value1 > value2)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool isEvenNumber(TYPE value)
{
    if (value == 0)
    {
        return true;
    }
    else if (value % 2 == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
bool isLeapYear(TYPE value)
{
    if (value % 400 == 0)
    {
        return true;
    }
    else if ((value % 4 == 0) && (value % 100 != 0))
    {
        return true;
    }
    else
    {
        return false;
    }
}

template 
TYPE getSquare(TYPE value)
{
    return value * value;
}

template 
TYPE getTriangleArea(TYPE value1, TYPE value2, TYPE value3)
{
    TYPE p = (a + b + c) / 2.0;
    sqrt(p * (p - value1) * (p - value2) * (p - value3));
}

template 
TYPE getAbs(TYPE value)
{
    return abs(value);
}

int main()
{
    /*
    getMax(2, 3);
    isEvenNumber(0);
    isLeapYear(2000);
    getSquare(3.5f);
    getAbs(-3.54);
    */



    CSmartPointer a;
    CSmartPointer b(2);
    b.setValue(3);
    b.getValue();
    CSmartPointer a2(4);
    CSmartPointer aa(5);
    a2 + b;
    ++a2;
    a2++;

    int va1 = 3;
    int va2 = 4;
    CCompare::isSmallThan(va1, va2);
   
    return 0;
}

11.使用面向对象编写吃豆人游戏

 //myPac-Man.cpp
#pragma once
#include "Control.h"


int main()
{
    //设置cmd大小
    system("mode con: cols=80 lines=32");

    //生成控制器
    CControl *pCtl = new CControl;
    while ((pCtl->getIsOver()) != true)
    {
        ;
    }

    printf("游戏结束,得分%d\r\n", pCtl->getScore());
    delete pCtl;

    system("pause");
    return 0;
}
 //Control.h
#pragma once
#include "Map.h"
#include "Move.h"
#include 
#include 

class CControl
{
public:
    CControl();
    ~CControl();
    bool getIsOver();
    const int getScore() const;
private:
    void setScore(int score);
    void setIsOver(const bool isOver);
    void startMove(CMove& move, char direction);
    bool canMove(CMove& move, int x, int y);
    bool checkDie(CMove& move);
    void play();
    void ghostAutoMove();
    CMove findPlayer(CMove move, CMove move2, int x, int y);
    bool checkWin();
private:
    CMap *m_pMap;
    CMove *m_pPlayer;
    CMove *m_pGhost;
    bool m_bIsOver;
    int m_iScore;
    time_t m_timeStart;
    time_t m_timeStop;
};
 //Map.h
#pragma once

#include 
#include 

const int g_rows = 28;  //行数。
const int g_cols = 31;  //列数

const int g_wall = -1;  //墙
const int g_beans = -2; //普通的豆子
const int g_beans2 = -3; //特殊的豆子
const int g_road = -4;  //可以走的路
const int g_player = -5;    //玩家
const int g_ghost = -6; //幽灵
const int g_ghostWall = -7; //幽灵的家


class CMap
{
public:
    CMap();
    ~CMap();
    void setMapinfo(const int i, const int j, const int value);
    void showMap() const;
    const int getMapInfo(const int i, const int j) const;
private:
    char m_mapInfo[g_cols][g_rows];    //地图大小  31 *28
};
 //Move.h
#pragma once

class CMove
{
public:
    CMove(bool isCanEat, int type, int mapType);
    ~CMove();
    const int getX();
    const int getY();
    void setX(const int x);
    void setY(const int y);
    void setCanEat(bool isCanEat);
    bool getCanEat() const;
    void setType(const int type);
    int getType() const;
    void setLastMapType(const int type);
    int getLastMapType() const;
private:
    bool m_bCanEat;
    int m_iX;
    int m_iY;
    int m_iType; //移动体的类型
    int m_iLasttMapType; //上一个地图的类型
};
 //Move.cpp
#include "Move.h"

CMove::CMove(bool isCanEat, int type, int mapType)
{
    setCanEat(isCanEat);
    setType(type);
    setLastMapType(mapType);
}

CMove::~CMove()
{
}

const int CMove::getX()
{
    return m_iX;
}

const int CMove::getY()
{
    return m_iY;
}

void CMove::setX(const int x)
{
    m_iX = x;
}

void CMove::setY(const int y)
{
    m_iY = y;
}

void CMove::setCanEat(bool isCanEat)
{
    m_bCanEat = isCanEat;
}

bool CMove::getCanEat() const
{
    return m_bCanEat;
}

void CMove::setType(const int type)
{
    m_iType = type;
}

int CMove::getType() const
{
    return m_iType;
}

void CMove::setLastMapType(const int type)
{
    m_iLasttMapType = type;
}

int CMove::getLastMapType() const
{
    return m_iLasttMapType;
}

 //Map.cpp
#include "Map.h"

CMap::CMap()
{
    //初始化地图
    char mapInfo[g_cols][g_rows] = {
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
        -1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-3,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-3,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-2,-2,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-7,-7,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-4,-4,-4,-4,-4,-4,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-4,-4,-4,-4,-4,-4,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-4,-4,-4,-4,-4,-4,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,
        -1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-2,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-2,-1,
        -1,-3,-2,-2,-1,-1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-3,-1,
        -1,-1,-1,-2,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-2,-1,-1,-1,
        -1,-1,-1,-2,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-2,-1,-1,-1,
        -1,-2,-2,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-1,-1,-2,-2,-2,-2,-2,-2,-1,
        -1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,
        -1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,
        -1,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-2,-1,
        -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
    };

    for (int i = 0; i < g_cols; i++)
    {
        for (int j = 0; j < g_rows; j++)
        {
            setMapinfo(i, j, mapInfo[i][j]);
        }
    }
}

CMap::~CMap()
{

}

void CMap::setMapinfo(const int i, const int j, const int value)
{
    m_mapInfo[i][j] = value;
}

void CMap::showMap() const
{
    system("cls");
    for (int i = 0; i < g_cols; i++)
    {
        for (int j = 0; j < g_rows; j++)
        {
            if (getMapInfo(i, j) == g_wall)
            {
                printf("■");
            }
            else if (getMapInfo(i, j) == g_beans)
            {
                printf("○");
            }
            else if (getMapInfo(i, j) == g_beans2)
            {
                printf("●");
            }
            else if (getMapInfo(i, j) == g_road)
            {
                printf("  ");
            }
            else if (getMapInfo(i, j) == g_player)
            {
                printf("★");
            }
            else if (getMapInfo(i, j) == g_ghost)
            {
                printf("※");
            }
            else if (getMapInfo(i, j) == g_ghostWall)
            {
                printf("□");
            }
        }

        printf("\r\n"); //新行换行
    }

}

const int CMap::getMapInfo(const int i, const int j) const
{
    return m_mapInfo[i][j];
}
 //Control.cpp
#include "Control.h"

/*
    每轮三条命,31 * 28, 4个幽灵,1个主角,4个特殊的豆子(吃了之后角色在10秒内可以吃掉幽灵,幽灵死亡回幽灵老家复活),每个豆子1分
    两个特殊的墙
*/
CControl::CControl()
{
    //初始化是否结束
    setIsOver(false);
    //初始化地图
    m_pMap = new CMap;
    //初始化玩家
    m_pPlayer = new CMove(true, g_player, g_road);
    m_pPlayer->setX(g_cols - 8);
    m_pPlayer->setY(g_rows / 2);
    m_pMap->setMapinfo(m_pPlayer->getX(), m_pPlayer->getY(), g_player);
    //初始化分数为1分,因为初始化位置为豆子
    setScore(1);
    //初始化幽灵
    m_pGhost = new CMove[4]{ 
        { false, g_ghost, g_road },{ false, g_ghost, g_road },
        { false, g_ghost, g_road },{ false, g_ghost, g_road }
    };

    for (int i = 0; i < 4; i++)
    {
        m_pGhost[i].setX(g_cols - 17);
        m_pGhost[i].setY(g_rows - 13 - i);
        m_pMap->setMapinfo(m_pGhost[i].getX(), m_pGhost[i].getY(), g_ghost);
    }

    srand((unsigned)time(NULL));
    time(&m_timeStart);
    m_pMap->showMap();
}

CControl::~CControl()
{
    if (m_pMap != nullptr)
    {
        delete m_pMap;
    }

    if (m_pPlayer != nullptr)
    {
        delete m_pPlayer;
    }

    if (m_pGhost != nullptr)
    {
        delete[] m_pGhost;
    }
}

bool CControl::getIsOver()
{
    bool isOver = false;

    for (int i = 0; i < 4; i++)
    {
        if (checkDie(m_pGhost[i]) == true)
        {
            isOver = true;
        }
    }

    if (checkDie(*m_pPlayer) == true)
    {
        isOver = true;
    }

    if (checkWin() == true)
    {
        isOver = true;
    }

    if (isOver == false)
    {
        ghostAutoMove();
        play();
    }
    else
    {
        setIsOver(true);
    }

    return m_bIsOver;
}

void CControl::play()
{
    
    if (_kbhit())
    {
        char cDis = _getch();
        switch (cDis)
        {
        case 'w':
        case 'W':
            startMove(*m_pPlayer, cDis);
            m_pMap->showMap();
            break;
        case 's':
        case 'S':
            startMove(*m_pPlayer, cDis);
            m_pMap->showMap();
            break;
        case 'a':
        case 'A':
            startMove(*m_pPlayer, cDis);
            m_pMap->showMap();
            break;
        case 'd':
        case 'D':
            startMove(*m_pPlayer, cDis);
            m_pMap->showMap();
            break;
        case 'p':
        case 'P':
            system("pause");
            break;
        default:
            break;
        }
    }
    
}

void CControl::setScore(int score)
{
    m_iScore = score;
}

const int CControl::getScore() const
{
    return m_iScore;
}

void CControl::setIsOver(const bool isOver)
{
    m_bIsOver = isOver;
}

void CControl::startMove(CMove& move, char direction)
{
    int x = move.getX();
    int y = move.getY();

    switch (direction)
    {
    case 'w':
    case 'W':
        x = x - 1;
        if (canMove(move, x, y))
        {
            //1.还原之前的地图类型
            m_pMap->setMapinfo(x + 1, y, move.getLastMapType());

            //2.如果移动的方向是豆子
            if (m_pMap->getMapInfo(x, y) == g_beans
                ||
                m_pMap->getMapInfo(x, y) == g_beans2
                )
            {
                //2.1.1如果是玩家移动
                if (move.getType() == g_player)
                {
                    //2.1.2设置上一个地图类型为路
                    move.setLastMapType(g_road);
                    m_pMap->setMapinfo(x, y, move.getType());
                    setScore(getScore() + 1);
                }
                //2.2如果是幽灵移动
                else if (move.getType() == g_ghost)
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, y));
                    m_pMap->setMapinfo(x, y, move.getType());
                }
            }
            //3.其它类型直接保存之前的类型,设置新地图类型
            else
            {
                move.setLastMapType(m_pMap->getMapInfo(x, y));
                m_pMap->setMapinfo(x, y, move.getType());
            }
            //4. 设置新位置
            move.setX(x);
        }
        break;
    case 's':
    case 'S':
        x = x + 1;
        if (canMove(move, x, y))
        {
            //1.还原之前的地图类型
            m_pMap->setMapinfo(x - 1, y, move.getLastMapType());

            //2.如果移动的方向是豆子
            if (m_pMap->getMapInfo(x, y) == g_beans
                ||
                m_pMap->getMapInfo(x, y) == g_beans2
                )
            {
                //2.1.1如果是玩家移动
                if (move.getType() == g_player)
                {
                    //2.1.2设置上一个地图类型为路
                    move.setLastMapType(g_road);
                    m_pMap->setMapinfo(x, y, move.getType());
                    setScore(getScore() + 1);
                }
                //2.2如果是幽灵移动
                else if (move.getType() == g_ghost)
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, y));
                    m_pMap->setMapinfo(x, y, move.getType());
                }
            }
            //3.其它类型直接保存之前的类型,设置新地图类型
            else
            {
                move.setLastMapType(m_pMap->getMapInfo(x, y));
                m_pMap->setMapinfo(x, y, move.getType());
            }
            //4. 设置新位置
            move.setX(x);
        }
        break;
    case 'a':
    case 'A':
        y = y - 1;
        //如果为特殊地图点
        if (x == 14 && y == -1)
        {
            //还原
            m_pMap->setMapinfo(x, y + 1, move.getLastMapType());
            //如果是玩家移动到这里
            if (move.getType() == g_player)
            {
                //判断跳转点是不是豆子
                if (m_pMap->getMapInfo(14, g_rows - 1) == g_beans)
                {
                    setScore(getScore() + 1);
                    move.setLastMapType(g_road);
                }
                else
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, g_rows - 1));
                }
            }
            else if (move.getType() == g_ghost)
            {
                move.setLastMapType(m_pMap->getMapInfo(x, 0));
            }

            move.setY(g_rows - 1);
            m_pMap->setMapinfo(move.getX(), move.getY(), move.getType());
            //setIsLastSpecialMove(true);
        }
        if (canMove(move, x, y))
        {
            //1.还原之前的地图类型
            m_pMap->setMapinfo(x, y + 1, move.getLastMapType());
            //2.如果移动的方向是豆子
            if (m_pMap->getMapInfo(x, y) == g_beans
                ||
                m_pMap->getMapInfo(x, y) == g_beans2
                )
            {
                //2.1.1如果是玩家移动
                if (move.getType() == g_player)
                {
                    //2.1.2设置上一个地图类型为路
                    move.setLastMapType(g_road);
                    m_pMap->setMapinfo(x, y, move.getType());
                    setScore(getScore() + 1);
                }
                //2.2如果是幽灵移动
                else if (move.getType() == g_ghost)
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, y));
                    m_pMap->setMapinfo(x, y, move.getType());
                }
            }
            //3.其它类型直接保存之前的类型,设置新地图类型
            else
            {
                move.setLastMapType(m_pMap->getMapInfo(x, y));
                m_pMap->setMapinfo(x, y, move.getType());
            }
            //4. 设置新位置
            move.setY(y);
        }
        break;
    case 'd':
    case 'D':
        y = y + 1;
        //如果为特殊地图点
        if (x == 14 && y == g_rows)
        {
            //还原
            m_pMap->setMapinfo(x, y - 1, move.getLastMapType());
            //如果是玩家移动到这里
            if (move.getType() == g_player)
            {
                //判断跳转点是不是豆子
                if (m_pMap->getMapInfo(14, 0) == g_beans)
                {
                    setScore(getScore() + 1);
                    move.setLastMapType(g_road);
                }
                else
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, 0));
                }
            }
            else if (move.getType() == g_ghost)
            {
                move.setLastMapType(m_pMap->getMapInfo(x, g_rows - 1));
            }

            move.setY(0);
            m_pMap->setMapinfo(move.getX(), move.getY(), move.getType());
            //setIsLastSpecialMove(true);
        }
        if (canMove(move, x, y))
        {
            //1.还原之前的地图类型
            m_pMap->setMapinfo(x, y - 1, move.getLastMapType());

            //2.如果移动的方向是豆子
            if (m_pMap->getMapInfo(x, y) == g_beans
                ||
                m_pMap->getMapInfo(x, y) == g_beans2
                )
            {
                //2.1.1如果是玩家移动
                if (move.getType() == g_player)
                {
                    //2.1.2设置上一个地图类型为路
                    move.setLastMapType(g_road);
                    m_pMap->setMapinfo(x, y, move.getType());
                    setScore(getScore() + 1);
                }
                //2.2如果是幽灵移动
                else if (move.getType() == g_ghost)
                {
                    move.setLastMapType(m_pMap->getMapInfo(x, y));
                    m_pMap->setMapinfo(x, y, move.getType());
                }
            }
            //3.其它类型直接保存之前的类型,设置新地图类型
            else
            {
                move.setLastMapType(m_pMap->getMapInfo(x, y));
                m_pMap->setMapinfo(x, y, move.getType());
            }
            //4. 设置新位置
            move.setY(y);
        }
        break;
    }
}

bool CControl::canMove(CMove& move, int x, int y)
{
    if (move.getType() == g_player)
    {
        if (m_pMap->getMapInfo(x, y) != g_wall
            &&
            m_pMap->getMapInfo(x, y) != g_ghostWall
            )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else if (move.getType() == g_ghost)
    {
        if (m_pMap->getMapInfo(x, y) != g_wall
            &&
            m_pMap->getMapInfo(x, y) != g_ghost
            )
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    else
    {
        return false;
    }
}

bool CControl::checkDie(CMove & move)
{
    if (move.getLastMapType() == g_player
        ||
        move.getLastMapType() == g_ghost
        )
    {
        setIsOver(true);
        return true;
    }
    else
    {
        return false;
    }
}

void CControl::ghostAutoMove()
{
    double cost;
    time(&m_timeStop);
    cost = difftime(m_timeStop, m_timeStart);

    if (cost >= 1.0f)
    {
        /*递归有问题
        for (int i = 0; i < 4; i++)
        {
            CMove tmpMove = findPlayer(
                m_pGhost[i],
                m_pGhost[i],
                m_pGhost[i].getX(), 
                m_pGhost[i].getY()
            );
            if (tmpMove.getX() != m_pGhost[i].getX())
            {
                if (tmpMove.getX() > m_pGhost[i].getX())
                {
                    startMove(m_pGhost[i], 's');
                }
                else
                {
                    startMove(m_pGhost[i], 'w');
                }
            }
            else
            {
                if (tmpMove.getY() > m_pGhost[i].getY())
                {
                    startMove(m_pGhost[i], 'a');
                }
                else
                {
                    startMove(m_pGhost[i], 'd');
                }
            }
        }
        */
        
        for (int i = 0; i < 4; i++)
        {
            int iDirection = rand() % 4;    //移动的方向0-3
            switch (iDirection)
            {
            case 0:
                if (canMove(m_pGhost[i], m_pGhost[i].getX() + 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 's');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() - 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 'w');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() + 1))
                {
                    startMove(m_pGhost[i], 'd');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() - 1))
                {
                    startMove(m_pGhost[i], 'a');
                }
                break;
            case 1:
                if (canMove(m_pGhost[i], m_pGhost[i].getX() - 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 'w');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() + 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 's');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() + 1))
                {
                    startMove(m_pGhost[i], 'd');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() - 1))
                {
                    startMove(m_pGhost[i], 'a');
                }
                break;
            case 2:
                if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() - 1))
                {
                    startMove(m_pGhost[i], 'a');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() - 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 'w');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() + 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 's');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() + 1))
                {
                    startMove(m_pGhost[i], 'd');
                }
                break;
            case 3:
                if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() + 1))
                {
                    startMove(m_pGhost[i], 'd');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX(), m_pGhost[i].getY() - 1))
                {
                    startMove(m_pGhost[i], 'a');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() - 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 'w');
                }
                else if (canMove(m_pGhost[i], m_pGhost[i].getX() + 1, m_pGhost[i].getY()))
                {
                    startMove(m_pGhost[i], 's');
                }
                break;
            }
        }

        time(&m_timeStart);
        m_pMap->showMap();
    }
}

CMove CControl::findPlayer(CMove move, CMove move2, int x, int y)
{
    if (m_pMap->getMapInfo(x, y) == g_player)
    {
        return move;
    }
    else if (canMove(move, x + 1, y)
        &&
        move2.getX() != x + 1
        )
    {
        move2.setX(move.getX());
        move2.setY(move.getY());
        move.setX(x + 1);
        findPlayer(move, move2, x + 1, y);
    }
    else if (canMove(move, x - 1, y)
        &&
        move2.getX() != x - 1
        )
    {
        move2.setX(move.getX());
        move2.setY(move.getY());
        move.setX(x - 1);
        findPlayer(move, move2, x - 1, y);
    }
    else if (canMove(move, x, y + 1)
        &&
        move2.getY() != y + 1
        )
    {
        move2.setX(move.getX());
        move2.setY(move.getY());
        move.setY(y + 1);
        findPlayer(move, move2, x, y + 1);
    }
    else if (canMove(move, x, y - 1)
        &&
        move2.getY() != y - 1
        )
    {
        move2.setX(move.getX());
        move2.setY(move.getY());
        move.setY(y - 1);
        findPlayer(move, move2, x, y - 1);
    }
}

bool CControl::checkWin()
{
    if (getScore() == 300)
    {
        return true;
    }
    else
    {
        return false;
    }
}
0 条评论
发表一条评论