贪吃蛇(流畅前进),很可爱的小蛇
作者:wysaid

这个版本的贪吃蛇用的面向对象技术,包含三个文件,请建立项目后将三个文件全部加入才可以编译。

运行效果就不抓图了,抓图不足以体现小蛇的可爱。

作者:wysaid,博客:http://qzone.qq.com/wysaid,邮箱:wysaid@gmail.com

以下是每个文件的代码(点这里下载完整的 VC6 项目打包):

文件 3-1:snake.cpp

///////////////////////////////////////////////////
// 程序名称:Greedy Snake (贪吃蛇)
// 编译环境:Visual C++ 6.0 / 2010,EasyX 2011惊蛰版
// 作  者:wysaid <wysaid@gmail.com>
// 最后修改:2011-1-23
//
#include "snake.h"
 
int main()
{
	// 初始化
	initgraph(640, 480);				// 创建绘图窗口
	setbkcolor(BLUE);					// 设置背景为蓝色
	cleardevice();						// 清屏
	setlinestyle(PS_SOLID, NULL, 5);	// 设置画线宽度
	BeginBatchDraw();					// 设置批绘图模式
	setcolor(YELLOW);					// 设置绘图颜色
	setfillstyle(YELLOW);				// 设置填充颜色

	Snake snake; 
	int speed = 1;
	Fruit fruit(rand()%600+100, rand()%400+100);
	char c = 'd';
	char prior = 0;
	line(100, 240, 0, 240);
	fillcircle(100, 240, 4);
	outtextxy(100, 50, _T("请选择难度:(1, 2, 3)"));
	outtextxy(100, 100, _T("1. 简单"));
	outtextxy(100, 150, _T("2. 中等"));
	outtextxy(100, 200, _T("3. 难!"));
	FlushBatchDraw();
	prior = getch();
	switch(prior)
	{
		case '2': speed = 2;break;
		case '3': speed = 4;break;
		default: prior = 49;
	}
	while(c != 27)
	{
		cleardevice();
		if(kbhit()) 
		{
			c = getch();
			if(abs(prior - c) == 4 || abs(prior - c) == 3) c = prior;
			prior = c;
		}
		switch(c)
		{
			case 'w': snake.move_up(c, speed);break;
			case 's': snake.move_down(c, speed);break;
			case 'a': snake.move_left(c, speed);break;
			case 'd': snake.move_right(c, speed);break;
			case 27: break;
			default: outtextxy(200, 240, _T("错误的按键!请按'w''a''s''d'控制方向或者ESC退出"));FlushBatchDraw();Sleep(1000);c = snake.getdir();
		}

		fruit.drawfruit(snake, speed);
		snake.draw(speed);
		snake.ifhit();
		FlushBatchDraw();
		Sleep(10);
	}

	// 结束游戏,按任意键退出
	outtextxy(200, 240, _T("谢谢使用,再见~"));
	EndBatchDraw();
	getch();
	closegraph();
	return 0;
}

文件 3-2:snake.h

#ifndef _snake_n_
#define _snake_n_

#include<vector>
#include<conio.h>
#include<graphics.h>
#include<cmath>
#include<ctime>
#include<cstdlib>
using std::vector;

class Snake
{
public:
	Snake(){direction = 'd';x_head = 100;y_head = 240;x_corner.push_back(0), y_corner.push_back(240);}
	void operator++();
	friend class Fruit;
	void draw(int);
	void ifhit();
	void longer();
	char getdir(){return direction;}
	void move_up(char direct, int speed){if(direction != direct) {x_corner.push_back(x_head);y_corner.push_back(y_head);}y_head -= speed;direction = direct;}
	void move_down(char direct, int speed){if(direction != direct) {x_corner.push_back(x_head);y_corner.push_back(y_head);}y_head += speed;direction = direct;}
	void move_left(char direct, int speed){if(direction != direct) {x_corner.push_back(x_head);y_corner.push_back(y_head);}x_head -= speed;direction = direct;}
	void move_right(char direct, int speed){if(direction != direct) {x_corner.push_back(x_head);y_corner.push_back(y_head);}x_head += speed;direction = direct;}

private:
	char direction;
	int x_head;
	int y_head;
	vector<int> x_corner;
	vector<int> y_corner;
};

