C++小项目-吃豆子游戏

GMap.h

#pragma once //保证头文件只被编译一次

#include "stdafx.h"

#define MAP_LEN    19    //逻辑地图大小 (逻辑地图由行、列各为19的方块组成)

#define P_ROW 10 //大嘴出生地的横逻辑坐标
#define P_COLUMN 9 //大嘴出生地的列逻辑坐标
#define E_ROW 8 //敌人出生地的横逻辑坐标
#define E_COLUMN 9 //敌人出生地的列逻辑坐标

/*
    地图中应该存在障碍物和豆子,所以要有豆子和障碍物的尺寸和逻辑地图点阵,以及绘制地图(包括障碍物)和豆子的绘制函数
    以及颜色变量和设置敌我出生位置不能有豆子存在,以及地图类要能被物体类和大嘴类访问,故设置物体类和大嘴类为地图类的友元类
    下面为地图类,为关卡1、关卡2、关卡3的父类
*/
class GMap
{
protected:
    static int LD;    //障碍物的尺寸大小,设置为静态变量,因为要所有GMap对象共用这个变量
    static int PD;    //豆子的半径,设置为静态变量,因为要所有GMap对象共用这个变量
    bool mapData[MAP_LEN][MAP_LEN]; //障碍物逻辑地图点阵
    bool peaMapData[MAP_LEN][MAP_LEN]; //豆子逻辑地图点阵
    COLORREF color; //COLORREF是DWORD的宏,而DWORD是unsigned long
    //----
    void InitOP();    //使敌我双方的出生位置没有豆子存在

public:
    void DrawMap(HDC &hdc); //绘制地图
    void DrawPeas(HDC &hdc); //绘制豆子

    friend class GObject; //设置物体类为地图类的友元类,使物体类对象能访问地图类对象
    friend class PacMan; //设置大嘴类为地图类的友元类,使大嘴类对象能访问地图类对象
};

//关卡1类,为地图类的子类
class Stage_1:public GMap  //c++默认的是private继承,无法进行转换,所以继承后面都要有一个public
{
private:
    bool static initData[MAP_LEN][MAP_LEN]; //关卡逻辑地图点阵

public:
    Stage_1(); //构造函数
};

class Stage_2:public GMap
{
private:
    bool static initData[MAP_LEN][MAP_LEN];
public:
    Stage_2();
};
class Stage_3:public GMap
{
private:
    bool static initData[MAP_LEN][MAP_LEN];
public:
    Stage_3();
};

GMap.cpp 

#include "stdafx.h"
#include "GMap.h"

int GMap::LD =36; //初始化静态变量  障碍物的尺寸大小
int GMap::PD =3; //豆子的半径

//使敌我双方的出生位置没有豆子存在
void GMap::InitOP()
{
    peaMapData[P_ROW][P_COLUMN] = false; //让大嘴出生地的豆子消失 true,有豆子 false,无豆子
    peaMapData[E_ROW][E_COLUMN] = false; //让敌人出生地的豆子消失 true,有豆子 false,无豆子
}

//绘制地图
void GMap::DrawMap(HDC &hdc)
{
    for(int i=0;i<MAP_LEN;i++)
    {
        for(int j=0;j<MAP_LEN;j++)
        {
            if(!mapData[i][j]) //元素为B,即false,为墙壁/障碍物,则进入if内绘制   是A的位置不绘制,即为空白处
            {
                RECT rect; //矩形结构体对象
                rect.left = j*LD; //设置矩形4个方向启动的坐标
                rect.top = i*LD;
                rect.right = (j+1)*LD;
                rect.bottom = (i+1)*LD;

                FillRect(hdc,&rect,CreateSolidBrush(color)); //绘制矩形(墙壁/障碍物)
            }
        }
    }
}

//绘制豆子
void GMap::DrawPeas(HDC &hdc)
{
    for(int i=0;i<MAP_LEN;i++)
    {
        for(int j=0;j<MAP_LEN;j++)
        {
            if(peaMapData[i][j]) //元素为A,即true,为豆子,则进入if内绘制   是B的位置则不绘制豆子
            {
                Ellipse(hdc,(LD/2-PD)+j*LD,(LD/2-PD)+i*LD,(LD/2+PD)+j*LD,(LD/2+PD)+i*LD); //绘制圆弧(豆子)
            }
        }
    }
}

#define A true
#define B false

//初始化static数组InitData[MAP_LEN][MAP_LEN,即关卡1的原始数据    B表示障碍物/墙壁,A表示空白处(除出生地外的空白处有豆子)
bool Stage_1::initData[MAP_LEN][MAP_LEN] =
                      {
                        B,B,B,B,B,B,B,B,B,A,B,B,B,B,B,B,B,B,B,//0
                        B,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,B,//1
                        B,A,A,B,A,A,B,B,B,A,B,B,B,A,A,B,A,A,B,//2
                        B,A,B,B,A,A,A,A,A,A,A,A,A,A,A,B,B,A,B,//3
                        B,A,B,A,A,A,B,B,B,A,B,B,B,A,A,A,B,A,B,//4
                        B,A,B,A,A,A,A,A,A,A,A,A,A,A,A,A,B,A,B,//5
                        B,A,A,A,A,A,B,B,A,A,A,B,B,A,A,A,A,A,B,//6
                        B,A,B,A,A,A,A,A,A,A,A,A,A,A,A,A,B,A,B,//7
                        B,A,B,A,A,A,A,A,B,A,B,A,A,A,A,A,B,A,B,//8
                        A,A,A,A,A,A,A,A,B,B,B,A,A,A,A,A,A,A,A,//9
                        B,A,B,A,A,A,A,A,A,A,A,A,A,A,A,A,B,A,B,//10
                        B,A,B,A,A,B,A,A,A,A,A,A,A,B,A,A,B,A,B,//11
                        B,A,B,A,B,B,B,A,A,A,A,A,B,B,B,A,B,A,B,//12
                        B,A,A,A,A,B,A,A,A,A,A,A,A,B,A,A,A,A,B,//13
                        B,A,B,B,A,A,A,A,A,A,A,A,A,A,A,B,B,A,B,//14
                        B,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,B,//15
                        B,A,A,A,A,B,B,B,A,B,A,B,B,B,A,A,A,A,B,//16
                        B,A,A,A,A,B,A,A,A,A,A,A,A,B,A,A,A,A,B,//17
                        B,B,B,B,B,B,B,B,B,A,B,B,B,B,B,B,B,B,B,//18
                      };
