C/C++实现植物大战僵尸(PVZ)(打地鼠版)

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

🚀欢迎互三👉:程序猿方梓燚 💎💎
🚀关注博主,后期持续更新系列文章
🚀如果有错误感谢请大家批评指出,及时修改
🚀感谢大家点赞👍收藏⭐评论✍

游戏效果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、准备工作

确保你安装了一个 C++ 编译器,如 Visual Studio 2019 等。安装了EasyX图形库。并且了解基本的 C++ 语法,包括变量声明、数据类型、控制结构(如循环和条件语句)等。

二、代码结构概述

整个代码实现了一个类似《植物大战僵尸》的游戏。
代码主要分为以下几个部分:
头文件(head.h):包含了游戏中所需的各种库的引用、宏定义、结构体、枚举类型、类的声明等。
源文件(PvZ.cpp):实现了游戏的各种功能函数和主函数。

三、头文件(head.h)详解

1、库引用和宏定义:

  • #include <iostream>等一系列库的引用为程序提供了输入输出、时间处理、图形绘制、声音播放等功能。

  • 宏定义了各种游戏元素的类型,例如不同的植物和僵尸类型、地图状态等,方便在程序中使用统一的标识符来表示这些元素。

#define GRASS 0
#define GRAVE1 1
//...
#define BUCKETHEADZOMBIE 16

这些宏定义使得在程序中可以使用诸如GRASS表示草地、BUCKETHEADZOMBIE表示铁桶僵尸等,提高了代码的可读性和可维护性。

2、结构体和枚举类型:

  • coordinate结构体定义了坐标,方便在程序中表示游戏元素的位置。
struct coordinate
{int x;int y;
};
  • CURSORFLAG枚举类型定义了鼠标光标的不同状态,用于确定玩家当前可以进行的操作。
enum CURSORFLAG
{Chammer, CpotatoMine,Ciceshroom,Cgravebuster
};

3、类的声明:

  • Bang类表示爆炸效果,包含爆炸的位置和倒计时等成员变量,用于在游戏中显示爆炸效果并控制其持续时间。
class Bang
{
public:int No;int x;int y;int countDown;Bang(int x,int y){No = bangNum;bangNum++;this->x = x;this->y = y;countDown = 20;}
};
  • Sun类表示太阳,包含太阳的位置、帧、编号等成员变量,用于在游戏中生成和管理太阳资源。
class Sun
{
public:int x;int y;int frame;int No;int changeFrameCountDown;int goToCount;int goToCountFrame;int tempX;int tempY;Sun(int x,int y){frame = 0;No=sunNum;sunNum++;this->x = x;this->y = y;this->tempX = x;this->tempY = y;changeFrameCountDown = 5;goToCount = 0;goToCountFrame = 10;}
};
  • Plant类是植物的基类,包含植物的类型、生命值、帧编号等成员变量,为不同类型的植物提供了共同的属性和方法。
class Plant
{
public:int type;int HP;int frameNo;int No;int x;int y;int changeFrameCountDown;Plant(){No = plantNum;plantNum++;changeFrameCountDown = 5;HP = 6;}~Plant(){}
};
  • PotatoMineGraveBusterIceShroom类分别是土豆雷、墓碑吞噬者、寒冰菇的具体类,继承自Plant类并添加了各自特有的成员变量,实现了不同植物的特定功能。
  • Zombie类是僵尸的基类,包含僵尸的生命值、行、位置、状态等成员变量,为不同类型的僵尸提供了共同的属性和方法。
class Zombie
{
public:int HP;int row;int location;int emerge1walk2eat3;int frameNo;int height;int No;int changeFrameCountDown;int isFrozen;int isSlowed;int type;Zombie(){No = zombieNum;zombieNum++;isFrozen = 0;isSlowed = 0;height = 115;frameNo = 19;emerge1walk2eat3 = 1;changeFrameCountDown = 10;}
};
  • NormalZombieConeheadZombieBucketheadZombie类分别是普通僵尸、路障僵尸、铁桶僵尸的具体类,继承自Zombie类并设置了不同的生命值和类型,实现了不同僵尸的特定行为。
  • Lawnmower类表示除草机,包含除草机的位置和状态等成员变量,用于在游戏中处理僵尸与除草机的交互。
class Lawnmower
{
public:int location = -20;int isActivated = 0;int isOut = 0;
};
  • NodeLinkList模板类用于实现链表结构,分别表示链表节点和链表,用于管理游戏中的各种对象,如太阳、植物、僵尸等。
template<class T>
class Node
{
public:T* content;Node* next = NULL;Node(T* t){content = t;}
};template<class T>
class LinkList
{
public:Node<T>* head;  Node<T>* tail;LinkList(){head = NULL;tail = NULL;};LinkList(Node<T> node){ head = node; tail = node; };~LinkList(){ DeleteAllNode();}     void InsertNode(T* t)//... (其他函数的实现)
};

四、源文件(PvZ.cpp)详解

1、函数声明和命名空间:

  • 使用各种编译指令和命名空间声明,为程序提供必要的设置和功能。
  • using namespace std;使得可以直接使用标准库中的名称而无需加上std::前缀,方便了代码的编写。

2、初始化函数(init):

void init()
{for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){mapState[i][j] = GRASS;}}currentSunshine = 0;plants.DeleteAllNode();zombies.DeleteAllNode();suns.DeleteAllNode();bangs.DeleteAllNode();for (int i = 0; i < 5; i++){lawnmowers[i] = new Lawnmower();}normalfrequency = 0.002;coneheadfrequency = 0.0025;bucketheadfrequency = 0.0028;SunsFrequency = 0.05;isNewGame = 1;isHitting = 0;hammerRadius = 0;drawingHint = 0;hintCountDown = 70;snowCountDown = 0;graveNum = 0;Win1Lose2 = 0;
}
  • 这个函数初始化了游戏的各种参数,包括地图状态、阳光数量、各种链表的清空、除草机的状态、生成僵尸和太阳的频率等。它为游戏的开始或重新开始提供了一个干净的状态。

3、 读取存档函数(readArchive)和写入存档函数(writeArchive):

  • readArchive函数从文件中读取游戏存档数据,包括地图状态、各种对象的状态等,并将其加载到游戏中。
void readArchive(char name[])
{init();char path[] = "./archives/", tmppath[200] = { 0 };strcat(strcat(tmppath, path), name);FILE* fp = fopen(tmppath, "rb");::fread(&mapState, sizeof(mapState), 1, fp);for (int i = 0; i < 5; i++){lawnmowers[i] = new Lawnmower();::fread(&lawnmowers[i]->location, sizeof(int), 1, fp);::fread(&lawnmowers[i]->isActivated, sizeof(int), 1, fp);::fread(&lawnmowers[i]->isOut, sizeof(int), 1, fp);}fread(&currentSunshine, sizeof(int), 1, fp);//... (读取其他参数和对象的状态)while (fread(&separator,sizeof(int),1,fp)){Sun* tmpSun = new Sun(0, 0);fread(&tmpSun->x, sizeof(int), 1, fp);fread(&tmpSun->y, sizeof(int), 1, fp);fread(&tmpSun->frame, sizeof(int), 1, fp);fread(&tmpSun->No, sizeof(int), 1, fp);fread(&tmpSun->changeFrameCountDown, sizeof(int), 1, fp);fread(&tmpSun->goToCount, sizeof(int), 1, fp);fread(&tmpSun->goToCountFrame, sizeof(int), 1, fp);fread(&tmpSun->tempX, sizeof(int), 1, fp);fread(&tmpSun->tempY, sizeof(int), 1, fp);suns.InsertNode(tmpSun);}fclose(fp);
}
  • writeArchive函数将游戏当前状态写入文件以保存存档。

4、精确延时函数(HpSleep

void HpSleep(int ms)
{static clock_t oldclock = clock();oldclock += ms * CLOCKS_PER_SEC / 1000;if (clock() > oldclock)oldclock = clock();elsewhile (clock() < oldclock)Sleep(1);
}
  • 这个函数通过计算时间差实现精确的延时功能,可以精确到 1ms。它用于控制游戏的帧率和动画效果的播放速度。

5、透明图像绘制函数(transparentImage)和添加冰效果函数(addIce):

  • transparentImage函数用于将一个图像以透明的方式绘制到另一个图像上指定的位置。
void transparentImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg)
{HDC dstDC = GetImageHDC(dstimg);HDC srcDC = GetImageHDC(srcimg);int w = srcimg->getwidth();int h = srcimg->getheight();BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}
  • addIce函数用于给图像添加冰效果,通过调整图像的颜色值实现。
void addIce(IMAGE* targetImage, IMAGE* srcImage, int addRed = 0, int addGreen = 0, int addBlue = 50)
{int srcImgWidth = srcImage->getwidth(), srcImgHeight = srcImage->getheight();targetImage->Resize(srcImgWidth, srcImgHeight);DWORD* pTargetBuffer = GetImageBuffer(targetImage);DWORD* pSrcBuffer = GetImageBuffer(srcImage);int allPixel = srcImgHeight * srcImgWidth;for (int i = 0; i < allPixel; ++i){UCHAR r = (UCHAR)GetRValue(pSrcBuffer[i]);UCHAR g = (UCHAR)GetGValue(pSrcBuffer[i]);UCHAR b = (UCHAR)GetBValue(pSrcBuffer[i]);r = r + addRed;r = r > 255? 255 : r;g = g + addGreen;g = g > 255? 255 : g;b = b + addBlue;b = b > 255? 255 : b;pTargetBuffer[i] = (DWORD)RGBA(r, g, b, pSrcBuffer[i] >> 24);}
}

6、绘制游戏元素的函数:

  • paintPlantsAndGraves函数绘制植物和墓碑。根据地图状态,在不同的位置绘制不同类型的植物和墓碑,并更新植物的状态。
void paintPlantsAndGraves()
{for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){switch (mapState[i][j]){case GRASS:break;case GRAVE1:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[0]);break;}//... (处理其他地图状态)}}}
}
  • paintZombies函数绘制僵尸。根据僵尸的状态绘制不同的僵尸图像,并处理僵尸的移动、动画和状态变化。