class Fruit
{
public:
	Fruit(){x = 0;y = 0;radius = 4;score = 0;}
	Fruit(int x_first, int y_first){x = x_first;y = y_first;radius = 4;score = 0;}
	void drawfruit(Snake&, int);
	bool eaten(Snake&);
private:
	int x;
	int y;
	int radius;
	int score;
};

void gameover();
#endif

文件 3-3:wysaid.cpp

#include "snake.h"

void Snake::draw(int speed)
{
	int b, s, n=1;

	if(x_head == x_corner[x_corner.size()-1])
		line(x_head, y_head, x_corner[x_corner.size()-1], y_corner[y_corner.size()-1]);
	else
		line(x_head, y_head, x_corner[x_corner.size()-1], y_corner[y_corner.size()-1]);

	fillcircle(x_head, y_head, 4);

	for(; n < (int)x_corner.size(); ++n)
	{
		if(x_corner[n] == x_corner[n-1])
		{
			line(x_corner[n], y_corner[n], x_corner[n-1], y_corner[n-1]);
			if(x_head != x_corner[n])
				continue;

			if(y_corner[n] > y_corner[n-1])
				b = y_corner[n], s = y_corner[n-1];
			else
				b = y_corner[n-1], s = y_corner[n];

			if(y_head < b && y_head > s)
				gameover();
		}
		else
		{
			line(x_corner[n], y_corner[n], x_corner[n-1], y_corner[n-1]);
			if(y_head != y_corner[n])
				continue;

			if(x_corner[n] > x_corner[n-1])
				b = x_corner[n], s = x_corner[n-1];
			else
				b = x_corner[n-1], s = x_corner[n];

			if((x_head < b) && (x_head > s)) gameover();
		}
	}

	if(x_corner.size() != 1)
	{
		if(x_corner[0] == x_corner[1])
		{
			y_corner[0]>y_corner[1]?y_corner[0]-=speed:y_corner[0]+=speed;
			if(y_corner[0] == y_corner[1]) 
			{
				y_corner.erase(y_corner.begin());
				x_corner.erase(x_corner.begin());	
			}
		}
		else if(y_corner[0] == y_corner[1])
		{
			x_corner[0]>x_corner[1]?x_corner[0]-=speed:x_corner[0]+=speed;
			if(x_corner[0] == x_corner[1]) 
			{
				y_corner.erase(y_corner.begin());
				x_corner.erase(x_corner.begin());	
			}
		}
	}
	else if(x_head == x_corner[0])
		y_corner[0] > y_head ? y_corner[0] -= speed : y_corner[0] += speed;
	else
		x_corner[0] > x_head ? x_corner[0] -= speed : x_corner[0] += speed;
}

bool Fruit::eaten(Snake& snake)
{
	return (pow(float(snake.x_head - x), 2) + pow(float(snake.y_head-y), 2) < pow(float(radius), 2) + 4);
}

void Fruit::drawfruit(Snake& snake, int speed)
{
	TCHAR wch[10];
	srand(unsigned(time(NULL)));
	if(eaten(snake))
	{
		x = rand() % (640 - radius) + 8;
		y = rand() % (480 - radius) + 8;
		score += 100 * speed;
		++snake;
	}
	fillcircle(x, y, radius);
	_itot(score, wch, 10);
	outtextxy(160, 10, _T("Your score is:"));
	outtextxy(300, 10, wch);
}

void Snake::ifhit(/*...待添加(障碍物等)...*/)
{
	if(x_head < 4 || x_head > 636 || y_head < 4 || y_head > 476)
		gameover();
	//...待添加...
}

void Snake::operator++()
{
	switch(direction)
	{
		case 'w': y_head -= 8;break;
		case 's': y_head += 8;break;
		case 'a': x_head -= 8;break;
		case 'd': x_head += 8;break;
		default: ;
	}	
}

void gameover()
{
	for(int x=160; x<420; ++x)
		for(int y=350; y<450; ++y)
			putpixel(x, y, RED);

	setcolor(GREEN);
	outtextxy(200, 400, _T("You Lose! But merry xmas!"));
	outtextxy(300, 420, _T("Made by wysaid"));

	EndBatchDraw();
	getch();
	closegraph();
	exit(0);
}
更新时间:2011/3/27