#undef A
#undef B

Stage_1::Stage_1()
{
    color =RGB(140,240,240); //设置关卡1的地图颜色

    for(int i=0;i<MAP_LEN;i++)
    {
        for(int j=0;j<MAP_LEN;j++)
        {
            this->mapData[i][j] = this->initData[i][j]; //初始化关卡1的地图数据
            this->peaMapData[i][j] = this->initData[i][j]; //初始化关卡1的豆子数据
        }
    }

    //敌我双方出现位置没有豆子出现
    this->InitOP();
}

//Stage_2成员定义
#define A true
#define B false
bool Stage_2::initData[MAP_LEN][MAP_LEN]=
{
    B,B,B,B,B,B,B,B,B,A,B,B,B,A,B,B,B,B,B,//0
    A,A,A,A,A,A,A,B,A,A,B,A,A,A,B,A,B,A,A,//1
    B,A,A,A,B,A,A,B,A,A,B,A,B,A,B,A,B,A,B,//2
    B,B,B,A,B,A,A,B,B,A,B,A,B,A,B,A,B,B,B,//3
    B,A,A,A,A,A,A,A,A,A,A,A,B,B,B,A,A,A,B,//4
    B,A,A,B,A,A,A,A,A,A,A,A,A,A,A,A,A,A,B,//5
    B,A,A,B,A,A,A,B,B,B,B,B,B,A,A,B,A,A,B,//6
    B,A,A,B,A,B,A,A,A,A,A,A,A,A,A,B,A,A,B,//7
    B,A,A,B,A,B,A,A,B,A,B,A,A,B,A,B,A,A,B,//8
    A,A,A,B,A,B,A,A,B,B,B,A,A,B,A,B,A,A,A,//9
    B,A,A,B,A,B,A,A,A,A,A,A,A,B,A,A,A,A,B,//10
    B,A,A,B,A,A,A,B,B,B,B,B,A,B,A,A,A,A,B,//11
    B,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,B,//12
    B,A,A,A,B,B,B,B,B,B,B,A,A,A,A,A,A,A,B,//13
    B,A,A,A,A,A,A,A,A,A,A,A,A,B,A,A,A,A,B,//14
    B,B,B,B,B,A,A,A,A,B,B,B,A,B,A,A,A,A,B,//15
    B,A,A,A,B,B,B,A,A,A,A,B,A,B,B,B,A,A,B,//16
    A,A,A,A,B,A,A,A,A,A,A,B,A,A,A,B,A,A,A,//17
    B,B,B,B,B,B,B,B,B,A,B,B,B,A,B,B,B,B,B,//18
};
#undef A
#undef B

Stage_2::Stage_2()
{
    color = RGB(240,140,140);
    for(int i= 0;i<MAP_LEN;i++)
    {
        for(int j =0;j<MAP_LEN;j++)
        {
            this->mapData[i][j] = this->initData[i][j];
            this->peaMapData[i][j] = this->initData[i][j];
        }
    }
    //敌我双方出现位置没有豆子出现
    this->InitOP();
}

//Stage_3成员定义
#define A true
#define B false
bool Stage_3::initData[MAP_LEN][MAP_LEN]=
{
    B,B,B,B,B,B,B,B,B,A,B,B,B,B,B,B,B,B,B,//0
    A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,A,//1
    B,A,A,B,A,A,B,B,B,B,B,B,B,A,A,A,B,A,B,//2
    B,A,B,B,A,A,A,A,A,A,A,A,B,A,A,A,B,A,B,//3
    B,A,B,A,A,A,B,B,B,B,B,B,B,A,A,A,B,A,B,//4
    B,A,B,A,B,B,B,A,A,A,A,A,B,B,B,A,B,A,B,//5
    B,A,A,A,B,A,B,A,A,A,A,A,A,A,A,A,B,A,B,//6
    B,A,B,A,B,A,A,A,A,A,A,A,A,B,A,A,B,A,B,//7
    B,A,B,A,B,B,A,A,B,A,B,A,A,B,A,A,B,A,B,//8
    B,A,A,A,A,B,A,A,B,B,B,A,A,B,A,A,B,A,B,//9
    B,A,B,A,A,B,A,A,A,A,A,A,A,B,A,A,A,A,B,//10
    B,A,B,A,A,B,A,A,A,A,A,A,B,B,B,A,B,A,B,//11
    B,A,B,A,A,B,A,B,B,B,B,B,B,A,B,A,B,A,B,//12
    B,A,B,A,A,B,A,A,A,A,A,A,A,A,B,A,B,A,B,//13
    B,A,B,B,A,B,B,B,B,B,B,A,B,A,B,A,B,A,B,//14
    B,A,A,A,A,B,A,A,A,A,A,A,B,A,B,A,B,A,B,//15
    B,B,B,B,B,B,A,A,B,B,B,A,B,A,B,A,B,A,B,//16
    A,A,A,A,A,A,A,A,B,A,A,A,A,A,B,A,A,A,A,//17
    B,B,B,B,B,B,B,B,B,A,B,B,B,B,B,B,B,B,B,//18
};
#undef A
#undef B

Stage_3::Stage_3()
{
    color = RGB(100,300,100);
    for(int i= 0;i<MAP_LEN;i++)
    {
        for(int j =0;j<MAP_LEN;j++)
        {
            this->mapData[i][j] = this->initData[i][j];
            this->peaMapData[i][j] = this->initData[i][j];
        }
    }
    //敌我双方出现位置没有豆子出现
    this->InitOP();
}

GObject.h

#include "stdafx.h"
#include <time.h>
#include "GMap.h"

#define DISTANCE 10//图型范围
#define D_OFFSET   2//绘图误差
#define RD (DISTANCE + D_OFFSET)//绘图范围 12
//----
#define PLAYER_SPEED 6//玩家速度
#define ENERMY_SPEED 4//敌人速度
//----
#define LEGCOUNTS 5//敌人腿的数量
#define BLUE_ALERT 8//蓝色警戒范围

//方向枚举
enum TWARDS{UP,DOWN,LEFT,RIGHT,OVER};

