两条蛇实现原理:先定义好一条蛇,然后派生出另外一条蛇,重要第二条蛇的移动方向的方法,换成键盘上的另外四个键,然后就是正常的游戏判断,两条蛇相碰的判断等等 . . .
素材就是一个背景加上一个音乐,其它的都是基于 EasyX 里的方法画出来的
游戏效果如下所示:
小游戏制作贪吃蛇
代码如下所示:
#include <iostream>
#include <graphics.h>
#include <ctime>
#include <conio.h>
#include <cstdlib>
#include <cmath>
#include <mmsystem.h>
#pragma comment (lib,"winmm")
void InitGame(); //初始化游戏
const int WIDTH = 640;
const int HEIGHT = 480;
class Snake // 1 红色 2 绿色
{
private:
const static int NUM = 100; //最大节数
struct Coord //每一节的坐标
{
int x;
int y;
};
int s_count; //初始为3节
int fruit_x, fruit_y; //果实的位置
Coord snake[NUM]; //一共多少节
protected:
enum Direction { Up = 72, Down = 80, Left = 75, Right = 77 }; //枚举方向
Direction direction; //默认为左方向
public:
//构造
Snake();
//析构
virtual ~Snake();
//初始蛇 和 果实的坐标
void InitSnakeFruitCoord();
//移动 (改变坐标) 画蛇 判断吃果实
void Move();
//刷新果实 位置
void RefreshFruit();
//改变蛇的方向
virtual void ChangeDirection(const char& ch);
//判断游戏 输赢
void JudgeWinLose(const Snake& op, const int flag)const;
};
class Snake1 :public Snake // 继承一个类 达到两条蛇
{
public:
//构造
Snake1();
virtual void ChangeDirection(const char& ch);
};
int main()
{
srand((unsigned)time(0)); //种下随机数的种子
DWORD t1 = GetTickCount(), tt1; //判断是否可以移动
Snake snake1; //两条蛇
Snake1 snake2;
InitGame();
snake1.InitSnakeFruitCoord(); //画出蛇刚开始的位置
snake2.InitSnakeFruitCoord();
while (1)
{
if (_kbhit()) //判断改变位置
{
char ch = _getch();
snake1.ChangeDirection(ch);
snake2.ChangeDirection(ch);
}
tt1 = GetTickCount();
if (tt1 - t1 > 100) //自移
{
setfillcolor(RED);
snake1.Move();
setfillcolor(GREEN);
snake2.Move();
t1 = tt1;
}
snake1.JudgeWinLose(snake2, 1);
snake2.JudgeWinLose(snake1, 2);
}
return 0;
}
Snake::Snake() :direction(Left), s_count(4), fruit_x(0), fruit_y(0)
{
int x = (rand() % (WIDTH - 100) + 50) / 15 * 15; //蛇的初始坐标
int y = (rand() % (HEIGHT - 150) + 50) / 15 * 15;
for (int i = 0; i < s_count; i++)
snake[i] = { (i * 15) + x, y };
}
Snake1::Snake1() :Snake() {} // 使用默认构造 函数 Snake() ----
Snake::~Snake() {}
void InitGame()
{
initgraph(WIDTH, HEIGHT);
MOUSEMSG msg;
mciSendString("open music.mp3 alias huameng", 0, 0, 0);
mciSendString("play huameng repeat", 0, 0, 0);
loadimage(nullptr, "start_background.jpg", WIDTH, HEIGHT);
std::cin.get();
setbkcolor(RGB(255, 128, 192));
cleardevice();
settextcolor(RED);
settextstyle(40, 25, "楷体");
outtextxy(200, 100, "开始游戏");
setlinecolor(RGB(155, 155, 0));
rectangle(190, 90, 410, 145); //------
settextstyle(20, 10, "楷体");
settextcolor(RGB(50, 128, 255));
outtextxy(130, 200, "游 戏 规 则 :");
outtextxy(180, 230, "玩家一:小红 控制:4个光标键");
outtextxy(180, 260, "玩家二:小绿 控制:W A S D");
outtextxy(80, 320, "胜利条件:1.对方触碰边界 2.对方触碰己方身体");
outtextxy(180, 355, "3.吃满果实(100个) >> __ <<");
outtextxy(170, 400, "注: 同灰余烬 算小绿 赢 !!!");
settextstyle(40, 25, "楷体");
while (1)
{
msg = GetMouseMsg();
int x = msg.x; //rectangle(190,90,410,145); 长 220 宽 55
int y = msg.y;
if (x - 190 < 220 && x - 190 > 0 && y - 90 > 0 && y - 90 <= 55 && msg.mkLButton)
break;
else if (x - 190 < 220 && x - 190 > 0 && y - 90 > 0 && y - 90 <= 55)
{
settextcolor(RGB(0, 255, 255));
outtextxy(200, 100, "开始游戏");
}
else
{
settextcolor(RED);
outtextxy(200, 100, "开始游戏");
}
}
setbkcolor(RGB(0, 255, 255));
cleardevice();
}
void Snake::RefreshFruit()
{
fruit_x = (rand() % (WIDTH - 100) + 50) / 15 * 15; // 刷新位置
fruit_y = (rand() % (HEIGHT - 100) + 50) / 15 * 15;
}
void Snake::InitSnakeFruitCoord()
{
for (int i = 0; i < s_count; i++)
solidrectangle(snake[i].x, snake[i].y, snake[i].x + 15, snake[i].y + 15);
fruit_x = (rand() % (WIDTH - 100) + 50) / 15 * 15;
fruit_y = (rand() % (HEIGHT - 100) + 50) / 15 * 15;
}
void Snake::Move()
{
clearrectangle(snake[s_count - 1].x, snake[s_count - 1].y, snake[s_count - 1].x + 15, snake[s_count - 1].y + 15);
for (int i = s_count - 1; i > 0; i--)
{
snake[i].x = snake[i - 1].x;
snake[i].y = snake[i - 1].y;
}
switch (direction)
{
case Snake::Up:
snake[0].y -= 15;
break;
case Snake::Down:
snake[0].y += 15;
break;
case Snake::Left:
snake[0].x -= 15;
break;
case Snake::Right:
snake[0].x += 15;
break;
}
for (int i = 0; i < s_count; i++)
solidrectangle(snake[i].x, snake[i].y, snake[i].x + 15, snake[i].y + 15);
solidrectangle(fruit_x, fruit_y, fruit_x + 15, fruit_y + 15);
if (snake[0].x == fruit_x && snake[0].y == fruit_y)
{
RefreshFruit();
Move(); //防止吃到果实 卡顿
s_count++;
}
}
void Snake::ChangeDirection(const char& ch)
{
switch (ch)
{
case 72:direction = Up; break;
case 75:direction = Left; break;
case 77:direction = Right; break;
case 80:direction = Down; break;
}
}
void Snake1::ChangeDirection(const char& ch)
{
switch (ch)
{
case 'W':direction = Up; break;
case 'A':direction = Left; break;
case 'D':direction = Right; break;
case 'S':direction = Down; break;
}
}
void Snake::JudgeWinLose(const Snake& op, const int flag)const
{
if (flag == 1)
{
if (snake[0].x <= 0 || snake[0].x >= WIDTH || snake[0].y <= 0 || snake[0].y >= HEIGHT || s_count >= 99)
{
MessageBox(nullptr, "小绿胜利了 >>_<<", "游戏结束!!", MB_OK);
exit(0);
}
else
for (int i = 0; i < op.s_count; i++)
{
if (snake[0].x == op.snake[i].x && snake[0].y == op.snake[i].y)
{
MessageBox(nullptr, "小绿胜利了 >>_<<", "游戏结束!!", MB_OK);
exit(0);
}
}
}
else
{
if (snake[0].x <= 0 || snake[0].x >= WIDTH || snake[0].y <= 0 || snake[0].y >= HEIGHT || s_count >= 99)
{
MessageBox(nullptr, "小红胜利了 >>_<<", "游戏结束!!", MB_OK);
exit(0);
}
else
for (int i = 0; i < op.s_count; i++)
{
if (snake[0].x == op.snake[i].x && snake[0].y == op.snake[i].y)
{
MessageBox(nullptr, "小红胜利了 >>_<<", "游戏结束!!", MB_OK);
exit(0);
}
}
}
}