#include using namespace std; #include //包含图形库头文件 #include #include #define WIDTH 1040 //定义场景大小 #define HEIGHT 640 #define SIZE 20 //定义食物以及蛇的大小 一个格子的大小 #define UP 1 //定义蛇的朝向 #define DOWN -1 #define LEFT 2 #define RIGHT -2 #define MAX 2000 //蛇的最大长度 typedef struct { int x; int y; }SnakeNode; SnakeNode temp[MAX]; //用另外一个数组来存储蛇原来的位置 int speed = 150; //蛇的速度 //创建蛇的类 class Snake { friend class Food; public: Snake(); //初始化 void Move(); //移动 void Draw(); //绘制蛇 bool Eat(Food food); //吃食物 bool Defeat(); //失败判定 private: int dirt; //朝向 int length; //长度 SnakeNode node[MAX]; //蛇的坐标 }; //创建食物的类 class Food { friend class Snake; public: Food(Snake snake); //食物初始化 void Draw(); //绘制食物 private: int x, y; //坐标 }; //蛇的初始化 Snake::Snake() { dirt = RIGHT; length = 3; //下标是0的位置为蛇的头部 for (int i = 0; i < length; i++) { node[i].x = 60 - ((i + 1) * SIZE);//坐标带上20 node[i].y = 0; } //固定刚开始蛇的位置 //蛇一开始从屏幕的左上角出现 } //移动 void Snake::Move() { for (int i = 0; i < length; i++) //将原来的蛇结点拷贝一份 { temp[i].x = node[i].x; temp[i].y = node[i].y; } int status = 0; //用来判断是否点击了转向按键 if (dirt == RIGHT) //四个方向,讨论现在的方向,分别判断是否转向,不能反向。 { //判断是否转向 if (GetAsyncKeyState('W') && status == 0) //捕捉键盘输入为w,easyx 判断转向 { dirt = UP; //去了if(dirt==up)的else status = 1; } else if (GetAsyncKeyState('S') && status == 0) { dirt = DOWN; status = 1; } else { node[0].x = node[0].x + SIZE; } } if (dirt == DOWN) { //判断是否转向 if (GetAsyncKeyState('A') && status == 0) { dirt = LEFT; status = 1; } else if (GetAsyncKeyState('D') && status == 0) { node[0].x = node[0].x + SIZE; dirt = RIGHT; status = 1; } else { node[0].y = node[0].y + SIZE; } } if (dirt == LEFT) { //判断是否转向 if (GetAsyncKeyState('W') && status == 0) { dirt = UP; status = 1; } else if (GetAsyncKeyState('S') && status == 0) { node[0].y = node[0].y + SIZE; dirt = DOWN; status = 1; } else { node[0].x -= SIZE; } } if (dirt == UP) { //判断是否转向 if (GetAsyncKeyState('A') && status == 0) { node[0].x = node[0].x - SIZE; dirt = LEFT; status = 1; } else if (GetAsyncKeyState('D') && status == 0) { node[0].x = node[0].x + SIZE; dirt = RIGHT; status = 1; } else { node[0].y = node[0].y - SIZE; //改变坐标 } } //移动 for (int i = 1; i < length; i++) { node[i].x = temp[i - 1].x; node[i].y = temp[i - 1].y; } Sleep(speed); //休眠这么长时间,停顿一下 } //绘制蛇 void Snake::Draw() { cleardevice(); //清空原先的绘图 srand((unsigned)time(NULL)); //设置颜色随机数(setfillcolor)时用 for (int i = 0; i < length; i++) { setfillcolor(RGB(rand() % 256, rand() % 256, rand() % 256)); //五颜六色的蛇 fillrectangle(node[i].x, node[i].y, node[i].x + SIZE, node[i].y + SIZE); } } //吃食物 bool Snake::Eat(Food food) { if (food.x == node[0].x && food.y == node[0].y) //头有没有碰到食物 { if (node[length - 1].x - node[length - 2].x == 0 && node[length - 1].y - node[length - 2].y == -20) { //判断蛇尾巴的方向(数组最后两个点的位置关系),新点加在尾巴后面 length++; node[length - 1].x = node[length - 2].x; node[length - 1].y = node[length - 2].y - SIZE; } else if (node[length - 1].x - node[length - 2].x == 0 && node[length - 1].y - node[length - 2].y == 20) { length++; node[length - 1].x = node[length - 2].x; node[length - 1].y = node[length - 2].y + SIZE; } else if (node[length - 1].x - node[length - 2].x == 20 && node[length - 1].y - node[length - 2].y == 0) { length++; node[length - 1].x = node[length - 2].x + SIZE; node[length - 1].y = node[length - 2].y; } else if (node[length - 1].x - node[length - 2].x == -20 && node[length - 1].y - node[length - 2].y == 0) { length++; node[length - 1].x = node[length - 2].x - SIZE; node[length - 1].y = node[length - 2].y; } return true; } return false; } //失败判定 bool Snake::Defeat() { //碰到边界 if (node[0].x < 0 || node[0].x >= WIDTH || node[0].y < 0 || node[0].y >= HEIGHT) return true; //碰到自己的身体 for (int i = 1; i < length; i++) { if (node[0].x == node[i].x && node[0].y == node[i].y) return true; } return false; } //食物的初始化 Food::Food(Snake snake) { table: srand((unsigned)time(NULL)); //设计随机种子,产生随机数 x = (rand() % (WIDTH / SIZE)) * SIZE; y = (rand() % (HEIGHT / SIZE)) * SIZE; for (int i = 0; i < snake.length; i++) { if (snake.node[i].x == x && snake.node[i].y == y) goto table; //如果食物在蛇身上,则重新初始化 } } //绘制食物 void Food::Draw() { setfillcolor(GREEN); //食物是绿色 fillrectangle(x, y, x + SIZE, y + SIZE); //绘制食物为矩形,四个顶点坐标。 } int main() { initgraph(WIDTH, HEIGHT); Snake snake; table: Food food(snake); while (1) { BeginBatchDraw(); FlushBatchDraw(); //双缓冲,防止屏幕一闪一闪的 snake.Draw(); food.Draw(); FlushBatchDraw(); //双缓冲,防止屏幕一闪一闪的 EndBatchDraw(); /*双缓冲,防止屏幕一闪一闪的*/ if (snake.Eat(food)) { goto table; //如果吃到食物,就再设置一个食物 } if (snake.Defeat()) { break; } snake.Move(); } HWND window = GetHWnd(); //弹窗,提示游戏失败 SetWindowText(window, L"提示"); //修改窗口标题,设置成提示 MessageBox(window, L"游戏失败", L"提示", MB_OKCANCEL); //提示失败信息 MB_OKCANCEL:下面有两个按键,确定或取消 return 0; }