//物体类 (含有纯虚函数,为抽象类,不能被实例化)
class GObject
{
protected:
    int dRow; //逻辑横坐标
    int dColumn; //逻辑纵坐标
    POINT point; //中心坐标
    int mX; //物体的中心横坐标
    int mY; //物体的中心纵坐标
    //----
    TWARDS twCommand;//朝向指令缓存
    TWARDS tw;//朝向
    //----
    int speed;//速度
    int frame;//帧数

    //子程序
    bool Achive(); //判断物体是否到达逻辑坐标位置
    int PtTransform(int k);//将实际坐标转换为逻辑坐标
    virtual void AchiveCtrl();//到达逻辑点后更新数据
    bool Collision() ;//逻辑碰撞检测,将物体摆放到合理的位置

public:
    static GMap* pStage; //指向地图类的指针,设置为静态,使所有自类对象都能够使用相同的地图

    GObject(int Row,int Column); //有参构造函数

    int GetRow(); //提供共有接口,获取保护成员变量dRow
    int GetArray(); //提供共有接口,获取保护成员变量dColumn
    virtual void action() = 0;//数据变更的表现
    //----
    void SetPosition(int Row,int Column); //设置自身中心位置
    void DrawBlank(HDC &hdc);
    virtual void Draw(HDC &hdc) = 0;//绘制对象

};

//大嘴,玩家控制的对象
class PacMan:public GObject //PacMan是GObject的子类
{
protected:
    virtual void AchiveCtrl();//重写虚函数 (到达逻辑点后更新数据)

public:
    PacMan(int Row,int Column);

    POINT GetPos(); //提供共有接口,获取保护成员变量point
    TWARDS GetTw(); //提供共有接口,获取保护成员变量twCommand
    //----
    bool Win(); //轮询peaMapData[][],判断是否存在任意一个豆子,来判断是否获胜
    void SetTwCommand(TWARDS command); //设置大嘴的移动方向指令
    void Over(); //设置大嘴的方向为OVER
    //----
    void Draw(HDC &hdc); //重写虚函数: 根据移动方向指令,绘制不同朝向的大嘴4帧动画
    void action();//数据变更的表现 (直接调用父类GObject的逻辑碰撞检测函数)
};

//追捕大嘴的敌人
class Enermy:public GObject //Enermy是GObject的子类
{
protected:
    void Catch(); //检测敌人是否抓捕到大嘴
    void virtual MakeDecision(bool b) = 0;//AI实现
    COLORREF color;

public:
    static PacMan* player; //在敌人类中,定义一个玩家(大嘴) 设置为静态变量,全部敌人追捕一个公共的玩家

    void virtual  Draw(HDC& hdc); //绘制敌人的图像
    Enermy(int x,int y);

    void virtual action();
};

//松散型的敌人,随机移动
class RedOne:public Enermy
{
protected:
    void virtual MakeDecision(bool b);
public:
    void Draw(HDC& hdc);
    RedOne(int x,int y):Enermy(x,y)
    {
        color = RGB(255,0,0); //松散型的敌人,颜色为红色
    }
};

//守卫者
class BlueOne:public RedOne
{
protected:
    void virtual MakeDecision(bool b);
public:
    void Draw(HDC& hdc);
    BlueOne(int x,int y):RedOne(x,y) //守卫者,颜色为蓝色
    {

        color = RGB(0,0,255);
    }

};

//扰乱者
class YellowOne:public RedOne
{
protected:
    void virtual MakeDecision(bool b);
public:
    void Draw(HDC& hdc);
    YellowOne(int x,int y):RedOne(x,y)
    {
        color = RGB(200,200,100); //扰乱者,颜色为黄色
    }
};

GObject.cpp

#include "stdafx.h"
#include "GObject.h"

//-----------------------------------------------------以下为GOject成员定义:------------------------------------------------
GMap* GObject::pStage =NULL; //静态变量使用前,必须先初始化

//有参构造函数  参数为物体出生地的逻辑坐标
GObject::GObject(int Row,int Column)
{
    this->dRow = Row; //逻辑横坐标
    this->dColumn = Column; //逻辑纵坐标
    this->point.y = dRow*pStage->LD + pStage->LD/2; //根据逻辑坐标换算获得中心坐标  【注意y方向对应的是行dRow,x方向对应的是列dColumn】
    this->point.x = dColumn*pStage->LD + pStage->LD/2;
    this->mX = point.x; //物体的中心横坐标
    this->mY = point.y ; //物体的中心纵坐标

    frame = 1; //初始帧数为1
    pStage = NULL; //初始化静态GMap指针
}

//提供共有接口,获取保护成员变量dRow
int GObject::GetRow()
{
    return dRow;
}

//提供共有接口,获取保护成员变量dColumn
int GObject::GetArray()
{
    return dColumn;
}

//判断物体是否到达逻辑坐标位置
bool GObject::Achive()
{
    //若物体在逻辑坐标位置,则point.x - pStage->LD/2 为pStage->LD的整数倍,取余为0
    if( (point.x - pStage->LD/2)%pStage->LD==0 && (point.y - pStage->LD/2)%pStage->LD==0 ) //到达逻辑坐标位置,返回true
    {
        return true; //到达逻辑坐标位置,返回true
    }

    return false; //未到达,返回false
}

//将实际坐标转换为逻辑坐标 k为point.x或者point.y
int GObject::PtTransform(int k)
{
    return (k - pStage->LD/2)/pStage->LD;
}

//到达逻辑坐标位置后更新数据
void GObject::AchiveCtrl() //声明时,为虚函数,定义加virtual会报错
{
    if(Achive()) //先判断是否到达逻辑坐标位置
    {
        dRow = PtTransform(point.y); //更新活动逻辑横坐标,由实际横坐标转换而来 【注意y方向对应的是行dRow,x方向对应的是列dColumn】
        dColumn = PtTransform(point.x); //更新活动逻辑纵坐标,由实际纵坐标转换而来
    }
}

