通过easyx窗口实现贪吃蛇

(创作不易,感谢有你,你的支持,就是我前行的最大动力,如果看完对你有帮助,请留下您的足迹)

 

今天我们来尝试一下通过easyx窗口创建贪吃蛇小游戏

首先就是引入几个必要的头文件,相信大家都已经不陌生了,因为在之前的小游戏中都有涉及

#include<stdio.h> 

#include<stdlib.h>
#include<graphics.h>  //便于引入easyx窗口及其函数
#include<conio.h>     //按键控制 
#include<time.h>     //构建随机函数

接下来就是对各个变量进行编写,我们这里的窗口高度定义为640,宽度为480

首先就是最为关键的坐标属性 

struct point //坐标属性
{
    int x;
    int y;
};

然后就是蛇和食物的属性 

struct Snake //蛇的属性
{
    int num;       //蛇的节数
    point xy[100]; //蛇最长的节数
    char postion;  //方向
}snake;

struct Food //食物属性
{
    point foodxy; //食物坐标
    int flag;     //食物是否存在
}food;

因为后期在移动小蛇时,我们要对方向进行编写,所以我们在这里不妨先枚举一下各个方向,便于后期编写

enum moveposition{right=77,left=75,down=80,up=72}; 

此处也可以不枚举,只需要将后面代码中的的方向改为相应的数字即可 

接下来我们就要用不同的函数来构建不同的变量,我将不同的变量总结了一下,便于大家观察

void intsnake();//初始化蛇
void drawsnake();//画蛇
void movesnake();//移动蛇
void keysnake();//按键控制
void intfood();//初始化食物
void drawfood();//画食物
void eatfood();//吃食物
int snakedie();//蛇死亡

首先就是初始化蛇了,这里我们将初始化的蛇确定为三节,并且每一节的间距为10,并初始化蛇运动的方向为右

