头文件function.h
#pragma once
#include <stdio.h>
#include <graphics.h>
#include <conio.h>
#include <time.h>
#define BLOCK_SIZE 20
#define HEIGHT 30
#define WIDTH 40
int blocks[HEIGHT][WIDTH] = { 0 };
int score = 0;//吃的食物数量,来控制速度
char moveDirection = 'd';//控制舍身运动方向;
int food_i, food_j;//食物的坐标
bool isfailure = false;//是否失败的标识符
void startup() {//初始化函数
int i;
blocks[HEIGHT / 2][WIDTH / 2] = 1; //1代表蛇头,给地图最中心生成蛇头
for (i = 1; i < 3; i++) {
blocks[HEIGHT / 2][WIDTH / 2 - i] = i + 1;
}//在蛇头后面初始化一个长度为5的蛇身;
srand(time(0));//给srand()时间种子,防止随机有规律有寻;
food_i = rand() % (HEIGHT - 5) + 2;//初始化食物坐标
food_j = rand() % (WIDTH - 5) + 2;
initgraph(WIDTH * BLOCK_SIZE, HEIGHT * BLOCK_SIZE);//初始化窗体
setlinecolor(RGB(50, 50, 50));//设置地图中每个方块的边界颜色
BeginBatchDraw();//开始批量绘制,防止闪屏,与FlushBatchDraw()一起使用;
}
void show() {//绘制函数
cleardevice();//清屏与绘画搭配使用,做到动画的效果;
int i, j;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {//整个地图遍历
if (blocks[i][j] > 0) {
setfillcolor(RGB(300, 50, 100));//蛇身的绘制,并用到HSVTORBG(),使蛇身颜色不一样;
}
else {
setfillcolor(RGB(0, 0, 0));//绘制非蛇身的场景;
}
fillrectangle(j * BLOCK_SIZE, i * BLOCK_SIZE, (j + 1) * BLOCK_SIZE, (i + 1) * BLOCK_SIZE);//真正的绘制函数;
}
}
setfillcolor(RGB(0, 255, 0));//设置食物颜色
fillrectangle(food_j * BLOCK_SIZE, food_i * BLOCK_SIZE, (food_j + 1) * BLOCK_SIZE, (food_i + 1) * BLOCK_SIZE);//在食物地址绘制食物;
if (isfailure) {//如果游戏失败,绘制游戏失败标题;
setbkmode(TRANSPARENT);
settextcolor(RGB(255, 0, 0));
settextstyle(80, 0, _T("宋体"));
outtextxy(240, 220, _T("游戏失败"));
}
setbkmode(TRANSPARENT);
settextcolor(RGB(255, 0, 0));
settextstyle(20, 0, _T("宋体"));
TCHAR s[20];
swprintf_s(s, _T("Now Your Socre is:%d"), score);
outtextxy(0, 0, s);
FlushBatchDraw();//按从BeginBatchDraw()开始的绘制要求绘制
}
void moveSnake() {//控制蛇身动作反应的内在函数
int i, j;
for (i = 0; i < HEIGHT; i++) {//给所有的蛇身的数组加一
for (j = 0; j < WIDTH; j++) {
if (blocks[i][j] > 0) {
blocks[i][j]++;
}
}
}
int oldtial_i, oldtial_j, oldHead_i, oldHead_j;
int max = 0;
for (i = 0; i < HEIGHT; i++) {
for (j = 0; j < WIDTH; j++) {
if (max < blocks[i][j]) {//数组中最大的一定是蛇尾,把旧蛇尾的坐标存起来;
max = blocks[i][j];
oldtial_i = i;
oldtial_j = j;
}
if (blocks[i][j] == 2) {//因为蛇头1加了1,所以为2,借此得到蛇头的位置
oldHead_i = i;
oldHead_j = j;
}
}
}
int newHead_i = oldHead_i; // 设定变量存储新蛇头的位置
int newHead_j = oldHead_j;
if (moveDirection == 'w') {
newHead_i = oldHead_i - 1;//向上新蛇头的位置应该是逻辑上老蛇头的Y坐标减1;
}
else if (moveDirection == 's') {
newHead_i = oldHead_i + 1;//向下新蛇头的位置应该是逻辑上老蛇头的Y坐标加1;
}
else if (moveDirection == 'a') {
newHead_j = oldHead_j - 1;//向左新蛇头的位置应该是逻辑上老蛇头的X坐标减1;
}
else if (moveDirection == 'd') {
newHead_j = oldHead_j + 1;//向右新蛇头的位置应该是逻辑上老蛇头的X坐标加1;
}
if (newHead_i >= HEIGHT || newHead_i <= 0 || newHead_j >= WIDTH || newHead_j <= 0 || blocks[newHead_i][newHead_j] > 0) {//蛇头蛇尾出界,以及检查到新蛇头在蛇身上,也就是蛇咬到自己为游戏失败;
isfailure = true;
return;
}
blocks[newHead_i][newHead_j] = 1;//给新蛇头的位置赋值1;
if (newHead_i == food_i && newHead_j == food_j) {//如果新蛇头位置在食物的地方,也就是蛇吃到了食物,并给食物重新给一个位置;
food_i = rand() % (HEIGHT - 5) + 2;
food_j = rand() % (WIDTH - 5) + 2;
score++;//吃的次数加一;
}
else
blocks[oldtial_i][oldtial_j] = 0;//如果没迟到食物,则尾部为0,就是逻辑上减一
}
void updateWithoutInput() {
if (isfailure) {//游戏未失败继续
return;
}
static int waitIndex = 1;
waitIndex++;
if (waitIndex == 10) {
moveSnake();
waitIndex = 1;//循环重新开始
}
}
void updateWithInput() {
if (_kbhit() && isfailure == 0) {//如果有输入,且未失败
char input = _getch();
if (input == 'a' || input == 's' || input == 'w' || input == 'd') {
moveDirection = input;
moveSnake();
}
}
}
cpp文件
#include "function.h"
int main()
{
startup();//初始化;
while (1) {//不断调用;
show();
updateWithoutInput();//更新与输入无关的参数;
updateWithInput();//更新与输入有关的参数;
}
return 0;
}