//逻辑碰撞检测,将物体摆放到合理的位置    返回指令有效与否的标志位
bool GObject::Collision()
{
    bool cmdValid_flag = true; //指令有效与否的标志位  ==true,指令有效  ==false,指令无效

    //检测逻辑碰撞前,先更新数据,直到到达逻辑坐标位置,进行逻辑碰撞检测
    AchiveCtrl(); //更新逻辑坐标数据,若物体是大嘴,则会执行PacMan重写的AchiveCtrl()消除豆子

    //判断指令的有效性
    if(dRow<0 || dColumn<0 || dRow>MAP_LEN-1 || dColumn>MAP_LEN-1) //逻辑横、纵坐标超出允许范围,即在屏幕外,则不可以改变指令(新指令无效)
        cmdValid_flag = false; //(新)指令无效
    else if (Achive()) //到达逻辑坐标位置,才能进行逻辑碰撞检测
    {
        switch(twCommand) //判断前进的方向
        {
        case LEFT:
            {
                if(dColumn>0 && !pStage->mapData[dRow][dColumn-1]) //判断下一个格子是否是墙/障碍物  是墙,则!B=!false=true
                    cmdValid_flag = false; //下一个格子是墙/障碍物,(新)指令无效
            }
            break;
        case RIGHT:
            {
                if(dColumn<MAP_LEN-1 && !pStage->mapData[dRow][dColumn+1])
                    cmdValid_flag = false;
            }
            break;
        case UP:
            {
                if(dRow>0 && !pStage->mapData[dRow-1][dColumn])
                    cmdValid_flag = false;
            }
            break;
        case DOWN:
            {
                if(dRow<MAP_LEN-1 && !pStage->mapData[dRow+1][dColumn])
                    cmdValid_flag = false;
            }
            break;
        }

        if(cmdValid_flag)
            tw = twCommand; //前进方向上的下一方格不是墙壁/障碍物,则指令成功,改变方向有效
    }

    //依照真实的方向移动
    mX = point.x;
    mY = point.y;
    int MAX = pStage->LD*MAP_LEN + pStage->LD/2; //超出地图右、下边界一个方格的位置(注意是"中心"坐标)
    int MIN = pStage->LD/2; //超出地图左、上边界一个方格的位置

    switch(tw)//判断行进的方向
    {
    case LEFT:
        if(dColumn>0 && !pStage->mapData[dRow][dColumn-1])//判断下一个格子是否能够通行
        {
            cmdValid_flag= false;
            break;//"撞墙了"
        }
        point.x -= speed; //改变物体在地图上的中心坐标,相当于物体在地图中移动(这里向左移动)
        if(point.x<MIN) //向左移动到了地图左边界外半个方格外,则从另一边出现
        {
            point.x = MAX;
        }

        break;
        //以下方向的判断原理相同
    case RIGHT:
        if(dColumn<MAP_LEN-1&&!pStage->mapData[dRow][dColumn+1])
        {
            cmdValid_flag= false;
            break;//"撞墙了"
        }
        point.x += speed;
        if(point.x>MAX)
        {
            point.x = MIN;
        }

        break;
    case UP:
        if(dRow>0&&!pStage->mapData[dRow-1][dColumn])
        {
            cmdValid_flag= false;
            break;//"撞墙了"
        }
        point.y -=speed;
        if(point.y<MIN)
        {
            point.y = MAX;
        }
        break;
    case DOWN:
        if(dRow<MAP_LEN-1&&!pStage->mapData[dRow+1][dColumn])
        {
            cmdValid_flag= false;
            break;//"撞墙了"
        }
        point.y +=speed;
        if(point.y>MAX)
        {
            point.y = MIN;
        }
        break;
    }

    return !cmdValid_flag; //返回指令有效与否的标志位
}

//设置自身中心位置
void GObject::SetPosition(int Row,int Column)
{
    dRow = Row;
    dColumn = Column;

    point.y = dRow*pStage->LD + pStage->LD/2; //根据逻辑坐标换算获得中心坐标 【注意y方向对应的是行dRow,x方向对应的是列dColumn】
    point.x = dColumn*pStage->LD + pStage->LD/2;
}

//将这一帧时物体所在的方格处绘制的图像擦除,移动后再绘制下一方格的图像,使物体看起来像在移动一样
void GObject::DrawBlank(HDC &hdc)
{
    RECT rect;

    rect.left = mX - RD; //这一帧时物体所在的方格(矩形),4个方向边缘坐标
    rect.top = mY - RD;
    rect.right = mX + RD;
    rect.bottom = mY + RD;

    FillRect(hdc,&rect,CreateSolidBrush(RGB(255,255,255)));
}

//-----------------------------------------------------以下为PacMan(大嘴)成员定义:------------------------------------------------

PacMan::PacMan(int Row,int Column):GObject(Row,Column) //使用初始化列表,同时初始化了PacMan::dROW、dColumn、point.x、point.y等等
{
    this->speed = PLAYER_SPEED; //设置大嘴速度
    twCommand = tw = LEFT; //设置开局时大嘴的移动方向
}

//提供共有接口,获取保护成员变量point
POINT PacMan::GetPos()
{
    return point;
}

//设置大嘴的方向为OVER
void PacMan::Over()
{
    tw = OVER;
}

//提供共有接口,获取保护成员变量tw
TWARDS PacMan::GetTw()
{
    return tw;
}

//设置大嘴的移动方向指令
void PacMan::SetTwCommand(TWARDS command)
{
    twCommand = command;
}

//轮询peaMapData[][],判断是否存在任意一个豆子,来判断是否获胜
bool PacMan::Win()
{
    for(int i=0;i<=MAP_LEN;i++)
    {
        for(int j=0;j<=MAP_LEN;j++)
        {
            if(pStage->peaMapData[i][j]==true)
            {
                return false; //存在任意一个豆子,没取得胜利
            }
        }
    }
    return true;//没有豆子,胜利
}

//重写虚函数 (到达逻辑点后更新数据)
void PacMan::AchiveCtrl()
{
    GObject::AchiveCtrl(); //直接调用GObject类的功能函数: 到达逻辑坐标位置后更新数据

    //重写虚函数,为实现大嘴的吃豆子功能
    if(Achive()) //必须到达逻辑坐标位置,才能进行下一步
    {
        if(dRow>=0 && dRow<MAP_LEN && dColumn>=0 && dColumn<MAP_LEN)//防止数组越界
        {
            //peaMapData[dRow][dColumn]:   ==true,表示有豆子   ==false,表示没有豆子
            if(pStage->peaMapData[dRow][dColumn]) //豆子到达的逻辑坐标位置,如果有豆子
            {
                pStage->peaMapData[dRow][dColumn] = false; //则将豆子"吃掉"
            }
        }
    }
}