void intsnake()
{
    snake.xy[2].x = 0;
    snake.xy[2].y = 0;
    snake.xy[1].x = 10;
    snake.xy[1].y = 0;
    snake.xy[0].x = 20;
    snake.xy[0].y = 0;
    snake.num = 3;
    snake.postion = right;

 然后就是对蛇进行绘画,我们这里用矩形来表示蛇的身体,对于蛇就颜色,大家可以选择自己喜欢的,我这里用随机函数进行绘制,效果奇特 ,哈哈哈哈哈嗝~

void drawsnake()
{
    for (int i = 0; i < snake.num; i++)
    {
        setlinecolor(BLACK);//边框颜色
        setfillcolor(RGB(rand()%255, rand() % 255, rand() % 255));//填充颜色(随机色)
        //画矩形
        fillrectangle(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + 10, snake.xy[i].y + 10);
    }

然后就是要考虑蛇移动的问题 ,我们可以这样想,所谓的蛇移动,就是在蛇头移动后,蛇身体的每一个坐标都等于它前面的坐标,这里我们将蛇头记为snake.xy[0],那么第二节的坐标就是蛇头移动前的坐标,第三节的坐标就变成了蛇移动前第二节的坐标。因此这里我们将蛇头与蛇身体分开表示

void movesnake()
{   //除了第一节(蛇头),后面每一节都是前一节的坐标
    for (int i = snake.num - 1; i > 0; i--)
    {
        snake.xy[i].x = snake.xy[i - 1].x;
        snake.xy[i].y = snake.xy[i - 1].y;
    }
    //第一节的处理
    switch (snake.postion)
    {
    case right:
        snake.xy[0].x += 10;
        break;
    case left:
        snake.xy[0].x -= 10;
        break;
    case down:
        snake.xy[0].y += 10;
        break;
    case up:
        snake.xy[0].y -= 10;
        break;
    default:
        break;
    }

在确定完蛇的移动顺序后,就是对蛇进行按键处理了,确保蛇可以被键盘控制,如果对键盘操作有不明白的同学可以查阅(http://t.csdn.cn/KkFwU

void keysnake()
{
    char userkey = 0;
    userkey = _getch();//控制台可以直接读取我按的键
    switch (userkey)
    {
    case 'd':
    case right:
        snake.postion = right;        
        break;
    case left:
    case 'a':
        snake.postion = left;        
        break;
    case down:
    case 's':
        snake.postion = down;    
        break;
    case up:
    case 'w':
        snake.postion = up;
        break;
    default:
        break;
    }

蛇我们已经完成,接下来就是对 食物进行编写,这里我们用随机函数rand对食物出现的位置进行定义,确保食物每次出现的位置不同,之所以将640分成64*10,是确保食物尽可能出现在窗口中间,不然数字太小,蛇可能吃不到。这里我们多加一个如果食物出现在蛇身上,是为了防止在一开始的时候食物便出现在蛇身上导致我们没有看见食物。(虽然这样的几率很小很小很小,但我还是想皮一下 ,嘿嘿嘿)

void intfood()
{
    //拆开写,防止蛇吃不到食物
    food.foodxy.x = rand() % 64 * 10;
    food.foodxy.y = rand() % 48 * 10;
    food.flag = 1;//防止反复出现食物
    //如果食物出现在蛇身上
    for(int i = 0; i > snake.num; i++)
    {
        
        if(food.foodxy.x==snake.xy[i].x && food.foodxy.y == snake.xy[i].y)
        {
            food.foodxy.x = rand() % 64 * 10;
            food.foodxy.y = rand() % 48 * 10;
        }
    }
}

 接下来就是画食物了,和蛇一样,我们也用矩形绘制食物

void drawfood()
{
    setlinecolor(BLACK);
    setfillcolor(GREEN);
    fillrectangle(food.foodxy.x, food.foodxy.y, food.foodxy.x + 10, food.foodxy.y + 10);
}

 食物画完了,接下来就该让小蛇吃食物啦

void eatfood()
{
    if (snake.xy[0].x == food.foodxy.x&&snake.xy[0].y==food.foodxy.y)
    {
        snake.num++;//蛇长度每次加一
        food.flag = 0;//重新显示食物
    }
}

接下来就是蛇的死亡啦,小蛇死亡分为两种,撞墙或者撞自己,因为这里用到了MessageBox,所以我们在开头应该声明一个主窗口

HWND hwnd = NULL;//表示主窗口

int snakedie()
{
    if (snake.xy[0].x > 640 || snake.xy[0].y > 480 || snake.xy[0].x < 0 || snake.xy[0].y < 0)
    {
        MessageBox(hwnd, "游戏结束","撞墙",MB_OK);//弹出一个窗口
        return 1;
    }
    for (int i = 1; i < snake.num; i++)//撞自己
    {
        if (snake.xy[0].x == snake.xy[i].x && snake.xy[0].y == snake.xy[i].y)
        {            
            MessageBox(hwnd, "游戏结束", "撞自己", MB_OK);//弹出一个窗口
            return 1;
        }
    }
    return 0;

接下来就是振奋人心的主函数组合啦,我们这里定义flag为0时表示无食物,此时就对食物进行定义并且绘制,在食物出现后,因为 intfood()中flag为1,所以之后食物就不会再次出现,直到在eatfood()中小蛇吃掉食物,并将flag改为0,则食物才会在while()循环的驱动下再次定义并绘制

这里我们还用到了双缓冲绘图,是为了防止小蛇在移动时一闪一闪,这个在我之前的easyx基础中有涉及

int main()
{
    srand((unsigned int)time(NULL));//生成随机数种子
    hwnd = initgraph(640, 480);//窗口大小,init意思是初始化
    setbkcolor(WHITE);//窗口颜色
    intsnake();
    while (1)//循环执行命令
    {
        cleardevice();//刷新一下,防止窗口颜色不变
        //双缓冲绘图,放在绘图代码之前和之后,防止贪吃蛇界面一闪一闪
        BeginBatchDraw();//开始绘图
        drawsnake();
        movesnake();
        drawfood();
        EndBatchDraw();// 结束绘图
        if (food.flag == 0)
        {
            intfood();
        }
        eatfood();
        if (snakedie())
        {
            break;
        }
        while (_kbhit())//判断是否有按键,防止出现屏幕不动的情况
        {
            keysnake();
        }
        Sleep(50);//放慢速度
    }
    getchar();//防止闪屏
    closegraph();//关闭窗口
    return 0;

 总体代码就是这样,如果大家发现bug或者有更好的方法 ,欢迎大家一起来讨论呀

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<graphics.h>
#include<conio.h>
struct point //坐标属性
{
	int x;
	int y;
};
struct Snake //蛇的属性
{
	int num;       //蛇的节数
	point xy[100]; //蛇最长的节数
	char postion;  //方向
}snake;
struct Food //食物属性
{
	point foodxy; //食物坐标
	int flag;     //食物是否存在
}food;
HWND hwnd = NULL;//表示主窗口
enum moveposition{right=77,left=75,down=80,up=72};
//void intsnake();//初始化蛇
//void drawsnake();//画蛇
//void movesnake();//移动蛇
//void keysnake();//按键控制
//void intfood();//初始化食物
//void drawfood();//画食物
//void eatfood();//吃食物
//int snakedie();//蛇死亡

void intsnake()
{
	snake.xy[2].x = 0;
	snake.xy[2].y = 0;
	snake.xy[1].x = 10;
	snake.xy[1].y = 0;
	snake.xy[0].x = 20;
	snake.xy[0].y = 0;
	snake.num = 3;
	snake.postion = right;
}
void drawsnake()
{
	for (int i = 0; i < snake.num; i++)
	{
		setlinecolor(BLACK);//边框颜色
		setfillcolor(RGB(rand()%255, rand() % 255, rand() % 255));//填充颜色(随机色)
		//画矩形
		fillrectangle(snake.xy[i].x, snake.xy[i].y, snake.xy[i].x + 10, snake.xy[i].y + 10);
	}
}
void movesnake()
{   //除了第一节(蛇头),后面每一节都是前一节的坐标
	for (int i = snake.num - 1; i > 0; i--)
	{
		snake.xy[i].x = snake.xy[i - 1].x;
		snake.xy[i].y = snake.xy[i - 1].y;
	}
	//第一节的处理
	switch (snake.postion)
	{
	case right:
		snake.xy[0].x += 10;
		break;
	case left:
		snake.xy[0].x -= 10;
		break;
	case down:
		snake.xy[0].y += 10;
		break;
	case up:
		snake.xy[0].y -= 10;
		break;
	default:
		break;
	}
}
void keysnake()
{
	char userkey = 0;
	userkey = _getch();//控制台可以直接读取我按的键
	switch (userkey)
	{
	case 'd':
	case right:
		snake.postion = right;		
		break;
	case left:
	case 'a':
		snake.postion = left;		
		break;
	case down:
	case 's':
		snake.postion = down;	
		break;
	case up:
	case 'w':
		snake.postion = up;
		break;
	default:
		break;
	}
}
void intfood()
{
	//拆开写,防止蛇吃不到食物
	food.foodxy.x = rand() % 64 * 10;
	food.foodxy.y = rand() % 48 * 10;
	food.flag = 1;
	//如果食物出现在蛇身上
	for(int i = 0; i > snake.num; i++)
	{
		
		if(food.foodxy.x==snake.xy[i].x && food.foodxy.y == snake.xy[i].y)
		{
			food.foodxy.x = rand() % 64 * 10;
			food.foodxy.y = rand() % 48 * 10;
		}
	}
}
void drawfood()
{
	setlinecolor(BLACK);
	setfillcolor(GREEN);
	fillrectangle(food.foodxy.x, food.foodxy.y, food.foodxy.x + 10, food.foodxy.y + 10);
}
void eatfood()
{
	if (snake.xy[0].x == food.foodxy.x&&snake.xy[0].y==food.foodxy.y)
	{
		snake.num++;//蛇长度每次加一
		food.flag = 0;//重新显示食物
	}
}
int snakedie()
{
	if (snake.xy[0].x > 640 || snake.xy[0].y > 480 || snake.xy[0].x < 0 || snake.xy[0].y < 0)
	{
		MessageBox(hwnd, "游戏结束","撞墙",MB_OK);//弹出一个窗口
		return 1;
	}
	for (int i = 1; i < snake.num; i++)//撞自己
	{
		if (snake.xy[0].x == snake.xy[i].x && snake.xy[0].y == snake.xy[i].y)
		{			
			MessageBox(hwnd, "游戏结束", "撞自己", MB_OK);//弹出一个窗口
			return 1;
		}
	}
	return 0;
}
int main()
{
	srand((unsigned int)time(NULL));//生成随机数种子
	hwnd = initgraph(640, 480);//窗口大小,init意思是初始化
	setbkcolor(WHITE);//窗口颜色
	intsnake();
	while (1)
	{
		cleardevice();//刷新一下,防止窗口颜色不变
		//双缓冲绘图,放在绘图代码之前和之后,防止贪吃蛇界面一闪一闪
		BeginBatchDraw();//开始绘图
		drawsnake();
		movesnake();
		drawfood();
		EndBatchDraw();// 结束绘图
		if (food.flag == 0)
		{
			intfood();
		}
		eatfood();
		if (snakedie())
		{
			break;
		}
		while (_kbhit())
		{
			keysnake();
		}
		Sleep(50);//放慢速度
	}
	getchar();//防止闪屏
	closegraph();//关闭窗口
	return 0;
}

 大家一起加油

  • 6
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
以下是一个使用easyx实现的简单贪吃蛇游戏C语言代码: ```c #include <graphics.h> #include <conio.h> #include <time.h> #define WIDTH 640 // 窗口宽度 #define HEIGHT 480 // 窗口高度 #define SIZE 20 // 贪吃蛇每个正方形的边长 #define MAX_LENGTH (WIDTH / SIZE) * (HEIGHT / SIZE) // 贪吃蛇最大长度 struct Snake { int x, y; // 贪吃蛇头部坐标 int length; // 贪吃蛇长度 int direction; // 贪吃蛇运动方向 int body[MAX_LENGTH][2]; // 贪吃蛇身体各个部分的坐标 } snake; struct Food { int x, y; // 食物坐标 } food; void init(); // 初始化函数 void drawSnake(); // 绘制贪吃蛇 void moveSnake(); // 移动贪吃蛇 void generateFood(); // 生成食物 bool isHitWall(); // 判断是否撞墙 bool isHitBody(); // 判断是否撞身体 bool isEatFood(); // 判断是否吃到食物 int main() { init(); while (1) { moveSnake(); if (isHitWall() || isHitBody()) { break; } if (isEatFood()) { generateFood(); } cleardevice(); drawSnake(); Sleep(100); } closegraph(); return 0; } void init() { initgraph(WIDTH, HEIGHT); setbkcolor(WHITE); setfillcolor(BLACK); setcolor(BLACK); snake.x = WIDTH / 2; snake.y = HEIGHT / 2; snake.length = 3; snake.direction = VK_RIGHT; for (int i = 0; i < snake.length; i++) { snake.body[i][0] = snake.x - i * SIZE; snake.body[i][1] = snake.y; } generateFood(); } void drawSnake() { for (int i = 0; i < snake.length; i++) { fillrectangle(snake.body[i][0], snake.body[i][1], snake.body[i][0] + SIZE, snake.body[i][1] + SIZE); } setfillcolor(RED); fillrectangle(food.x, food.y, food.x + SIZE, food.y + SIZE); setfillcolor(BLACK); } void moveSnake() { for (int i = snake.length - 1; i > 0; i--) { snake.body[i][0] = snake.body[i - 1][0]; snake.body[i][1] = snake.body[i - 1][1]; } switch (snake.direction) { case VK_UP: snake.y -= SIZE; break; case VK_DOWN: snake.y += SIZE; break; case VK_LEFT: snake.x -= SIZE; break; case VK_RIGHT: snake.x += SIZE; break; } snake.body[0][0] = snake.x; snake.body[0][1] = snake.y; } void generateFood() { srand((unsigned int)time(NULL)); bool flag = true; while (flag) { flag = false; food.x = SIZE * (1 + rand() % (WIDTH / SIZE - 2)); food.y = SIZE * (1 + rand() % (HEIGHT / SIZE - 2)); for (int i = 0; i < snake.length; i++) { if (food.x == snake.body[i][0] && food.y == snake.body[i][1]) { flag = true; break; } } } } bool isHitWall() { if (snake.x < SIZE || snake.x > WIDTH - 2 * SIZE || snake.y < SIZE || snake.y > HEIGHT - 2 * SIZE) { return true; } else { return false; } } bool isHitBody() { for (int i = 1; i < snake.length; i++) { if (snake.body[i][0] == snake.x && snake.body[i][1] == snake.y) { return true; } } return false; } bool isEatFood() { if (snake.x == food.x && snake.y == food.y) { snake.length++; snake.body[snake.length - 1][0] = snake.body[snake.length - 2][0]; snake.body[snake.length - 1][1] = snake.body[snake.length - 2][1]; return true; } else { return false; } } ``` 在该代码中,我们使用了`graphics.h`和`conio.h`两个头文件来实现图形界面和键盘输入的功能。其中,`init()`函数负责初始化贪吃蛇和食物的位置、长度、方向等信息,`drawSnake()`函数负责绘制贪吃蛇和食物,`moveSnake()`函数负责移动贪吃蛇,`generateFood()`函数负责随机生成食物,并判断其是否与贪吃蛇身体重叠,`isHitWall()`函数和`isHitBody()`函数分别用于判断贪吃蛇是否撞墙和撞身体,`isEatFood()`函数用于判断贪吃蛇是否吃到了食物。在主函数中,我们使用一个循环不断移动贪吃蛇,并根据不同情况终止游戏。 在编写完代码后,我们需要在编译选项中添加`-lbgi -lgdi32 -lcomdlg32 -luuid -loleaut32 -lole32`这些库文件,才能正常编译和运行程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小周不摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值