创建源文件选择.cpp?
vs2019下载Easyx并包含头文件
#include<graphics.h>
Easyx图形库下载地址?www.easyx.cn
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<graphics.h>
#include<stdlib.h> //设置种子需要头文件stdlib.h
#include<conio.h> //键盘操作的头文件kbhit,_geth
#define SnakeNum 500//蛇的最大节数
#define FoodNum 40 //食物数量
HWND hwnd = NULL; //用句柄来表示主窗口
enum DIR //表示蛇的方向,枚举
{
UP,
DOWN,
LEFT,
RIGHT,
};
//蛇的结构:坐标xy,节数,方向,速度
struct snake
{
int size;//节数
int dir; //方向,上下左右
int speed;//速度
POINT coor[SnakeNum];//坐标,蛇不止1节,用数组xy,point.保存long型x和y
}snake;
//食物的结构
struct food
{
int x;
int y;
int r; //食物大小(半径)
bool flag; //食物是否被吃的标记
DWORD color; //设置颜色,参数无符号长整型
DWORD eatgrade; //食物分数
}food[FoodNum],Food;
void CreateFood(int i)
{
food[i].x = rand() % 640;//可以用time.h?
food[i].y = rand() % 480;//任何数%一个数永远不会>被%数,2%5=2,//0-4,包含4,被模数是几就是几个数,从0开始
food[i].r = rand() % 10 + 4;//半径
food[i].flag = true;
food[i].eatgrade = 0;
food[i].color = RGB(rand() % 256, rand() % 256, rand() % 256);
}
void GameInit()//数据初始化,xy的坐标
{
initgraph(640, 480); //创建窗口
//initgraph(640, 480,SHOWCONTROL); SHOWCONTROL显示控制台
//设置随机数种子rand +s
srand(GetTickCount());//GetTickCount():获取系统开机到现在所经过的毫秒数,返回毫秒数作为种子
snake.size = 3;//一开始有3节蛇
snake.speed = 10;//速度
snake.dir = RIGHT;
for (int i = 0; i < snake.size; i++)//(初始化三节蛇,开始有3节,用循环,0-3)
//for(执行了语句再更新i++,再看测试条件)
{
snake.coor[i].x = 40 - 10 * i;//画一节就用[0]
snake.coor[i].y = 10;//y不变,下标为0的元素是蛇头
//printf("?%d %d",snake.coor[i].x ,snake.coor[i].y);
//snake.coor[0].x = 40;
//snake.coor[0].y = 10;
//snake.coor[1].x = 30;
//snake.coor[1].y = 10;
//snake.coor[2].x = 20;
//snake.coor[2].y = 10;
}
//初始化食物,食物随机就可以了,随机函数:随机生成一个整数,如果没有设置随机数种子,每次产生的都是固定的整数,如果设置随机数种子,每次产生的都是不同的整数.
//设置种子需要头文件stdlib.h,一般把时间做为种子,因为时间在不断变化,1毫秒一毫秒地增加,1秒=1k毫秒
for (int i = 0; i < FoodNum; i++)
{
CreateFood(i);
}
}
void GameDraw()
{
setbkcolor(WHITE);//设置背景色,要2步,除了设置颜色还要清空绘图设备
cleardevice(); //清除图形屏幕
setlinecolor(RGB(230, 231, 239)); //设置线条颜色
for (int i = 0; i < 640; i += 10) //斜着方向行走速度比xy方向速度快,用 i+=10减少遍历次数
{
//对角线比矩形的边长,画竖线,每格是10个像素宽度就画一条线,x的坐标(10,0) (20,0)(30,0)
//(10,640)(20,640)//y坐标不变,x坐标每次加10
line(i, 0, i, 480);//有两个参数(点),两点确定一个线段,画竖线(高度)//line(i*10,....)
line(0, i, 640, i); //画横线
}
for (int i = 0; i < snake.size; i++)
{
solidcircle(snake.coor[i].x, snake.coor[i].y, 6);//画蛇,圆蛇,solidcircle实心圆,坐标xy,半径
}
//绘制食物
for (int i = 0; i < FoodNum; i++)
{
if (!food[i].flag)//跳过不存在的食物
continue;
setfillcolor(food[i].color);//设置颜色
solidcircle(food[i].x, food[i].y, food[i].r);//画圆
}
setfillcolor(RGB(138, 27, 255)); //setfillcolor((RGB(rand() % 255, rand() % 255, rand() % 255)));//彩色蛇,red green blue
}
//移动蛇,坐标改变,移动时候根据方向去移动,只要改变方向就可以了
void movesnake()
{ //让身体跟着头移动
for (int i = snake.size - 1; i > 0; i--)//如果用snake.size数组越界
{
snake.coor[i] = snake.coor[i - 1];
}//蛇头移动,每一节蛇都是上一节的坐标,后面的节跟着上一节(蛇头的坐标)
//蛇不能直接掉头:限定如果往上就不能按下,往左不能按右...在改变方向那里改这个
switch (snake.dir)//穿墙:往下走之后立马从上面出来
{
case UP:snake.coor[0].y -= snake.speed;//穿墙,每个移动的地方都要进行一次判断
if (snake.coor[0].y + 10 <= 0) //如果头的y坐标往上的时候<=0,超出上面边界,上面是y等于0
{
snake.coor[0].y = 480; //让它的y等于下面(窗口的高度)实现穿墙,头是圆的,以圆心为标椎(+10)
}
break;
case DOWN:snake.coor[0].y += snake.speed;//高度为y=480,宽度为x=640
if (snake.coor[0].y - 10 >= 480)
{
snake.coor[0].y = 0;
}
break;
case LEFT:snake.coor[0].x -= snake.speed;
if (snake.coor[0].x + 10 <= 0)
{
snake.coor[0].x = 640;
}
break;
case RIGHT:snake.coor[0].x += snake.speed;
if (snake.coor[0].x - 10 >= 640)
{
snake.coor[0].x = 0;
}
break;
default:
break;
}
}
void keycontrol()//通过按键改变蛇的方向
{
if (_kbhit())//先判断有没有按键,kbhit检测有没有按键,如果有按键返回真
{
switch (_getch()) // 键盘操作72 80 75 77 上下左右键值小键盘
//只是改变方向,改变snake.dir的方向
//_getch是一个堵塞函数,如果keyctrol()直接放主函数里面蛇不动了,按一下才动一下,所以要先判断有没有按键
{
case 'w':
case 'W':
case 72:
if (snake.dir != DOWN)//如果蛇的方向不是向下就执行向上操作,多了个前提条件:原来代码可以直接执行向上操作,这样就会调头了.
{
snake.dir = UP;
}
break;
case 's':
case 'S':
case 80:
if (snake.dir != UP)
{
snake.dir = DOWN;
}
break;
case 'a':
case 'A':
case 75:
if (snake.dir != RIGHT)
{
snake.dir = LEFT;
}
break;
case 'd':
case 'D':
case 77:
if (snake.dir != LEFT)
{
snake.dir = RIGHT;
}
break;
case ' '://游戏暂停,if满足条件就终止函数
while (1)
{
if (_getch() == ' ')
return;
}
default:
break;
}
}
}
//吃食物,头和食物的距离<=半径长
void eatfood()
{
for (int i = 0; i < FoodNum; i++)
{
if (food[i].flag && (snake.coor[0].x >= food[i].x - food[i].r) && (snake.coor[0].x <= food[i].x + food[i].r) &&
(snake.coor[0].y >= food[i].y - food[i].r) && (snake.coor[0].y <= food[i].y + food[i].r))
{ //让头刚刚挨着食物,就可以吃了.用半径差,食物也有半径,xy要判断两次,在一个范围之内
food[i].flag = false;
snake.size++; //食物存在才能吃,加一个条件:判断食物是否存在
}
if (food[i].flag == 0)//如果食物消失,则重新生成一个食物(falg为假,再初始化食物的属性)
{
food[i].x = rand() % 640;
food[i].y = rand() % 480;
food[i].r = rand() % 10 + 4;//半径
food[i].flag = true;
Food.eatgrade += 2;
}
}
}
void showgrade()//显示分数
{
char grade[100] = "0";
sprintf(grade, "%d", Food.eatgrade); //用sprintf把整型分数转字符串
setbkmode(TRANSPARENT); //透明方式输出,不改变背景
settextcolor(LIGHTBLUE);
outtextxy(560, 20, "分数:");
outtextxy(610, 20, grade);
}
int main()
{
GameInit();
BeginBatchDraw();
while (1)
{
movesnake();
GameDraw();
keycontrol();
eatfood();
showgrade();
Sleep(155); //延迟155毫秒
FlushBatchDraw();//刷新
}
closegraph(); //关闭图形窗口
return 0;
}
|