//行为函数,直接调用父类GObject的逻辑碰撞检测函数
void PacMan::action()
{
    Collision(); //直接调用父类GObject的逻辑碰撞检测函数
}

//重写虚函数: 根据移动方向指令,绘制不同朝向的大嘴4帧动画
void PacMan::Draw( HDC& hdc)
{
    if(tw == OVER) //移动指令为OVER,无效,不执行如何程序
    {

    }
    else if(frame%2 == 0) //绘制第2帧动画和第4帧动画 (都是V形开口的圆弧)
    {
        int x1=0,x2=0,y1=0,y2=0;
        int offsetX =  DISTANCE/2+D_OFFSET;//弧弦交点 10/2+2 = 7
        int offsetY =  DISTANCE/2+D_OFFSET;//弧弦交点
        switch(tw) //移动方向不同,(大嘴)圆弧的V形开口不同
        {
            case UP:
                x1 = point.x - offsetX;
                x2 = point.x + offsetX;
                y2 = y1 = point.y-offsetY;
            break;
            case DOWN:
                x1 = point.x + offsetX;
                x2 = point.x - offsetX;
                y2 = y1 = point.y+offsetY;
            break;
            case LEFT:
                x2 = x1 = point.x-offsetX;
                y1 = point.y + offsetY;
                y2 = point.y - offsetY;
            break;
            case RIGHT: //V形开口向右
                x2 = x1 =point.x + offsetX;
                y1 = point.y - offsetY;
                y2 = point.y + offsetY;
            break;
        }

        //绘制圆弧   RIGHT朝向情况下,x1,y1和x2,y2各为右上角、右下角的弧弦交点
        Arc(hdc,point.x-DISTANCE,point.y-DISTANCE,
            point.x+DISTANCE,point.y+DISTANCE,
            x1,y1,
            x2,y2);
        MoveToEx(hdc,x1,y1,NULL); //RIGHT朝向情况下,移动坐标原点到右上角的弧弦交点
        LineTo(hdc,point.x,point.y); //绘制右上角的弧弦交点到大嘴中心坐标点的直线
        LineTo(hdc,x2,y2); //绘制大嘴中心坐标点到右下角的弧弦交点的直线
    }
    else if(frame%3 ==0) //绘制第3帧动画 (椭圆)
    {
        Ellipse(hdc,point.x-DISTANCE,point.y-DISTANCE,
            point.x+DISTANCE,point.y+DISTANCE);
    }
    else  //绘制第1帧动画 半圆
    {
        int x1=0,x2=0,y1=0,y2=0;
        switch(tw)
        {
            case UP:
                x1 = point.x - DISTANCE;
                x2 = point.x + DISTANCE;
                y2 = y1 = point.y;
            break;
            case DOWN:
                x1 = point.x + DISTANCE;
                x2 = point.x - DISTANCE;
                y2 = y1 = point.y;
            break;
            case LEFT:
                x2 = x1 = point.x;
                y1 = point.y + DISTANCE;
                y2 = point.y - DISTANCE;
            break;
            case RIGHT:
                x2 = x1 =point.x ;
                y1 = point.y - DISTANCE;
                y2 = point.y + DISTANCE;
            break;
        }

        Arc(hdc,point.x-DISTANCE,point.y-DISTANCE,
            point.x+DISTANCE,point.y+DISTANCE,
            x1,y1,
            x2,y2);
        MoveToEx(hdc,x1,y1,NULL);
        LineTo(hdc,point.x,point.y);
        LineTo(hdc,x2,y2);
    }

    frame++;//绘制下一祯
}

//-----------------------------------------------------以下为Enermy(敌人)成员定义:------------------------------------------------

PacMan* Enermy::player = NULL; //在敌人类中,定义一个玩家(大嘴) 设置为静态变量,全部敌人追捕一个公共的玩家

//Enermy(敌人)的构造函数
Enermy::Enermy(int x,int y):GObject(x,y)
{
    this->speed = ENERMY_SPEED; //设置敌人的速度
    twCommand = tw = LEFT; //设置开局时,敌人的移动方向
    //twCommand = UP;
}

//检测敌人是否抓捕到大嘴
void Enermy::Catch()
{
    int DX =point.x - player->GetPos().x; //敌人与玩家的中心坐标,在x方向上的距离
    int DY =point.y - player->GetPos().y; //敌人与玩家的中心坐标,在y方向上的距离

    //敌人与玩家的中心坐标,在x、y方向上的距离小于绘图距离RD,则说明敌人和玩家接触了一半身体  敌人和玩家的直径接近2*RD,实际是2*DISTANCE
    if((-RD<DX && DX<RD) && (-RD<DY && DY<RD))
    {
        player->Over(); //敌人抓到了玩家,玩家方向设置为OVER,不能再移动了
    }
}