void paintZombies()
{Node<Zombie> *cur = zombies.head, *next = NULL;while (cur!= NULL){Zombie* zombieptr = cur->content;if (zombieptr->emerge1walk2eat3 == 1){//... (绘制正在冒出来的僵尸)}else if (zombieptr->emerge1walk2eat3 == 2){//... (绘制正在行走的僵尸)}else if (zombieptr->emerge1walk2eat3 == 3){//... (绘制正在吃植物的僵尸)}// 判断是否冻住或减速if (zombieptr->isFrozen > 0){//...}if (zombieptr->isSlowed > 0){//...}// 如果僵尸走到最左边且此行有除草机if (zombieptr->location < -50 && lawnmowers[zombieptr->row]->isOut == 0){//...}// 如果僵尸前面有植物//...// 如果僵尸前面有除草机if (lawnmowers[zombieptr->row]->isOut == 0 && zombieptr->location < lawnmowers[zombieptr->row]->location - 30){//...}cur = cur->next;}
}
  • paintSuns函数绘制太阳。更新太阳的帧并处理太阳被收集的情况
void paintSuns()
{Node<Sun> *cur = suns.head, *next;while (cur!= NULL){Sun* sun = cur->content;transparentImage(NULL, sun->x, sun->y, &sunPictures[sun->frame]);sun->changeFrameCountDown--;if (sun->changeFrameCountDown == 0){sun->changeFrameCountDown = 5;sun->frame++;if (sun->frame == 22) sun->frame = 0;if (sun->goToCount == 1){sun->x = sun->tempX / 10 * sun->goToCountFrame;sun->y = sun->tempY / 10 * sun->goToCountFrame;sun->goToCountFrame--;if (sun->goToCountFrame == 0){next = cur->next;suns.DeleteNode(sun->No);cur = next;currentSunshine += 25;continue;}}}cur = cur->next;}
}
  • 这个函数遍历太阳链表,绘制每个太阳的图像。通过更新太阳的帧编号和倒计时,实现太阳的动画效果。当太阳被点击 (goToCount为 1)时,太阳会逐渐移动到特定位置,然后被收集,增加阳光数量并从链表中删除。
  • paintBangs函数绘制爆炸效果。根据爆炸的倒计时绘制爆炸图像,并在倒计时结束时删除爆炸对象。
void paintBangs()
{Node<Bang>* cur = bangs.head,*pre;while (cur!= NULL){if (cur->content->countDown > 0){cur->content->countDown--;transparentImage(NULL, cur->content->x, cur->content->y, &bang);}pre = cur;cur = cur->next; if(pre->content->countDown<=0)bangs.DeleteNode(pre->content->No);}
}
  • 该函数遍历爆炸效果链表,绘制每个爆炸的图像。随着倒计时的减少,不断更新爆炸的状态。当倒计时为 0 时,从链表中删除对应的爆炸对象。
  • paintCursor函数绘制鼠标光标。根据光标的状态绘制不同的图像。
void paintCursor()
{if (cursor == Chammer){// 如果没锤,画正常角度锤子if (!isHitting)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &hammer[0]);else{// 画旋转锤子transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &hammer[hammerRadius]);hammerRadius++;if (hammerRadius == 13){hammerRadius = 0;isHitting = 0;}}}else if (cursor == CpotatoMine)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &potaotoMinePictures[0]);else if (cursor == Ciceshroom)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &iceshroomPictures[0]);elsetransparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &gravebusterPictures[0]);
}
  • 根据鼠标光标的状态(锤子、土豆雷、寒冰菇、墓碑吞噬者),在鼠标位置绘制相应的图像。如果是锤子状态且正在锤击(isHitting为真),则绘制旋转的锤子图像。

7、随机生成游戏元素的函数:

  • generateSunshine函数在一定概率下生成阳光,并将其添加到游戏中。
void generateSunshine(int x, int y)
{// 一定概率产生 3 个阳光double p = rand() / (double)RAND_MAX;if (p < SunsFrequency){Sun* sunshine[3];for (int i = 0; i < 3; i++){sunshine[i] = new Sun(x + 80 + rand() % 100 - 50, y + 60 + rand() % 50 - 25);suns.InsertNode(sunshine[i]);}}
}
  • 这个函数根据给定的概率生成阳光对象,并将它们添加到太阳链表中。阳光的位置在一定范围内随机生成。
  • randomZombies函数随机生成僵尸。根据概率在地图上随机位置生成不同类型的僵尸,并播放相应的音效。
void randomZombies()
{// 随机产生僵尸for (int i = 0; i < 5; i++){for (int j = 3; j < 9; j++){if (1 <= mapState[i][j] && mapState[i][j] <= 8){double p = rand() / (double)RAND_MAX;if (p < normalfrequency){NormalZombie* normalZombie = new NormalZombie();normalZombie->row = i;normalZombie->location = xys[i][j].x - 75;zombies.InsertNode(normalZombie);mciSendString("play./Music/dirt_rise.mp3 from 0", 0, 0, 0);}else if (normalfrequency <= p && p < coneheadfrequency){ConeheadZombie* coneheadZombie = new ConeheadZombie();coneheadZombie->row = i;coneheadZombie->location = xys[i][j].x - 75;zombies.InsertNode(coneheadZombie);mciSendString("play./Music/dirt_rise.mp3 from 0", 0, 0, 0);}else if (coneheadfrequency <= p && p < bucketheadfrequency){BucketheadZombie* bucketheadZombie = new BucketheadZombie();bucketheadZombie->row = i;bucketheadZombie->location = xys[i][j].x - 75;zombies.InsertNode(bucketheadZombie);mciSendString("play./Music/dirt_rise.mp3 from 0", 0, 0, 0);}}}}// 随机呻吟声double p = rand() / (double)RAND_MAX;if (p < groanFrequency){int px = rand() % 6 + 1;switch (px){case 1:mciSendString("play./Music/groan.mp3 from 0", 0, 0, 0);break;case 2:mciSendString("play./Music/groan2.mp3 from 0", 0, 0, 0);break;case 3:mciSendString("play./Music/groan3.mp3 from 0", 0, 0, 0);break;case 4:mciSendString("play./Music/groan4.mp3 from 0", 0, 0, 0);break;case 5:mciSendString("play./Music/groan5.mp3 from 0", 0, 0, 0);break;case 6:mciSendString("play./Music/groan6.mp3 from 0", 0, 0, 0);break;}}
}
  • 这个函数在游戏中随机生成僵尸。首先,根据给定的概率在地图上的特定位置生成普通僵尸、路障僵尸或铁桶僵尸,并播放相应的音效。然后,再次根据概率随机播放僵尸的呻吟声。
  • randomGraves函数随机生成墓碑。确保游戏中有一定数量的墓碑,并随机分布在地图上。
void randomGraves()
{// 随机产生墓碑while (graveNum < 6 || graveNum > 13){graveNum = 0;for (int i = 0; i < 5; i++){int num = rand() % 4;for (int j = 0; j < num; j++){int column = rand() % 6 + 3;if (mapState[i][column] == 0){mapState[i][column] = rand() % 8 + 1;graveNum++;}else j--;}}}
}
  • 该函数用于在游戏开始时随机生成一定数量的墓碑。通过不断调整墓碑的数量,确保游戏中有 6 到 13 个墓碑随机分布在地图上。

8、绘制存档名称函数(paintNames)和绘制提示函数(drawHint):

  • paintNames函数读取存档文件夹中的存档文件,并在游戏界面上绘制存档名称。如果存档过多或没有存档,会显示相应的提示信息。
void paintNames()
{// 画出存档名称getFiles("./archives");RECT rect;setbkmode(TRANSPARENT);settextcolor(RGB(222, 186, 97));if (files.size() > 5){settextstyle(20, 0, "华文隶书");rect = { 268, 135, 538, 335 };drawtext("存档过多,请删除 archives", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);rect = { 268, 175, 538, 375 };drawtext("文件夹下的存档并重启!", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else if (files.size() == 0){settextstyle(40, 0, "华文隶书");rect = { 268, 159, 538, 360 };drawtext("没有存档!", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else{int h = 189;settextstyle(35, 0, "华文隶书");for (int i = 0; i < files.size(); ++i){rect = { 268, h, 538, h + 40 };drawtext(files[i].c_str(), &rect, DT_CENTER);h += 40;}}
}
  • 这个函数首先获取存档文件夹中的存档文件列表。然后,根据存档数量的不同情况,在游戏界面上绘制相应的提示信息或存档名称。如果存档过多,会提示玩家删除一些存档并重启游戏;如果没有存档,则显示 “没有存档!”;如果有存档,则逐个绘制存档名称。
  • drawHint函数根据游戏状态绘制提示信息,如 “此处不能种植物!” 或 “阳光不足!”。
void drawHint()
{if (drawingHint!= 0){settextcolor(WHITE);settextstyle(40, 0, "隶书");if (drawingHint == 1){drawtext("此处不能种植物!", &rect, DT_CENTER);}else if (drawingHint == 2)drawtext("阳光不足!", &rect, DT_CENTER);hintCountDown--;if (hintCountDown == 0){hintCountDown = 70;drawingHint = 0;}}
}
  • 该函数根据游戏中的提示状态(drawingHint)绘制相应的提示信息在游戏界面上。如果提示状态为 1,则绘制 “此处不能种植物!”;如果提示状态为 2,则绘制 “阳光不足!”。提示会持续一段时间(由hintCountDown控制),然后消失。

五、完整代码&素材

head.h

#include <iostream>
#include <ctime>
#include <string>
#include <graphics.h>
#include <conio.h>
#include <Windows.h>
#include <io.h>
#include <vector>
#include <stdio.h>
#include <cmath>
#include <mmsystem.h>
using namespace std;#define GRASS 0
#define GRAVE1 1
#define GRAVE2 2
#define GRAVE3 3
#define GRAVE4 4
#define GRAVE5 5
#define GRAVE6 6
#define GRAVE7 7
#define GRAVE8 8
#define POTATO 9
#define POTATOMINE 10
#define POTATOBOOM 11
#define GRAVEBUSTER_GRAVE1 12
#define GRAVEBUSTER_GRAVE2 13
#define GRAVEBUSTER_GRAVE3 14
#define GRAVEBUSTER_GRAVE4 15
#define GRAVEBUSTER_GRAVE5 16
#define GRAVEBUSTER_GRAVE6 17
#define GRAVEBUSTER_GRAVE7 18
#define GRAVEBUSTER_GRAVE8 19
#define ICESHROOM 20
#define NORMALZOMBIE 21
#define CONEHEADZOMBIE 22
#define BUCKETHEADZOMBIE 16//非游戏参数
int zombieNum=0;
int plantNum=0;
int sunNum=0;
int bangNum=0;
double groanFrequency = 0.0005;
IMAGE potatoBoom;
IMAGE potato;
IMAGE grave[8];
IMAGE hammer[13];
IMAGE tmpImg;
IMAGE tmpImg2;
IMAGE potaotoMinePictures[8];
IMAGE iceshroomPictures[11];
IMAGE gravebusterPictures[28];
IMAGE sunPictures[22];
IMAGE normalZombieWalkPictures[47];
IMAGE normalZombieEmergePictures[20];
IMAGE normalZombieEatPictures[10];
IMAGE coneheadZombieWalkPictures[47];
IMAGE coneheadZombieEmergePictures[20];
IMAGE coneheadZombieEatPictures[10];
IMAGE bucketheadZombieWalkPictures[47];
IMAGE bucketheadZombieEmergePictures[20];
IMAGE bucketheadZombieEatPictures[10];
IMAGE plantsBar;
IMAGE menu;
IMAGE background;
IMAGE selectID;
IMAGE iceTrap;
IMAGE snow;
IMAGE lawnmower;
IMAGE loseGame;
IMAGE winGame;
IMAGE bang;
ExMessage mousemsg;struct coordinate
{int x;int y;
};enum CURSORFLAG
{Chammer, CpotatoMine,Ciceshroom,Cgravebuster
};coordinate xys[32][32];
CURSORFLAG cursor;
RECT rect = { 0, 500, 820, 600 };
char sunshineNum[10];
char username[200];
vector<string> files;class Bang
{
public:int No;int x;int y;int countDown;Bang(int x,int y){No = bangNum;bangNum++;this->x = x;this->y = y;countDown = 20;}
};class Sun
{
public:int x;int y;int frame;int No;int changeFrameCountDown;int goToCount;int goToCountFrame;int tempX;int tempY;Sun(int x,int y){frame = 0;No=sunNum;sunNum++;this->x = x;this->y = y;this->tempX = x;this->tempY = y;changeFrameCountDown = 5;goToCount = 0;goToCountFrame = 10;}
};class Plant
{
public:int type;int HP;int frameNo;int No;int x;int y;int changeFrameCountDown;Plant(){No = plantNum;plantNum++;changeFrameCountDown = 5;HP = 6;}~Plant(){}
};// 土豆雷
class PotatoMine : public Plant
{
public:int underCountDown = 400;int boomCountDown = 50;PotatoMine(){frameNo = 0;type = POTATOMINE;}
};// 墓碑吞噬者
class GraveBuster : public Plant
{
public:GraveBuster(){frameNo = 1;type = GRAVEBUSTER_GRAVE1;}
};// 寒冰菇
class IceShroom : public Plant
{
public:int frozenCountDown = 200;int slowingCountDown = 1000;IceShroom(){frameNo = 0;type = ICESHROOM;}
};class Zombie
{
public:int HP;int row;int location;int emerge1walk2eat3;int frameNo;int height;int No;int changeFrameCountDown;int isFrozen;int isSlowed;int type;Zombie(){No = zombieNum;zombieNum++;isFrozen = 0;isSlowed = 0;height = 115;			// 僵尸图像高度frameNo = 19;			// 表示播放到第几帧emerge1walk2eat3 = 1;	// 正在冒出来用 1 表示,正在行走用 2 表示,正在吃植物用 3 表示changeFrameCountDown = 10;}
};
class NormalZombie : public Zombie
{
public:NormalZombie(){HP = 1;type = NORMALZOMBIE;}
};class ConeheadZombie : public Zombie
{
public:ConeheadZombie(){HP = 2;type = CONEHEADZOMBIE;}
};class BucketheadZombie : public Zombie
{
public:BucketheadZombie(){HP = 3;type = BUCKETHEADZOMBIE;}
};class Lawnmower
{
public:int location = -20;int isActivated = 0;int isOut = 0;
};template<class T>
class Node
{
public:T* content;Node* next = NULL;Node(T* t){content = t;}
};template<class T>
class LinkList
{
public:Node<T>* head;  Node<T>* tail;LinkList(){head = NULL;tail = NULL;};LinkList(Node<T> node){ head = node; tail = node; };~LinkList(){ DeleteAllNode();}     void InsertNode(T* t){Node<T>* node=new Node<T>(t);if (head == NULL){head = node;tail = node;}else{tail->next = node;tail = node;}};void DeleteNode(int No){Node<T>* cur = head,*pre=NULL;while (cur != NULL && cur->content->No != No){pre = cur;cur = cur->next;}if (pre == NULL){head = cur->next;}else if (cur == NULL){cout << "没有找到符合条件的结点!" << endl;return;}else{pre->next = cur->next;}if (cur == tail){tail = pre;}delete cur;};void DeleteAllNode(){Node<T>* cur = head,*pre=NULL;while (tail != NULL){pre = cur;cur = cur->next;DeleteNode(pre->content->No);}};
};

PvZ.cpp

#include "head.h"
#pragma warning (disable:4996)
#pragma comment( lib, "MSIMG32.LIB")
#pragma comment( lib, "winmm.lib")// 游戏参数
int mapState[32][32];		// 地图状态。0:空,1:墓碑,2:地雷(没出土),3:地雷(已出土),4:寒冰菇
int currentSunshine;
LinkList<Sun> suns;
LinkList<Plant> plants;
LinkList<Zombie> zombies;
LinkList<Bang> bangs;
Lawnmower* lawnmowers[5];
double normalfrequency;
double coneheadfrequency;
double bucketheadfrequency;
double SunsFrequency;
int isNewGame;
int isHitting;
int hammerRadius;
int drawingHint;
int hintCountDown;
int snowCountDown;
int graveNum;
int Win1Lose2;void init()
{for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){mapState[i][j] = GRASS;}}currentSunshine = 0;plants.DeleteAllNode();zombies.DeleteAllNode();suns.DeleteAllNode();bangs.DeleteAllNode();for (int i = 0; i < 5; i++){lawnmowers[i] = new Lawnmower();}normalfrequency = 0.002;coneheadfrequency = 0.0025;bucketheadfrequency = 0.0028;SunsFrequency = 0.05;isNewGame = 1;isHitting = 0;hammerRadius = 0;drawingHint = 0;hintCountDown = 70;snowCountDown = 0;graveNum = 0;Win1Lose2 = 0;
}void getFiles(string path)
{files.clear();//文件句柄  intptr_t hFile = 0;//文件信息  struct _finddata_t fileinfo;string p;if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1){do{files.push_back(fileinfo.name);} while (_findnext(hFile, &fileinfo) == 0);_findclose(hFile);}files.erase(files.begin());files.erase(files.begin());
}void readArchive(char name[])
{init();char path[] = "./archives/", tmppath[200] = { 0 };strcat(strcat(tmppath, path), name);FILE* fp = fopen(tmppath, "rb");::fread(&mapState, sizeof(mapState), 1, fp);for (int i = 0; i < 5; i++){lawnmowers[i] = new Lawnmower();::fread(&lawnmowers[i]->location, sizeof(int), 1, fp);::fread(&lawnmowers[i]->isActivated, sizeof(int), 1, fp);::fread(&lawnmowers[i]->isOut, sizeof(int), 1, fp);}fread(&currentSunshine,		sizeof(int),	1, fp);fread(&normalfrequency,		sizeof(double),	1, fp);fread(&coneheadfrequency,	sizeof(double),	1, fp);fread(&bucketheadfrequency,	sizeof(double),	1, fp);fread(&SunsFrequency,		sizeof(double),	1, fp);fread(&isNewGame,			sizeof(int),	1, fp);fread(&isHitting,			sizeof(int),	1, fp);fread(&hammerRadius,		sizeof(int),	1, fp);fread(&drawingHint,			sizeof(int),	1, fp);fread(&hintCountDown,		sizeof(int),	1, fp);fread(&snowCountDown,		sizeof(int),	1, fp);fread(&graveNum,			sizeof(int),	1, fp);fread(&Win1Lose2,			sizeof(int),	1, fp);int separator;while (1){fread(&separator, sizeof(int), 1, fp);if (separator!=1234567){Zombie* tmpZombie = new Zombie();fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(&tmpZombie->HP,					sizeof(int), 1, fp);fread(&tmpZombie->row,					sizeof(int), 1, fp);fread(&tmpZombie->location,				sizeof(int), 1, fp);fread(&tmpZombie->emerge1walk2eat3,		sizeof(int), 1, fp);fread(&tmpZombie->frameNo,				sizeof(int), 1, fp);fread(&tmpZombie->height,				sizeof(int), 1, fp);fread(&tmpZombie->No,					sizeof(int), 1, fp);fread(&tmpZombie->changeFrameCountDown,	sizeof(int), 1, fp);fread(&tmpZombie->isFrozen,				sizeof(int), 1, fp);fread(&tmpZombie->isSlowed,				sizeof(int), 1, fp);fread(&tmpZombie->type,					sizeof(int), 1, fp);zombies.InsertNode(tmpZombie);}else break;}int tmpPlantType;while (1){fread(&separator, sizeof(int), 1, fp);if (separator!=7654321){fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(&tmpPlantType, sizeof(int), 1, fp);switch (tmpPlantType){case POTATOMINE:{PotatoMine* tmpPotatoMine = new PotatoMine();tmpPotatoMine->type = tmpPlantType;fread(&tmpPotatoMine->frameNo, sizeof(int), 1, fp);fread(&tmpPotatoMine->No, sizeof(int), 1, fp);fread(&tmpPotatoMine->x, sizeof(int), 1, fp);fread(&tmpPotatoMine->y, sizeof(int), 1, fp);fread(&tmpPotatoMine->changeFrameCountDown, sizeof(int), 1, fp);fread(&tmpPotatoMine->underCountDown, sizeof(int), 1, fp);fread(&tmpPotatoMine->boomCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpPotatoMine);break;}case GRAVEBUSTER_GRAVE1:{GraveBuster* tmpGraveBuster = new GraveBuster();tmpGraveBuster->type = tmpPlantType;fread(&tmpGraveBuster->frameNo, sizeof(int), 1, fp);fread(&tmpGraveBuster->No, sizeof(int), 1, fp);fread(&tmpGraveBuster->x, sizeof(int), 1, fp);fread(&tmpGraveBuster->y, sizeof(int), 1, fp);fread(&tmpGraveBuster->changeFrameCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpGraveBuster);break;}case ICESHROOM:{IceShroom* tmpIceShroom = new IceShroom();tmpIceShroom->type = tmpPlantType;fread(&tmpIceShroom->frameNo, sizeof(int), 1, fp);fread(&tmpIceShroom->No, sizeof(int), 1, fp);fread(&tmpIceShroom->x, sizeof(int), 1, fp);fread(&tmpIceShroom->y, sizeof(int), 1, fp);fread(&tmpIceShroom->changeFrameCountDown, sizeof(int), 1, fp);fread(&tmpIceShroom->frozenCountDown, sizeof(int), 1, fp);fread(&tmpIceShroom->slowingCountDown, sizeof(int), 1, fp);plants.InsertNode(tmpIceShroom);break;}}}else break;}while (1){fread(&separator, sizeof(int), 1, fp);if (separator != 357421){Bang* tmpBang = new Bang(0,0);fseek(fp, -(int)sizeof(int), SEEK_CUR);fread(&tmpBang->No, sizeof(int), 1, fp);fread(&tmpBang->x, sizeof(int), 1, fp);fread(&tmpBang->y, sizeof(int), 1, fp);fread(&tmpBang->countDown, sizeof(int), 1, fp);bangs.InsertNode(tmpBang);}elsebreak;}while (fread(&separator,sizeof(int),1,fp)){Sun* tmpSun = new Sun(0, 0);fread(&tmpSun->x, sizeof(int), 1, fp);fread(&tmpSun->y, sizeof(int), 1, fp);fread(&tmpSun->frame, sizeof(int), 1, fp);fread(&tmpSun->No, sizeof(int), 1, fp);fread(&tmpSun->changeFrameCountDown, sizeof(int), 1, fp);fread(&tmpSun->goToCount, sizeof(int), 1, fp);fread(&tmpSun->goToCountFrame, sizeof(int), 1, fp);fread(&tmpSun->tempX, sizeof(int), 1, fp);fread(&tmpSun->tempY, sizeof(int), 1, fp);suns.InsertNode(tmpSun);}fclose(fp);
}void writeArchive(char name[])
{char path[] = "./archives/", tmppath[200] = { 0 };strcat(strcat(tmppath, path), name);FILE* fp = fopen(tmppath, "wb");::fwrite(mapState, sizeof(mapState), 1, fp);for (int i = 0; i < 5; i++){::fwrite(&lawnmowers[i]->location, sizeof(int), 1, fp);::fwrite(&lawnmowers[i]->isActivated, sizeof(int), 1, fp);::fwrite(&lawnmowers[i]->isOut, sizeof(int), 1, fp);}::fwrite(&currentSunshine, sizeof(int), 1, fp);::fwrite(&normalfrequency, sizeof(double), 1, fp);::fwrite(&coneheadfrequency, sizeof(double), 1, fp);::fwrite(&bucketheadfrequency, sizeof(double), 1, fp);::fwrite(&SunsFrequency, sizeof(double), 1, fp);::fwrite(&isNewGame, sizeof(int), 1, fp);::fwrite(&isHitting, sizeof(int), 1, fp);::fwrite(&hammerRadius, sizeof(int), 1, fp);::fwrite(&drawingHint, sizeof(int), 1, fp);::fwrite(&hintCountDown, sizeof(int), 1, fp);::fwrite(&snowCountDown, sizeof(int), 1, fp);::fwrite(&graveNum, sizeof(int), 1, fp);::fwrite(&Win1Lose2, sizeof(int), 1, fp);Node<Zombie>* curZombie = zombies.head;while (curZombie != NULL){Zombie* zombie = curZombie->content;::fwrite(&zombie->HP, sizeof(int), 1, fp);::fwrite(&zombie->row, sizeof(int), 1, fp);::fwrite(&zombie->location, sizeof(int), 1, fp);::fwrite(&zombie->emerge1walk2eat3, sizeof(int), 1, fp);::fwrite(&zombie->frameNo, sizeof(int), 1, fp);::fwrite(&zombie->height, sizeof(int), 1, fp);::fwrite(&zombie->No, sizeof(int), 1, fp);::fwrite(&zombie->changeFrameCountDown, sizeof(int), 1, fp);::fwrite(&zombie->isFrozen, sizeof(int), 1, fp);::fwrite(&zombie->isSlowed, sizeof(int), 1, fp);::fwrite(&zombie->type, sizeof(int), 1, fp);curZombie = curZombie->next;}int separator1 = 1234567;::fwrite(&separator1, sizeof(int), 1, fp);Node<Plant>* curPlant = plants.head;while (curPlant != NULL){switch (curPlant->content->type){case POTATOMINE:{PotatoMine* potatoMine = static_cast<PotatoMine*>(curPlant->content);::fwrite(&potatoMine->type, sizeof(int), 1, fp);::fwrite(&potatoMine->frameNo, sizeof(int), 1, fp);::fwrite(&potatoMine->No, sizeof(int), 1, fp);::fwrite(&potatoMine->x, sizeof(int), 1, fp);::fwrite(&potatoMine->y, sizeof(int), 1, fp);::fwrite(&potatoMine->changeFrameCountDown, sizeof(int), 1, fp);::fwrite(&potatoMine->underCountDown, sizeof(int), 1, fp);::fwrite(&potatoMine->boomCountDown, sizeof(int), 1, fp);break;}case ICESHROOM:{IceShroom* iceShroom = static_cast<IceShroom*>(curPlant->content);::fwrite(&iceShroom->type, sizeof(int), 1, fp);::fwrite(&iceShroom->frameNo, sizeof(int), 1, fp);::fwrite(&iceShroom->No, sizeof(int), 1, fp);::fwrite(&iceShroom->x, sizeof(int), 1, fp);::fwrite(&iceShroom->y, sizeof(int), 1, fp);::fwrite(&iceShroom->changeFrameCountDown, sizeof(int), 1, fp);::fwrite(&iceShroom->frozenCountDown, sizeof(int), 1, fp);::fwrite(&iceShroom->slowingCountDown, sizeof(int), 1, fp);break;}case GRAVEBUSTER_GRAVE1:{GraveBuster* graveBuster = static_cast<GraveBuster*>(curPlant->content);::fwrite(&graveBuster->type, sizeof(int), 1, fp);::fwrite(&graveBuster->frameNo, sizeof(int), 1, fp);::fwrite(&graveBuster->No, sizeof(int), 1, fp);::fwrite(&graveBuster->x, sizeof(int), 1, fp);::fwrite(&graveBuster->y, sizeof(int), 1, fp);::fwrite(&graveBuster->changeFrameCountDown, sizeof(int), 1, fp);break;}}curPlant = curPlant->next;}int separator2 = 7654321;::fwrite(&separator2, sizeof(int), 1, fp);Node<Bang>* curBang = bangs.head;while (curBang!= NULL){Bang* bang = curBang->content;::fwrite(&bang->No, sizeof(int), 1, fp);::fwrite(&bang->x, sizeof(int), 1, fp);::fwrite(&bang->y, sizeof(int), 1, fp);::fwrite(&bang->countDown, sizeof(int), 1, fp);curBang = curBang->next;}int separator3 = 357421;::fwrite(&separator3, sizeof(int), 1, fp);Node<Sun>* curSun = suns.head;while (curSun != NULL){Sun* sun = curSun->content;::fwrite(&sun->x, sizeof(int), 1, fp);::fwrite(&sun->y, sizeof(int), 1, fp);::fwrite(&sun->frame, sizeof(int), 1, fp);::fwrite(&sun->No, sizeof(int), 1, fp);::fwrite(&sun->changeFrameCountDown, sizeof(int), 1, fp);::fwrite(&sun->goToCount, sizeof(int), 1, fp);::fwrite(&sun->goToCountFrame, sizeof(int), 1, fp);::fwrite(&sun->tempX, sizeof(int), 1, fp);::fwrite(&sun->tempY, sizeof(int), 1, fp);curSun = curSun->next;}fclose(fp);
}// 精确延时函数(可以精确到 1ms,精度 ±1ms)
// by yangw80<yw80@qq.com>, 2011-5-4
void HpSleep(int ms)
{static clock_t oldclock = clock();		// 静态变量,记录上一次 tickoldclock += ms * CLOCKS_PER_SEC / 1000;	// 更新 tickif (clock() > oldclock)					// 如果已经超时,无需延时oldclock = clock();elsewhile (clock() < oldclock)			// 延时Sleep(1);						// 释放 CPU 控制权,降低 CPU 占用率
//			Sleep(0);						// 更高精度、更高 CPU 占用率
}void transparentImage(IMAGE* dstimg, int x, int y, IMAGE* srcimg)
{HDC dstDC = GetImageHDC(dstimg);HDC srcDC = GetImageHDC(srcimg);int w = srcimg->getwidth();int h = srcimg->getheight();BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };AlphaBlend(dstDC, x, y, w, h, srcDC, 0, 0, w, h, bf);
}void paintPlantsAndGraves()
{// 画植物和墓碑for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){switch (mapState[i][j]){case GRASS:break;case GRAVE1:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[0]);break;}case GRAVE2:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[1]);break;}case GRAVE3:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[2]);break;}case GRAVE4:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[3]);break;}case GRAVE5:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[4]);break;}case GRAVE6:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[5]);break;}case GRAVE7:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[6]);break;}case GRAVE8:{transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[7]);break;}case POTATO:{transparentImage(NULL, xys[i][j].x, xys[i][j].y + 37, &potato);Node<Plant>* cur = plants.head;while (cur != NULL){if (cur->content->x == i && cur->content->y == j){break;}else cur = cur->next;}if (cur != NULL){PotatoMine* potato = static_cast<PotatoMine*>(cur->content);potato->underCountDown--;if (potato->underCountDown == 0){mapState[i][j] = POTATOMINE;mciSendString("play ./Music/dirt_rise.mp3 from 0 ", 0, 0, 0);}}break;}case POTATOMINE:{Node<Plant>* cur = plants.head;while (cur != NULL){if (cur->content->x == i && cur->content->y == j)break;else cur = cur->next;}                if (cur != NULL){transparentImage(NULL, xys[i][j].x, xys[i][j].y + 40, &potaotoMinePictures[cur->content->frameNo]);cur->content->changeFrameCountDown--;if (cur->content->changeFrameCountDown == 0){cur->content->changeFrameCountDown = 20;cur->content->frameNo++;if (cur->content->frameNo == 7){cur->content->frameNo = 0;}}}                   break;}case POTATOBOOM:{transparentImage(NULL, xys[i][j].x - 25, xys[i][j].y + 20, &potatoBoom);Node<Plant>* cur = plants.head;while (cur != NULL){if (cur->content->x == i && cur->content->y == j)break;else cur = cur->next;}if (cur != NULL){PotatoMine* potato = static_cast<PotatoMine*>(cur->content);potato->boomCountDown--;if (potato->boomCountDown == 0){plants.DeleteNode(potato->No);mapState[i][j] = GRASS;}}            break;}case GRAVEBUSTER_GRAVE1:transparentImage(NULL, xys[i][j].x-5, xys[i][j].y, &grave[0]);goto label;case GRAVEBUSTER_GRAVE2:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[1]);goto label;case GRAVEBUSTER_GRAVE3:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[2]);goto label;case GRAVEBUSTER_GRAVE4:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[3]);goto label;case GRAVEBUSTER_GRAVE5:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[4]);goto label;case GRAVEBUSTER_GRAVE6:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[5]);goto label;case GRAVEBUSTER_GRAVE7:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[6]);goto label;case GRAVEBUSTER_GRAVE8:transparentImage(NULL, xys[i][j].x - 5, xys[i][j].y, &grave[7]);goto label;{label:Node<Plant>* cur = plants.head;while (cur != NULL){if (cur->content->x == i && cur->content->y == j)break;else cur = cur->next;}if (cur != NULL){transparentImage(NULL, xys[i][j].x - 10, xys[i][j].y - 10, &gravebusterPictures[cur->content->frameNo]);cur->content->changeFrameCountDown--;if (cur->content->changeFrameCountDown == 0){cur->content->changeFrameCountDown = 10;cur->content->frameNo++;if (cur->content->frameNo > 27){plants.DeleteNode(cur->content->No);mapState[i][j] = GRASS;graveNum--;if (graveNum == 5){SunsFrequency = 0.2;normalfrequency = 0.003;coneheadfrequency = 0.0035;bucketheadfrequency = 0.0038;}else if (graveNum == 3){SunsFrequency = 0.4;normalfrequency=0.006;coneheadfrequency=0.0065;bucketheadfrequency=0.0068;}}}}        break;}case ICESHROOM:{Node<Plant>* cur = plants.head;while (cur != NULL){if (cur->content->x == i && cur->content->y == j)break;else cur = cur->next;}if (cur != NULL){transparentImage(NULL, xys[i][j].x, xys[i][j].y + 15, &iceshroomPictures[cur->content->frameNo]);cur->content->changeFrameCountDown--;if (cur->content->changeFrameCountDown == 0){cur->content->changeFrameCountDown = 8;cur->content->frameNo++;if (cur->content->frameNo > 10){plants.DeleteNode(cur->content->No);mciSendString("play ./Music/shoop.mp3 from 0 ", 0, 0, 0);mapState[i][j] = 0;snowCountDown = 20;Node<Zombie>* cur = zombies.head;while (cur != NULL){cur->content->isFrozen = 200;cur = cur->next;}}}}              break;}}}}
}void addIce(IMAGE* targetImage, IMAGE* srcImage, int addRed = 0, int addGreen = 0, int addBlue = 50)
{int srcImgWidth = srcImage->getwidth(), srcImgHeight = srcImage->getheight();targetImage->Resize(srcImgWidth, srcImgHeight);DWORD* pTargetBuffer = GetImageBuffer(targetImage);DWORD* pSrcBuffer = GetImageBuffer(srcImage);int allPixel = srcImgHeight * srcImgWidth;#define RGBA(r, g, b, a) ((b) + (g << 8) + (r << 16) + (a << 24))for (int i = 0; i < allPixel; ++i){UCHAR r = (UCHAR)GetRValue(pSrcBuffer[i]);UCHAR g = (UCHAR)GetGValue(pSrcBuffer[i]);UCHAR b = (UCHAR)GetBValue(pSrcBuffer[i]);r = r + addRed;r = r > 255 ? 255 : r;g = g + addGreen;g = g > 255 ? 255 : g;b = b + addBlue;b = b > 255 ? 255 : b;pTargetBuffer[i] = (DWORD)RGBA(r, g, b, pSrcBuffer[i] >> 24);}
}void generateSunshine(int x, int y)
{// 一定概率产生3个阳光double p = rand() / (double)RAND_MAX;if (p < SunsFrequency){Sun* sunshine[3];for (int i = 0; i < 3; i++){sunshine[i] = new Sun(x + 80 + rand() % 100 - 50, y + 60 + rand() % 50 - 25);suns.InsertNode(sunshine[i]);}}
}void paintZombies()
{// 画僵尸Node<Zombie> *cur = zombies.head, *next = NULL;while (cur != NULL){Zombie* zombieptr = cur->content;if (zombieptr->location < -150){cur = cur->next;zombies.DeleteNode(zombieptr->No);continue;}if (zombieptr->emerge1walk2eat3 == 1){if (zombieptr->type == NORMALZOMBIE)tmpImg=normalZombieEmergePictures[zombieptr->frameNo];else if (zombieptr->type == CONEHEADZOMBIE)tmpImg = coneheadZombieEmergePictures[zombieptr->frameNo];elsetmpImg = bucketheadZombieEmergePictures[zombieptr->frameNo];transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg);zombieptr->frameNo--;if (zombieptr->frameNo == 0){zombieptr->emerge1walk2eat3 = 2;}}else if (zombieptr->emerge1walk2eat3 == 2){if (zombieptr->type == NORMALZOMBIE)tmpImg = normalZombieWalkPictures[zombieptr->frameNo];else if (zombieptr->type == CONEHEADZOMBIE)tmpImg = coneheadZombieWalkPictures[zombieptr->frameNo];elsetmpImg = bucketheadZombieWalkPictures[zombieptr->frameNo];if (zombieptr->isFrozen){addIce(&tmpImg2, &tmpImg);transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg2);}else if (zombieptr->isSlowed){addIce(&tmpImg2, &tmpImg);transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg2);zombieptr->changeFrameCountDown -= 1;if (zombieptr->changeFrameCountDown <= 0){zombieptr->changeFrameCountDown = 6;zombieptr->location -= 1; zombieptr->frameNo++;if (zombieptr->frameNo > 46){zombieptr->frameNo = 0;}}}else{transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg);zombieptr->changeFrameCountDown -= 2;if (zombieptr->changeFrameCountDown <= 0){zombieptr->changeFrameCountDown = 6;zombieptr->location -= 2;zombieptr->frameNo++;if (zombieptr->frameNo > 46){zombieptr->frameNo = 0;}}}}else if (zombieptr->emerge1walk2eat3 == 3){/*if (zombieptr->type == NORMALZOMBIE)tmpImg = normalZombieEatPictures[zombieptr->frameNo];else if (zombieptr->type == CONEHEADZOMBIE)tmpImg = coneheadZombieEatPictures[zombieptr->frameNo];else tmpImg = bucketheadZombieEatPictures[zombieptr->frameNo];if (zombieptr->isFrozen) {addIce(&tmpImg2, &tmpImg);transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg2);}else if (zombieptr->isSlowed) {addIce(&tmpImg2, &tmpImg);transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg2);zombieptr->changeFrameCountDown -= 1;if (zombieptr->changeFrameCountDown <= 0) {zombieptr->changeFrameCountDown = 6;zombieptr->location -= 1;zombieptr->frameNo++;if (zombieptr->frameNo > 46) {zombieptr->frameNo = 0;}}}else {transparentImage(NULL, zombieptr->location, xys[zombieptr->row][0].y - 40, &tmpImg);zombieptr->changeFrameCountDown -= 2;if (zombieptr->changeFrameCountDown <= 0) {zombieptr->changeFrameCountDown = 25;zombieptr->frameNo++;}}*/}// 判断是否冻住if (zombieptr->isFrozen > 0){zombieptr->isFrozen--;if (zombieptr->isFrozen == 0)	zombieptr->isSlowed = 400;transparentImage(NULL, zombieptr->location+100, xys[zombieptr->row][0].y+70, &iceTrap);           }// 判断是否减速if (zombieptr->isSlowed > 0){zombieptr->isSlowed--;}// 如果僵尸走到最左边且此行有除草机if (zombieptr->location < -50 && lawnmowers[zombieptr->row]->isOut == 0){lawnmowers[zombieptr->row]->isActivated = 1;mciSendString("play lawnmower from 0", 0, 0, 0);} 如果僵尸前面有植物//Node<Plant>* curPlant = plants.head,*pre;//while (curPlant != NULL)//{//	Plant* plant = curPlant->content;//	if (zombieptr->row == plant->x//		&& zombieptr->location < xys[plant->x][plant->y].x- 25//		&& zombieptr->location > xys[plant->x][plant->y-1].x-25)//	{//		if (zombieptr->emerge1walk2eat3 == 2)//		{//			zombieptr->emerge1walk2eat3 = 3;//			zombieptr->frameNo = 0;//			mciSendString("play ./Music/chomp.mp3 from 0", 0, 0, 0);//		}//		if (zombieptr->emerge1walk2eat3 == 3 && zombieptr->frameNo > 9)//		{//			zombieptr->frameNo = 0;//			mciSendString("play ./Music/chomp.mp3 from 0", 0, 0, 0);//			plant->HP--;//			if (plant->HP == 0)//			{//				pre = curPlant;//				curPlant = curPlant->next;//				plants.DeleteNode(pre->content->No);//				zombieptr->emerge1walk2eat3 = 2;//				continue;//			}//		}//	}//	curPlant = curPlant->next;//}// 如果僵尸前面有除草机if (lawnmowers[zombieptr->row]->isOut == 0 && zombieptr->location < lawnmowers[zombieptr->row]->location - 30){next = cur->next;zombies.DeleteNode(zombieptr->No);generateSunshine(zombieptr->location, xys[zombieptr->row][0].y);cur = next;continue;}      cur = cur->next;}
}void paintSuns()
{Node<Sun> *cur = suns.head, *next;while (cur != NULL){Sun* sun = cur->content;transparentImage(NULL, sun->x, sun->y, &sunPictures[sun->frame]);sun->changeFrameCountDown--;if (sun->changeFrameCountDown == 0){sun->changeFrameCountDown = 5;sun->frame++;if (sun->frame == 22)sun->frame = 0;if (sun->goToCount ==1 ){sun->x = sun->tempX / 10 * sun->goToCountFrame;sun->y = sun->tempY / 10 * sun->goToCountFrame;sun->goToCountFrame--;if (sun->goToCountFrame == 0){next = cur->next;suns.DeleteNode(sun->No);cur = next;currentSunshine += 25;continue;}}}cur = cur->next;}
}void paintBangs()
{Node<Bang>* cur = bangs.head,*pre;while (cur != NULL){if (cur->content->countDown > 0){cur->content->countDown--;transparentImage(NULL, cur->content->x, cur->content->y, &bang);}pre = cur;cur = cur->next; if(pre->content->countDown<=0)bangs.DeleteNode(pre->content->No);}
}void paintCursor()
{if (cursor == Chammer){// 如果没锤,画正常角度锤子if (!isHitting)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &hammer[0]);else{// 画旋转锤子transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &hammer[hammerRadius]);hammerRadius++;if (hammerRadius == 13){hammerRadius = 0;isHitting = 0;}}}else if (cursor == CpotatoMine)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &potaotoMinePictures[0]);else if (cursor == Ciceshroom)transparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &iceshroomPictures[0]);elsetransparentImage(NULL, mousemsg.x - 45, mousemsg.y - 45, &gravebusterPictures[0]);
}void randomZombies()
{// 随机产生僵尸for (int i = 0; i < 5; i++){for (int j = 3; j < 9; j++){if (1 <= mapState[i][j] && mapState[i][j] <= 8){double p = rand() / (double)RAND_MAX;if (p < normalfrequency){NormalZombie* normalZombie = new NormalZombie();normalZombie->row = i;normalZombie->location = xys[i][j].x-75;zombies.InsertNode(normalZombie);mciSendString("play ./Music/dirt_rise.mp3 from 0", 0, 0, 0);}else if (normalfrequency <= p && p < coneheadfrequency){ConeheadZombie* coneheadZombie = new ConeheadZombie();coneheadZombie->row = i;coneheadZombie->location = xys[i][j].x-75;zombies.InsertNode(coneheadZombie);mciSendString("play ./Music/dirt_rise.mp3 from 0", 0, 0, 0);}else if (coneheadfrequency <= p && p < bucketheadfrequency){BucketheadZombie* bucketheadZombie = new BucketheadZombie();bucketheadZombie->row = i;bucketheadZombie->location = xys[i][j].x-75;zombies.InsertNode(bucketheadZombie);mciSendString("play ./Music/dirt_rise.mp3 from 0", 0, 0, 0);}}}}// 随机呻吟声double p = rand() / (double)RAND_MAX;if (p < groanFrequency){int px = rand() % 6 + 1;switch (px){case 1:mciSendString("play ./Music/groan.mp3 from 0", 0, 0, 0);break;case 2:mciSendString("play ./Music/groan2.mp3 from 0", 0, 0, 0);break;case 3:mciSendString("play ./Music/groan3.mp3 from 0", 0, 0, 0);break;case 4:mciSendString("play ./Music/groan4.mp3 from 0", 0, 0, 0);break;case 5:mciSendString("play ./Music/groan5.mp3 from 0", 0, 0, 0);break;case 6:mciSendString("play ./Music/groan6.mp3 from 0", 0, 0, 0);break;}}
}void paintNames()
{// 画出存档名称getFiles("./archives");RECT rect;setbkmode(TRANSPARENT);settextcolor(RGB(222, 186, 97));if (files.size() > 5){settextstyle(20, 0, "华文隶书");rect = { 268, 135, 538, 335 };drawtext("存档过多,请删除archives", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);rect = { 268, 175, 538, 375 };drawtext("文件夹下的存档并重启!", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else if (files.size() == 0){settextstyle(40, 0, "华文隶书");rect = { 268, 159, 538, 360 };drawtext("没有存档!", &rect, DT_CENTER | DT_VCENTER | DT_SINGLELINE);}else{int h = 189;settextstyle(35, 0, "华文隶书");for (int i = 0; i < files.size(); ++i){rect = { 268, h, 538, h + 40 };drawtext(files[i].c_str(), &rect, DT_CENTER);h += 40;}}   
}void drawHint()
{if (drawingHint !=0){settextcolor(WHITE);settextstyle(40, 0, "隶书");if (drawingHint == 1){drawtext("此处不能种植物!", &rect, DT_CENTER);}else if(drawingHint == 2)drawtext("阳光不足!", &rect, DT_CENTER);hintCountDown--;if (hintCountDown == 0){hintCountDown = 70;drawingHint = 0;}}
}void randomGraves()
{// 随机产生墓碑while (graveNum < 6 || graveNum>13){graveNum = 0;for (int i = 0; i < 5; i++){int num = rand() % 4;for (int j = 0; j < num; j++){int column = rand() % 6 + 3;if (mapState[i][column] == 0){mapState[i][column] = rand() % 8 + 1;graveNum++;}else j--;}}}
}void beginGame()
{// 如果是新游戏if (isNewGame){// 随机产生墓碑randomGraves();isNewGame = 0;cursor = Chammer;}mciSendString("open ./Music/Loonboon.mp3 alias BGM2", 0, 0, 0);mciSendString("play BGM2 repeat", 0, 0, 0);mciSendString("play ./Music/theZombiesareComing.mp3 from 0", 0, 0, 0);while (1){// 绘图cleardevice();// 画背景、植物条、菜单、阳光数putimage(0, 0, &background);putimage(0, 0, &plantsBar);transparentImage(NULL, 685, 0, &menu);RECT r = { 8, 63, 68, 85 };		// 12, 62, 68, 84settextstyle(20, 0, "微软雅黑", 0, 0, FW_BOLD, false, false, false);settextcolor(BLACK);drawtext(itoa(currentSunshine,sunshineNum,10), &r, DT_CENTER);// 画植物和墓碑paintPlantsAndGraves();// 画僵尸paintZombies();// 画除草机for (int i = 0; i < 5; i++){if (lawnmowers[i]->isOut == 0){transparentImage(NULL, lawnmowers[i]->location, xys[i][0].y + 45, &lawnmower);}}drawHint();		// 画提示paintSuns();		// 画太阳paintBangs();		// 画 bangpaintCursor();		// 画鼠标// 画雪花if (snowCountDown > 0){snowCountDown--;transparentImage(NULL, 0, 0, &snow);}FlushBatchDraw();// 计算// 除草机状态for (int i = 0; i < 5; i++){if (lawnmowers[i]->isActivated == 1){lawnmowers[i]->location += 5;if (lawnmowers[i]->location > 800){lawnmowers[i]->isOut = 1;}}}// 如果点了鼠标while (peekmessage(&mousemsg, EM_MOUSE)){           if (mousemsg.message == WM_LBUTTONDOWN){if (mousemsg.x > 692 && mousemsg.y > 0 && mousemsg.x < 815 && mousemsg.y < 44){// 如果点击了菜单,存档退出writeArchive(username);goto stopGame;}if (cursor == Chammer){// 如果鼠标是锤子// 如果点了土豆雷if (mousemsg.x > 86 && mousemsg.y > 10 && mousemsg.x < 133 && mousemsg.y < 79){if (currentSunshine >= 25)cursor = CpotatoMine;elsedrawingHint = 2;}// 如果点了墓碑吞噬者else if (mousemsg.x > 145 && mousemsg.y > 10 && mousemsg.x < 191 && mousemsg.y < 79){if (currentSunshine >= 75)cursor = Cgravebuster;elsedrawingHint = 2;}// 如果点了寒冰菇else if (mousemsg.x > 204 && mousemsg.y > 10 && mousemsg.x < 253 && mousemsg.y < 79){if (currentSunshine >= 75)cursor = Ciceshroom;elsedrawingHint = 2;}else{hammerRadius = 0;isHitting = 1;mciSendString("play ./Music/hit.mp3 from 0", 0, 0, 0);Node<Zombie>* cur = zombies.head;while (cur != NULL){Zombie* zombie = cur->content;                        if (mousemsg.x > zombie->location + 97 && mousemsg.y > xys[zombie->row][0].y - 40&& mousemsg.x < zombie->location + 164 && mousemsg.y < xys[zombie->row][0].y + zombie->height){// 如果锤到了僵尸,僵尸减血或死亡 bangs.InsertNode(new Bang(mousemsg.x - 70, mousemsg.y - 30));zombie->HP--;if (zombie->HP == 0){zombies.DeleteNode(zombie->No);generateSunshine(zombie->location, xys[zombie->row][0].y);}else if (zombie->HP == 1)zombie->type = NORMALZOMBIE;        goto skipLittleWhile;}cur = cur->next;}Node<Sun>* curSun = suns.head;while (curSun != NULL){Sun* sun = curSun->content;if (mousemsg.x > sun->x + 20 && mousemsg.y > sun->y - 18 && mousemsg.x < sun->x + 108 && mousemsg.y < sun->y + 80){// 如果锤中太阳curSun->content->goToCount = 1;mciSendString("play ./Music/sunshine.mp3 from 0", 0, 0, 0);goto skipLittleWhile;}curSun = curSun->next;}}}// 如果鼠标是植物else{int i, j, isInPlantZone = 0;for (i = 0; i < 5; i++){for (j = 0; j < 9; j++){if (mousemsg.x > xys[i][j].x && mousemsg.y > xys[i][j].y&& mousemsg.x < xys[i][j].x + 80 && mousemsg.y < xys[i][j].y + 100){isInPlantZone = 1;break;}}if (isInPlantZone)break;}if ((cursor != Cgravebuster && mapState[i][j] != GRASS) || isInPlantZone == 0){drawingHint = 1;continue;}switch (cursor){case CpotatoMine:{currentSunshine -= 25;mapState[i][j] = POTATO;PotatoMine* potatoMine = new PotatoMine();potatoMine->x = i;potatoMine->y = j;plants.InsertNode(potatoMine);mciSendString("play ./Music/plant.mp3 from 0", 0, 0, 0);break;}case Ciceshroom:{currentSunshine -= 75;mapState[i][j] = ICESHROOM;IceShroom* iceshroom = new IceShroom();iceshroom->x = i;iceshroom->y = j;plants.InsertNode(iceshroom);mciSendString("play ./Music/plant.mp3 from 0", 0, 0, 0);break;}case Cgravebuster:{if (mapState[i][j] < 1 || mapState[i][j]>8){drawingHint = 1;continue;}currentSunshine -= 75;switch (mapState[i][j]){case GRAVE1:mapState[i][j] = GRAVEBUSTER_GRAVE1;break;case GRAVE2:mapState[i][j] = GRAVEBUSTER_GRAVE2;break;case GRAVE3:mapState[i][j] = GRAVEBUSTER_GRAVE3;break;case GRAVE4:mapState[i][j] = GRAVEBUSTER_GRAVE4;break;case GRAVE5:mapState[i][j] = GRAVEBUSTER_GRAVE5;break;case GRAVE6:mapState[i][j] = GRAVEBUSTER_GRAVE6;break;case GRAVE7:mapState[i][j] = GRAVEBUSTER_GRAVE7;break;case GRAVE8:mapState[i][j] = GRAVEBUSTER_GRAVE8;break;default:continue;break;}GraveBuster* gravebuster = new GraveBuster();gravebuster->x = i;gravebuster->y = j;plants.InsertNode(gravebuster);mciSendString("play ./Music/gravebusterchomp.mp3 from 0", 0, 0, 0);break;}}cursor = Chammer;}}else if(mousemsg.message == WM_RBUTTONDOWN){cursor = Chammer;}}//判断土豆雷是否被触发for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){if (mapState[i][j] == POTATOMINE){Node<Zombie>* curZombie = zombies.head, * pre = NULL;while (curZombie != NULL){                       pre = curZombie;curZombie = curZombie->next;if (pre->content->row == i && pre->content->location>xys[i][j].x - 135 && pre->content->location < xys[i][j].x - 20){mapState[i][j] = POTATOBOOM;mciSendString("play ./Music/potato_mine.mp3 from 0", 0, 0, 0);zombies.DeleteNode(pre->content->No);}}}}}//随机产生僵尸randomZombies();//判断输赢if (graveNum == 0 && zombies.head==NULL){Win1Lose2 = 1;mciSendString("play ./Music/trophy.mp3 from 0", 0, 0, 0);goto stopGame;}Node<Zombie>* cur = zombies.head;while (cur != NULL){if (cur->content->location < -150){Win1Lose2 = 2;mciSendString("play ./Music/losemusic.mp3 from 0", 0, 0, 0);goto stopGame;}cur = cur->next;}skipLittleWhile://延时HpSleep(15);}stopGame:mciSendString("close BGM2", 0, 0, 0);
}void loadImages(IMAGE imgs[], char path[],int n,int begin)
{for (int i = 0; i < n; i++){char tmpPath[200], frameNo[4];strcpy_s(tmpPath, 200, path);strcat(strcat(tmpPath, itoa(i + begin, frameNo, 10)), ".png");loadimage(&imgs[i], tmpPath);}
}void loading()
{loadImages(grave, "./graphics/GraveStones/", 8, 1);loadImages(hammer, "./graphics/Screen/hammer/hammer", 13, 1);loadImages(sunPictures, "./graphics/Plants/Sun/Sun_", 22, 0);loadImages(potaotoMinePictures, "./graphics/Plants/PotatoMine/PotatoMine/PotatoMine_", 8, 0);loadImages(iceshroomPictures, "./graphics/Plants/IceShroom/IceShroom/IceShroom_", 11, 0);loadImages(gravebusterPictures, "./graphics/Plants/GraveBuster/GraveBuster-", 28, 1);loadImages(normalZombieWalkPictures, "./graphics/Zombies/NormalZombie/Zombie/Zombie-", 47, 1);loadImages(coneheadZombieWalkPictures, "./graphics/Zombies/ConeheadZombie/ConeheadZombie/ConeheadZombie-", 47, 1);loadImages(bucketheadZombieWalkPictures, "./graphics/Zombies/BucketheadZombie/BucketheadZombie/BucketheadZombie-", 47, 1);loadImages(normalZombieEmergePictures, "./graphics/Zombies/NormalZombie/ZombieEmerge/Zombie-", 20, 1);loadImages(coneheadZombieEmergePictures, "./graphics/Zombies/ConeheadZombie/ConeheadZombieEmerge/Zombie-", 20, 1);loadImages(bucketheadZombieEmergePictures, "./graphics/Zombies/BucketheadZombie/BucketheadZombieEmerge/Zombie-", 20, 1);loadImages(normalZombieEatPictures, "./graphics/Zombies/NormalZombie/ZombieAttack/ZombieAttack_", 10, 0);loadImages(coneheadZombieEatPictures, "./graphics/Zombies/ConeheadZombie/ConeheadZombieAttack/ConeheadZombieAttack_", 10, 0);loadImages(bucketheadZombieEatPictures, "./graphics/Zombies/BucketheadZombie/BucketheadZombieAttack/BucketheadZombieAttack_", 10, 0);loadimage(&potatoBoom, "./graphics/Plants/PotatoMine/PotatoMineExplode/PotatoMineExplode_0.png");loadimage(&potato, "./graphics/Plants/PotatoMine/PotatoMineInit/PotatoMineInit_0.png");loadimage(&plantsBar, "./graphics/Screen/ChooserBackground.png");loadimage(&background, "./graphics/Screen/Background.jpg");loadimage(&selectID, "./graphics/Screen/selectID.png");loadimage(&iceTrap, "./graphics/Plants/IceShroom/IceShroomTrap_0.png");loadimage(&snow, "./graphics/Plants/IceShroom/IceShroomSnow_0.png");loadimage(&menu, "./graphics/Screen/menu.png");loadimage(&lawnmower, "./graphics/Screen/lawnmower.png");loadimage(&loseGame, "./graphics/Screen/lose.png");loadimage(&winGame, "./graphics/Screen/win.png");loadimage(&bang, "./graphics/Screen/bang.png");mciSendString("open ./Music/chomp.mp3", 0, 0, 0);mciSendString("open ./Music/dirt_rise.mp3", 0, 0, 0);mciSendString("open ./Music/gravebusterchomp.mp3", 0, 0, 0);mciSendString("open ./Music/groan.mp3", 0, 0, 0);mciSendString("open ./Music/groan2.mp3", 0, 0, 0);mciSendString("open ./Music/groan3.mp3", 0, 0, 0);mciSendString("open ./Music/groan4.mp3", 0, 0, 0);mciSendString("open ./Music/groan5.mp3", 0, 0, 0);mciSendString("open ./Music/groan6.mp3", 0, 0, 0);mciSendString("open ./Music/hit.mp3", 0, 0, 0);mciSendString("open ./Music/lawnmower.mp3 alias lawnmower", 0, 0, 0);mciSendString("open ./Music/losemusic.mp3", 0, 0, 0);mciSendString("open ./Music/plant.mp3", 0, 0, 0);mciSendString("open ./Music/potato_mine.mp3", 0, 0, 0);mciSendString("open ./Music/shoop.mp3", 0, 0, 0);mciSendString("open ./Music/theZombiesareComing.mp3", 0, 0, 0);mciSendString("open ./Music/trophy.mp3", 0, 0, 0);mciSendString("open ./Music/sunshine.mp3", 0, 0, 0);
}int main()
{srand((unsigned)time(NULL));loading();    for (int i = 0; i < 5; i++){for (int j = 0; j < 9; j++){xys[i][j].x = 40 + j * 82;xys[i][j].y = 70 + i * 100;//cout << "xys[" << i << "][" << j << "]:" << xys[i][j].x << "," << xys[i][j].y << endl;;}}initgraph(820, 600);BeginBatchDraw();labelBGM:mciSendString("open ./Music/Cerebrawl.mp3 alias BGM1", 0, 0, 0);mciSendString("play BGM1 repeat", 0, 0, 0);label2:cleardevice();//背景putimage(0, 0, &background);//对话框if (Win1Lose2 == 0){transparentImage(NULL, 177, 35, &selectID);paintNames();}else if (Win1Lose2 == 1){transparentImage(NULL, 230, 140, &winGame);}else if (Win1Lose2 == 2){transparentImage(NULL, 230, 140, &loseGame);}FlushBatchDraw();while (1){getmessage(&mousemsg, EM_MOUSE);if (mousemsg.message == WM_LBUTTONDOWN){cout << mousemsg.x << "," << mousemsg.y << endl;if (Win1Lose2 == 0){if (mousemsg.x > 236 && mousemsg.y > 436 && mousemsg.x < 391 && mousemsg.y < 474){//点击了“没有我的名字”char s[10];InputBox(s, 10, "请输入你的姓名:");init();writeArchive(s);goto label2;}else if (mousemsg.x > 410 && mousemsg.y > 438 && mousemsg.x < 566 && mousemsg.y < 473){//点击了退出,存档if (strcmp(username, "") != 0)writeArchive(username);return 0;}else if (mousemsg.x > 268 && mousemsg.y > 190 && mousemsg.x < 538 && mousemsg.y < 385){//点击了存档位置if (190 <= mousemsg.y && mousemsg.y < 229){if (0 < files.size() && files.size() < 6)strcpy(username, (char*)files[0].c_str());else continue;}else if (229 <= mousemsg.y && mousemsg.y < 268){if (1 < files.size() && files.size() < 6)strcpy(username, (char*)files[1].c_str());else continue;}else if (268 <= mousemsg.y && mousemsg.y < 307){if (2 < files.size() && files.size() < 6)strcpy(username, (char*)files[2].c_str());else continue;}else if (307 <= mousemsg.y && mousemsg.y < 346){if (3 < files.size() && files.size() < 6)strcpy(username, (char*)files[3].c_str());else continue;}else if (346 <= mousemsg.y && mousemsg.y < 385){if (4 < files.size() && files.size() < 6)strcpy(username, (char*)files[4].c_str());else continue;}readArchive(username);mciSendString("close BGM1", 0, 0, 0);beginGame();if (Win1Lose2 == 0)goto labelBGM;else goto label2;}}else{if (mousemsg.x > 297 && mousemsg.y > 331 && mousemsg.x < 500 && mousemsg.y < 369){init();mciSendString("close BGM1", 0, 0, 0);beginGame();if (Win1Lose2 == 0)goto labelBGM;else goto label2;}}}}getch();EndBatchDraw();closegraph();return 0;
}

素材

邮箱地址在评论区里发给我,我发给你。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/54117.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022高教社杯全国大学生数学建模竞赛C题 问题一(1) Python代码演示

目录 问题 11.1 对这些玻璃文物的表面风化与其玻璃类型、纹饰和颜色的关系进行分析数据探索 -- 单个分类变量的绘图树形图条形图扇形图雷达图Cramer’s V 相关分析统计检验列联表分析卡方检验Fisher检验绘图堆积条形图分组条形图分类模型Logistic回归随机森林import matplotlib…

GAN的损失函数和二元交叉熵损失的对应及代码

以下解释为GPT生成 这里有个问题&#xff0c;使用二元交叉熵&#xff0c;的时候生成器的损失如何体现 看代码 import torch import torch.nn as nn import torch.optim as optim# 设置设备为GPU或CPU device torch.device("cuda" if torch.cuda.is_available() el…

EndnoteX9安装及使用教程

EndnoteX9安装及使用教程 一、EndNote安装 1.1 下载 这里提供一个下载链接&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1RlGJksQ67YDIhz4tBmph6Q 提取码&#xff1a;5210 解压完成后&#xff0c;如下所示&#xff1a; 1.2 安装 双击右键进行安装 安装比较简单…

【C++11 —— 线程库】

C11 —— 线程库 thread类介绍线程函数参数原子性操作库(atomic)lock_guard与unique_lockmutex的种类lock_guardunique_lock 两个线程交替打印奇偶数 thread类介绍 在C11之前&#xff0c;涉及到多线程的问题&#xff0c;都是和平台相关的&#xff0c;比如windows和Linux下各有…

AI 时代程序员的应变之道

一、AI 浪潮来袭&#xff0c;编程界风云变幻 随着 AIGC 大语言模型如 ChatGPT、Midjourney、Claude 等的涌现&#xff0c;AI 辅助编程工具日益普及&#xff0c;程序员的工作方式正经历着深刻的变革。 分析公司 OReilly 日前发布的《2023 Generative AI in the Enterprise》报告…

【Linux基础】冯诺依曼体系结构操作系统的理解

目录 前言一&#xff0c;冯诺依曼体系1. 为什么有内存结构?2. 对硬件中数据流动的再理解 二&#xff0c;操作系统(Operator System)1. 概念2. 操作系统结构的层状划分3. 操作系统对硬件管理的理解4. 用户与操作系统的关系的理解5. 系统调用和库函数的关系6. 为什么要有操作系统…

策略路由与路由策略的区别

&#x1f423;个人主页 可惜已不在 &#x1f424;这篇在这个专栏 华为_可惜已不在的博客-CSDN博客 &#x1f425;有用的话就留下一个三连吧&#x1f63c; 目录 一、主体不同 二、方式不同 三、规则不同 四、定义和基本概念 一、主体不同 1、路由策略&#xff1a;是为了改…

android 删除系统原有的debug.keystore,系统运行的时候,重新生成新的debug.keystore,来完成App的运行。

1、先上一个图&#xff1a;这个是keystore无效的原因 之前在安装这个旧版本android studio的时候呢&#xff0c;安装过一版最新的android studio&#xff0c;然后通过模拟器跑过测试的demo。 2、运行旧的项目到模拟器的时候&#xff0c;就报错了&#xff1a; Execution failed…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0916)

接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835 接口根路径&#xff1a; http://big-event-vue-api-t.itheima.net 本项目的技术栈 本项目技术栈基于 ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus http:/…

RabbitMQ(高阶使用)死信队列

文章内容是学习过程中的知识总结&#xff0c;如有纰漏&#xff0c;欢迎指正 文章目录 一、什么是死信队列&#xff1f; 二、死信队列使用场景 三、死信队列如何使用 四、打车超时处理 1.打车超时实现 以下是本篇文章正文内容 一、什么是死信队列&#xff1f; 先从概念解释上搞…

idea插件推荐之Cool Request

Cool Request是一款基于IDEA的HTTP调试工具&#xff0c;可以看成是轻量版的postman&#xff0c;它会自动扫描项目代码中所有API路径&#xff0c;按项目分组管理。一个类被定义为Controller且其中的方法被RequestMapping或者XXXMapping注解标注以后就会被扫描到。 对应方法左侧会…

智能硬件从零开始的设计生产流程

文章目录 市场分析团队组建ID设计结构设计pcba设计软件开发手板EVT开模DVTPVTMP 智能硬件研发是一个复杂的过程, 当然一件事要发出萌芽必须得有人, 有一天,几个合伙人凑在一起,说一起开发个智能硬件产品吧,于是故事开始了. 市场分析 合伙人: 万物互联的时代, 智能音箱已经成为…

LDR6020,单C口OTG,充放一体新潮流!

PD&#xff08;Power Delivery&#xff09;芯片实现单Type-C接口输入和输出OTG&#xff08;On-The-Go&#xff09;功能&#xff0c;主要是通过支持USB Power Delivery规范和OTG功能的特定硬件和软件设计来实现的。以下是对这一过程的具体解释&#xff1a; 一、PD芯片基础功能 …

Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用增强扩展(text2sql)

前言 我在上一篇文章中《Chainlit集成Langchain并使用通义千问实现和数据库交互的网页对话应用&#xff08;text2sql&#xff09;》 利用langchain 中create_sql_agent 创建一个数据库代理智能体&#xff0c;但是实测中发现&#xff0c;使用 create_sql_agent 在对话中&#x…

Qt控制开发板的LED

Qt控制开发板的LED 使用开发板的IO接口进行控制是嵌入式中非常重要的一点&#xff0c;就像冯诺依曼原理说的一样&#xff0c;一个计算机最起码要有输入输出吧&#xff0c;我们有了信息的接收和处理&#xff0c;那我们就要有输出。 我们在开发板上一般都是使用开发板的GPIO接口…

七、垃圾收集器ParNewCMS与底层三色标记算法详解

文章目录 垃圾收集算法分代收集理论标记-复制算法标记-清除算法标记-整理算法 垃圾收集器1.1 Serial收集器(-XX:UseSerialGC -XX:UseSerialOldGC)1.2 Parallel Scavenge收集器(-XX:UseParallelGC(年轻代),-XX:UseParallelOldGC(老年代))1.3 ParNew收集器(-XX:UseParNewGC)1.4 C…

MATLAB 可视化基础:绘图命令与应用

目录 1. 绘制子图1.1基本绘图命令1.2. 使用 subplot 函数1.3. 绘图类型 2.MATLAB 可视化进阶(以下代码均居于以上代码的数据定义上实现)2.1. 极坐标图2.3. 隐函数的绘制 3.总结 在数据分析和科学计算中&#xff0c;数据可视化是理解和解释结果的关键工具。今天&#xff0c;我将…

Text2vec -文本转向量

文章目录 一、关于 Text2vec1、Text2vec 是什么2、Features3、Demo4、News5、Evaluation英文匹配数据集的评测结果&#xff1a;中文匹配数据集的评测结果&#xff1a; 6、Release Models 二、Install三、使用1、文本向量表征1.2 Usage (HuggingFace Transformers)1.3 Usage (se…

标准库标头 <barrier>(C++20)学习

此头文件是线程支持库的一部分。 类模板 std::barrier 提供一种线程协调机制&#xff0c;阻塞已知大小的线程组直至该组中的所有线程到达该屏障。不同于 std::latch&#xff0c;屏障是可重用的&#xff1a;一旦到达的线程组被解除阻塞&#xff0c;即可重用同一屏障。与 std::l…

深度学习之微积分预备知识点

极限&#xff08;Limit&#xff09; 定义&#xff1a;表示某一点处函数趋近于某一特定值的过程&#xff0c;一般记为 极限是一种变化状态的描述&#xff0c;核心思想是无限靠近而永远不能到达 公式&#xff1a; 表示 x 趋向 a 时 f(x) 的极限。 知识点口诀解释极限的存在左…