//绘制敌人的图像
void Enermy::Draw(HDC& hdc)
{
    HPEN pen =::CreatePen(0,0,color); //创建画笔
    HPEN oldPen = (HPEN)SelectObject(hdc,pen); //应用创建的画笔

    Arc(hdc,point.x-DISTANCE,point.y-DISTANCE,
        point.x+DISTANCE,point.y+DISTANCE,
        point.x+DISTANCE,point.y,
        point.x-DISTANCE,point.y);//先绘制半圆型的头

    int const LEGLENTH = (DISTANCE)/(LEGCOUNTS); //LEGLENTH为“腿部圆弧”的半径

    //根据祯数来绘制身体和“腿部”
    if(frame%2 == 0) //绘制第2帧和第4帧图像
    {
        //绘制2根直线,作为敌人的身子
        MoveToEx(hdc,point.x-DISTANCE,point.y,NULL);//矩形的身子
        LineTo(hdc,point.x-DISTANCE,point.y +DISTANCE - LEGLENTH);
        MoveToEx(hdc,point.x+DISTANCE,point.y,NULL);
        LineTo(hdc,point.x+DISTANCE,point.y +DISTANCE - LEGLENTH);

        for(int i = 0;i<LEGCOUNTS;i++)//从左往右绘制“腿部”
        {
            //绘制腿部,为多个圆弧
            Arc(hdc,point.x-DISTANCE+i*2*LEGLENTH,point.y+DISTANCE-2*LEGLENTH,
                point.x-DISTANCE+(i+1)*2*LEGLENTH,point.y+DISTANCE,
                point.x-DISTANCE+i*2*LEGLENTH,point.y+DISTANCE-LEGLENTH,
                point.x-DISTANCE+(i+1)*2*LEGLENTH,point.y+DISTANCE-LEGLENTH
                );
        }
    }
    else //绘制第1帧和第3帧图像
    {
        MoveToEx(hdc,point.x-DISTANCE,point.y,NULL);//绘制身体
        LineTo(hdc,point.x-DISTANCE,point.y +DISTANCE);
        MoveToEx(hdc,point.x+DISTANCE,point.y,NULL);
        LineTo(hdc,point.x+DISTANCE,point.y +DISTANCE);
        //从左往右绘制“腿部”

        MoveToEx(hdc,point.x-DISTANCE,point.y+DISTANCE,NULL);
        LineTo(hdc,point.x-DISTANCE+LEGLENTH,point.y+DISTANCE-LEGLENTH);

        for(int i = 0;i<LEGCOUNTS-1;i++)
        {
            Arc(hdc,point.x-DISTANCE+(1+i*2)*LEGLENTH,point.y+DISTANCE-2*LEGLENTH,
                point.x-DISTANCE+(3+i*2)*LEGLENTH,point.y+DISTANCE,
                point.x-DISTANCE+(1+i*2)*LEGLENTH,point.y+DISTANCE-LEGLENTH,
                point.x-DISTANCE+(3+i*2)*LEGLENTH,point.y+DISTANCE-LEGLENTH
                );
        }

        MoveToEx(hdc,point.x+DISTANCE,point.y+DISTANCE,NULL);
        LineTo(hdc,point.x+DISTANCE-LEGLENTH,point.y+DISTANCE-LEGLENTH);
    }

    //根据方向绘制眼睛
    int R = DISTANCE/5; //眼睛的半径
    switch(tw)
    {
        case UP:
            Ellipse(hdc,point.x-2*R,point.y-2*R,point.x,point.y);
            Ellipse(hdc,point.x,point.y-2*R,point.x+2*R,point.y);
        break;
        case DOWN:
            Ellipse(hdc,point.x-2*R,point.y,point.x,point.y+2*R);
            Ellipse(hdc,point.x,point.y,point.x+2*R,point.y+2*R);
        break;
        case LEFT:
            Ellipse(hdc,point.x-3*R,point.y-R,point.x-R,point.y +R);
            Ellipse(hdc,point.x-R,point.y-R,point.x+R,point.y +R);
        break;
        case RIGHT:
            Ellipse(hdc,point.x-R,point.y-R,point.x+R,point.y +R);
            Ellipse(hdc,point.x+R,point.y-R,point.x+3*R,point.y+R);
        break;
    }

    frame++; //准备绘制下一祯

    SelectObject(hdc,oldPen);
    DeleteObject(pen); //销毁画笔

    return;
}

//敌人:数据变更的表现
void Enermy::action()
{
    bool b = Collision();
    MakeDecision(b);
    Catch();
}

//-----------------------------------------------------以下为RedOne(敌人)成员定义:------------------------------------------------

//绘制RedOne(敌人)的图像
void RedOne::Draw(HDC& hdc)
{
    Enermy::Draw(hdc);
}

//AI-人工智能函数: 松散型
void RedOne::MakeDecision(bool b)
{
    //srand(time(0));
    int i = rand();
    if(b)//撞到墙壁,改变方向
    {
        //逆时针转向
        if(i%4==0)
        {
            tw == UP?twCommand = LEFT:twCommand=UP;
        }
        else if(i%3==0)
        {
            tw == DOWN?twCommand =RIGHT:twCommand=DOWN;
        }
        else if(i%2==0)
        {
            tw == RIGHT?twCommand = UP:twCommand=RIGHT;
        }
        else
        {
            tw == LEFT?twCommand = DOWN:twCommand=LEFT;
        }
        return;
    }

    if(i%4==0)
    {
        twCommand!=UP?tw==DOWN:twCommand ==UP;
    }
    else if(i%3==0)
    {
        tw != DOWN?twCommand = UP:twCommand=DOWN;
    }
    else if(i%2==0)
    {
        tw != RIGHT?twCommand = LEFT:twCommand=RIGHT;
    }
    else
    {
        tw != LEFT?twCommand = RIGHT:twCommand=LEFT;
    }

}

//-----------------------------------------------------以下为BlueOne(敌人)成员定义:------------------------------------------------

//绘制BlueOne(敌人)的图像
void BlueOne::Draw( HDC& hdc)
{
    Enermy::Draw(hdc);
}

//AI-人工智能函数: 守卫者
void BlueOne::MakeDecision(bool b)
{

    const int DR = this->dRow-player->GetRow();
    const int DA = this->dColumn-player->GetArray();
    if(!b&&DR==0)
    {
        if(DA<=BLUE_ALERT&&DA>0)//玩家在左侧边警戒范围s
        {
            twCommand = LEFT;    //向左移动
            return;
        }
        if(DA<0&&DA>=-BLUE_ALERT)//右侧警戒范围
        {
            twCommand = RIGHT;//向右移动
            return;
        }
    }
    if(!b&&DA==0)
    {
        if(DR<=BLUE_ALERT&&DR>0)//下方警戒范围
        {
            twCommand = UP;
            return;
        }
        if(DR<0&&DR>=-BLUE_ALERT)//上方警戒范围
        {
            twCommand = DOWN;
            return;
        }
    }

    RedOne::MakeDecision(b);//不在追踪模式时RED行为相同
}

//-----------------------------------------------------以下为YellowOne(敌人)成员定义:------------------------------------------------

//绘制YellowOne(敌人)的图像
void YellowOne::Draw(HDC& hdc)
{
    Enermy::Draw(hdc);
}

//AI-人工智能函数:扰乱者
void YellowOne::MakeDecision(bool b)
{
    const int DR = this->dRow-player->GetRow();
    const int DA = this->dColumn-player->GetArray();
    if(!b)
    {
        if(DR*DR>DA*DA)
        {
            if(DA>0)//玩家在左侧边警戒范围
            {
                twCommand = LEFT;    //向左移动
                return;
            }
            else if(DA<0)//右侧警戒范围
            {
                twCommand = RIGHT;//向右移动
                return;
            }
        }
        else
        {
            if(DR>0)//下方警戒范围
            {
                twCommand = UP;
                return;
            }
            if(DR<0)//上方警戒范围
            {
                twCommand = DOWN;
                return;
            }
        }
    }
    RedOne::MakeDecision(b);
}

PacMan.cpp(包含主函数)

// pacman.cpp : 定义应用程序的入口点。
//

#include "stdafx.h"
#include "pacman.h"
#include "GObject.h"

//-----start-----
#define WLENTH 700
#define WHIGHT 740
#define STAGE_COUNT 3 //关卡数

//游戏物体
PacMan* p ;
GObject* e1;
GObject* e2 ;
GObject* e3 ;
GObject* e4 ;

//释放动态内存函数模板
template<class T>
void Realese(T t)
{
    if(t!=NULL)
        delete t;
}

//进入下一关卡的时候,还原所有物体的位置
void ResetGObjects()
{
    p->SetPosition(P_ROW,P_COLUMN);
    e1->SetPosition(E_ROW,E_COLUMN);
    e2->SetPosition(E_ROW,E_COLUMN);
    e3->SetPosition(E_ROW,E_COLUMN);
    e4->SetPosition(E_ROW,E_COLUMN);
}

//------end------

#define MAX_LOADSTRING 100

// 全局变量:
HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名s

// 此代码模块中包含的函数的前向声明:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE,int,HWND&);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR    lpCmdLine,
    int       nCmdShow)
{

    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: 在此放置代码。
    int s_n = 0;//进行到的关卡数
    p = new PacMan(P_ROW,P_COLUMN);
    e1 =new RedOne(E_ROW,E_COLUMN);
    e2 =new RedOne(E_ROW,E_COLUMN);
    e3 = new BlueOne(E_ROW,E_COLUMN);
    e4 = new YellowOne(E_ROW,E_COLUMN);
    GMap* MapArray[STAGE_COUNT] = {new Stage_1(),new Stage_2(),new Stage_3()};
    GObject::pStage =MapArray[s_n];//初始化为第一关地图
    Enermy::player = p;
    //-----end-----

    MSG msg;
    HACCEL hAccelTable;

    // 初始化全局字符串
    LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadString(hInstance, IDC_PACMAN, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // 执行应用程序初始化: 【改写了】
    HWND hWnd;
    if (!InitInstance (hInstance, nCmdShow,hWnd))
    {
        return FALSE;
    }
    hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PACMAN));

    DWORD t =0;
    // 主消息循环:
    while(p->GetTw()!=OVER&&s_n<3)
    {
        if(p->Win()) //赢了,p->Win()返回true
        {
            HDC hdc = GetDC(hWnd);
            s_n++;
            ResetGObjects(); //进入下一关卡的时候,还原所有物体的位置
            if(s_n <3)
            {
                MessageBoxA(hWnd,"恭喜您过关","吃豆子提示",MB_OK);
                GObject::pStage = MapArray[s_n];
                RECT screenRect;
                screenRect.top = 0;
                screenRect.left = 0;
                screenRect.right = WLENTH;
                screenRect.bottom = WHIGHT;
                ::FillRect(hdc,&screenRect,CreateSolidBrush(RGB(255,255,255)));
                GObject::pStage->DrawMap(hdc);
            }
            continue;
        }

        if(PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if(GetAsyncKeyState(VK_DOWN)&0x8000)
        {
            p->SetTwCommand(DOWN);
        }

        if(GetAsyncKeyState(VK_LEFT)&0x8000)
        {
            p->SetTwCommand(LEFT);
        }

        if(GetAsyncKeyState(VK_RIGHT)&0x8000)
        {
            p->SetTwCommand(RIGHT);
        }

        if(GetAsyncKeyState(VK_UP)&0x8000)
        {
            p->SetTwCommand(UP);
        }

        else
        {
            if(GetTickCount()-t>58) //每58ms,游戏的数据和画面会更新一次
            {
                HDC hdc = GetDC(hWnd);
                e1->action();
                e2->action();
                e3->action();
                e4->action();
                p->action();

                GObject::pStage->DrawPeas(hdc);
                e1->DrawBlank(hdc);
                e2->DrawBlank(hdc);
                e3->DrawBlank(hdc);
                e4->DrawBlank(hdc);    

                p->DrawBlank(hdc);
                e1->Draw(hdc);
                e2->Draw(hdc);
                e3->Draw(hdc);
                e4->Draw(hdc);
                p->Draw(hdc);

                DeleteDC(hdc); //销毁上下文设备

                t = GetTickCount(); //GetTickCount()函数获得的是从开机到当前时刻机器运行的毫秒数
            }
        }
    }

    Realese(e1);
    Realese(e2);
    Realese(e3);
    Realese(e4);

    for(int i = 0;i<STAGE_COUNT;i++)
    {
        Realese(MapArray[i]);
    }

    if(p->GetTw()==OVER)
    {
        MessageBoxA(hWnd,"出师未捷","吃豆子提示",MB_OK);
    }
    else
    {
        MessageBoxA(hWnd,"恭喜您赢得了胜利","吃豆子提示",MB_OK);
    }

    Realese(p);

    return (int) msg.wParam;
}

//
//  函数: MyRegisterClass()
//
//  目的: 注册窗口类。
//
//  注释:
//
//    仅当希望
//    此代码与添加到 Windows 95 中的“RegisterClassEx”
//    函数之前的 Win32 系统兼容时,才需要此函数及其用法。调用此函数十分重要,
//    这样应用程序就可以获得关联的
//    “格式正确的”小图标。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style            = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra        = 0;
    wcex.cbWndExtra        = 0;
    wcex.hInstance        = hInstance;
    wcex.hIcon            = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_PACMAN));
    wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wcex.hbrBackground    = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName    = MAKEINTRESOURCE(IDC_PACMAN);
    wcex.lpszClassName    = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//
//   函数: InitInstance(HINSTANCE, int)
//
//   目的: 保存实例句柄并创建主窗口
//
//   注释:
//
//        在此函数中,我们在全局变量中保存实例句柄并
//        创建和显示主程序窗口。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow,HWND& hWnd)  //【改写了,增加了一个参数HWND& hWnd】
{

    hInst = hInstance; // 将实例句柄存储在全局变量中

    hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
        0, 0, WLENTH, WHIGHT, NULL, NULL, hInstance, NULL);

    if (!hWnd)
    {
        return FALSE;
    }

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    return TRUE;
}

//
//  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  目的: 处理主窗口的消息。
//
//  WM_COMMAND    - 处理应用程序菜单
//  WM_PAINT    - 绘制主窗口
//  WM_DESTROY    - 发送退出消息并返回
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
    case WM_COMMAND:
        wmId    = LOWORD(wParam);
        wmEvent = HIWORD(wParam);
        // 分析菜单选择:
        switch (wmId)
        {
        case IDM_ABOUT:
            DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
            break;
        case IDM_START:

        case IDM_EXIT:
            DestroyWindow(hWnd);
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        break;
    case WM_PAINT:
        hdc = BeginPaint(hWnd, &ps);
        // TODO: 在此添加任意绘图代码...
        GObject::pStage->DrawMap(hdc);
        EndPaint(hWnd, &ps);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        ::exit(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// “关于”框的消息处理程序。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

原文地址:https://www.cnblogs.com/linuxAndMcu/p/9736873.html

时间: 2024-10-14 05:48:00

C++小项目-吃豆子游戏的相关文章

Java小项目之拼图游戏

首先声明,代码是自创的,如有雷同,不胜荣幸! 先谈谈思路: 1.设计界面. 2.素材的处理. 3.设计图片加载区域的图片加载处理类. 4.设计按钮组中的按钮初始化方法. 5.设计按钮组中的随机图片加载方法. 6.设计重置按钮方法. 7.设计按钮监听器. 8.设计判定胜利的条件的方法. 1.界面的设计: a.使用了Windows Builder插件,安装网页:WindoswBuilder - http://download.eclipse.org/windowbuilder/WB/integrat

小项目特供 贪吃蛇游戏(基于C语言)

C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第二天写了第二版和第三版. 相信C语言写个小游戏或小项目是大多数计算机相关专业的学生都做的事情,但是作为一个数学专业的学生,我们教研室的老师对C语言的要求也就比较低了,大一没有让我们做个小项目实践一次.至今为止用C/C++做过的三个小项目(大作业),一个是外校同学让我帮忙写的学生信息管理系统(天呐,这

java小项目之:扫雷,这游戏其实没有那么简单!

扫雷我之前分享的小项目和小游戏,电影购票.坦克大战.捕鱼达人.贪吃蛇等,虽然已经是耳熟能详人尽皆知的项目和游戏,但是保不齐真的有人没接触过.今天分享的这个项目,我不相信没人接触过(仅限80后-00后).扫雷,这几乎所有电脑都有的一款超级小游戏,在全国各地的微机课上饱受欢迎,玩法紧张刺激.老少皆宜,而且还益智.今天便分享用java怎么实现这一款神作.(文末附带源码素材获取方式)游戏介绍:扫雷就是要把所有非地雷的格子揭开即胜利:踩到地雷格子就算失败.游戏主区域由很多个方格组成.使用鼠标左键随机点击一

Java小项目之:拼图游戏!

Java小项目之:拼图游戏!今天教大家用java做出一个拼图游戏,很适合java初学者练手.所用素材: 部分代码: package picture_mosical; import java.awt.Graphics; import java.awt.Image; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.awt.image.CropImageFilter; import java.awt.i

[业余项目]黄金点游戏

准备业余时间做一下这个: 创新的时机 – 黄金点游戏 结对和团队项目建议 - 黄金点游戏 --------------------------------------------------------------------------------------------------------------------------------------------------------- 在<移山之道>里, 我提到移山软件学院的游戏: 阿超的课都是下午两点钟,这时班上不少的同学都昏昏欲睡

轮播特效小项目总结

首先谈谈关于还原设计稿学到的一些东西,比如说网页设计稿和交互效果做好了,拿给我们在网页上实现,那如何实现呢,我就说说自己的鄙见吧. 第一,思考整个设计图的层次,比如说分别由哪些部分构成,针对这些"块",怎么设计div的结构,怎么把静态页面有条理的编写出来. 第二,思考如何实现设计图的交互效果,在逻辑上分析,比如用JS绑定哪些事件,采用什么样的函数实现怎么样的效果等等. 第三,代码的优化性考虑,怎么让代码简洁明了,方便维护. 以上就是我现在阶段对页面还原的一些看法,也许比较浅显,我也希望

手把手教学MFC吃豆子教程

手把手教学MFC吃豆子教程 本教程适用于零基础学员制作C++课程设计 编程工具:VC++6.0. 本次教学主要知识点: 1.控件消息响应. 2.CDC类函数的使用. 下面开始教学: 吃豆子的基本思想: 1.定义脸和食物类. 2.不断将脸的上一个坐标重绘为白色,将新的脸绘制出来,从而在宏观上实现脸的移动. 3.运用OnTimer()函数制作时钟更新画面,运用OnKeyDown()接收键盘消息. 首先创建工程:我们选择的是MFC AppW的单文档工程. xxxxxxxxxxxxxxxxxxxxxxx

小项目创意大集合

每个程序员都可以入手的小项目创意大集合 我经常看有人发帖问关于软件项目创意点子的事,也看到了很多回帖,我自己也回了一些常见的软件项目创意.不过我觉得只列出三两个是远远不够的,因此就收集并这个软件项目创意列表,大家要找简单的编程软件项目创意学习练手的话,可以收藏并扩散本文.这些软件项目创意并不是论文级别的,只是想抛砖引玉让大家能从中受些启发. 下面你们会看到 120 多个个软件项目创意想法,都是我通过头脑风暴得来的.我将其根据主题分成了10 个分类,但有些软件项目创意其实涵盖了不止一个主题. 更新

小项目特供 简易迷宫(基于Java)

明天返校,于是昨天和今天简单熟系了一下JAVA的GUI,做了一个简易的迷宫小游戏(暂时没有时间实现随机迷宫及多关卡,仅供学习) 源码及运行文件(提供JRE8):简易迷宫  访问密码 8dd8 小项目特供 简易迷宫(基于Java)