Day16.贪吃蛇(有小BUG)
一、小知识点
改变光标位置函数:
#include<Windows.h>
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
去掉控制台的光标:
//在main函数开始写这段代码
CONSOLE_CURSOR_INFO cci;
cci.bVisible = FALSE;
cci.dwSize = sizeof(cci);
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
键盘输入,不显示输入的字符
_getch()
此函数没有键盘输入时,返回值为0
_kbhit()
二、代码
贪吃蛇.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<time.h>
#include "wall.h"
#include "snake.h"
#include "food.h"
//分数
int score = 0;
//改变光标位置
void gotoxy(int x, int y)
{
if (x == 0 && y == 0)
{
return;
}
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void gameover(int i)
{
if (i == 1)
{
gotoxy(0, HEIGHT + 1);
printf("撞到墙了,游戏结束!!");
system("pause");
exit(1);
}
if (i == 2)
{
//防止撞到自己,蛇头消失
gotoxy(snake.body[0].x, snake.body[0].y);
printf("@");
gotoxy(0, HEIGHT + 1);
printf("撞到自己了,游戏结束!!");
system("pause");
exit(1);
}
}
void update()
{
for (int i = 0; i < snake.size; i++)
{
gotoxy(snake.body[i].x,snake.body[i].y );
if (i == 0)
{
printf("@");
}
else
{
printf("#");
}
}
//更新食物
gotoxy(food.x, food.y);
printf("X");
//更新蛇尾
gotoxy(slast_x, slast_y);
printf(" ");
//判断是否循环
if (isRool == 1)
{
gotoxy(snake.body[0].x, snake.body[0].y);
printf("@");
}
gotoxy(0, HEIGHT);
printf("得分:%d", score);
}
int main(void)
{
//去掉控制台的光标
CONSOLE_CURSOR_INFO cci;
cci.bVisible = FALSE;
cci.dwSize = sizeof(cci);
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
//生成随机数种子
srand((unsigned int)time(NULL));
//设置墙的颜色
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 128);
//初始化墙
init_wall();
//初始化蛇
init_snake();
//初始化食物
init_food();
//更新显示
update();
//初始化蛇移动方向,默认方向为向右
char key = 'd';
char oldkey = 'd';
while (snake.body[0].x >= 1 && snake.body[0].x <= WIDTH - 2
&& snake.body[0].y >= 1 && snake.body[0].y <= HEIGHT - 2)
{
//获取移动方向,如果没有键盘输入,返回值为0
if(_kbhit())
{
//oldkey = key;
key = _getch();
}
//判断其方向是否冲突
if (oldkey == 'd' && key == 'a' || oldkey == 'a' && key == 'd'
|| oldkey == 'w' && key == 's' || oldkey == 's' && key == 'w')
{
key = oldkey;
}
else
{
oldkey = key;
}
//通过方向更新蛇头偏移量
switch (key)
{
case 'w':
smove_x = 0;
smove_y = -1;
break;
case 'a':
smove_x = -1;
smove_y = 0;
break;
case 's':
smove_x = 0;
smove_y = 1;
break;
case 'd':
smove_x = 1;
smove_y = 0;
break;
}
//判断蛇头是否碰到食物
if ((snake.body[0].x == food.x) && (snake.body[0].y == food.y))
{
snake.size++;
score += 10;
init_food();
}
//判断蛇头是否碰到自己身体
for (int i = 1; i < snake.size; i++)
{
if ((snake.body[0].x == snake.body[i].x) && (snake.body[0].y == snake.body[i].y))
{
gameover(2);
}
}
//获取当前蛇尾位置
slast_x = snake.body[snake.size - 1].x;
slast_y = snake.body[snake.size - 1].y;
//蛇身移动
for (int i = snake.size - 1; i > 0; i--)
{
snake.body[i].x = snake.body[i - 1].x;
snake.body[i].y = snake.body[i - 1].y;
}
//蛇头移动
snake.body[0].x += smove_x;
snake.body[0].y += smove_y;
//判断是否循环
if (snake.body[0].x == snake.body[snake.size - 1].x && snake.body[0].y == snake.body[snake.size - 1].y)
{
isRool = 1;
}
else
{
isRool = 0;
}
update();
if (0 <= score <= 50)
Sleep(250);
else if (50 < score <= 80)
Sleep(150);
else if (80 < score <= 120)
Sleep(100);
else
Sleep(50);
}
gameover(1);
//getchar();
return 0;
}
wall.h
#pragma once
#include<stdio.h>
#define HEIGHT 30
#define WIDTH 60
//初始化墙
void init_wall();
wall.c
#include "wall.h"
void init_wall()
{
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
if (i == 0 || j == 0 || i == HEIGHT - 1 || j == WIDTH-1)
{
printf("*");
}
else
{
printf(" ");
}
}
if (i == 10)
printf("\t贪吃蛇小游戏");
if (i == 11)
printf("\t上:W");
if (i == 12)
printf("\t下:S");
if (i == 13)
printf("\t左:A");
if (i == 14)
printf("\t右:D");
if (i == 15)
printf("\t制作人:徐杰");
printf("\n");
}
}
snake.h
#pragma once
#include<stdio.h>
#include "wall.h"
#include "food.h"
//蛇的每段身体结构体
struct SnakeBody
{
int x;//蛇身体x坐标
int y;//蛇身体y坐标
};
struct Snake
{
int size;
struct SnakeBody body[(HEIGHT - 2) * (WIDTH - 2)];
}snake;
//蛇的初始化
void init_snake();
//蛇移动的偏移量
int smove_x;
int smove_y;
//蛇尾的位置
int slast_x;
int slast_y;
//蛇是否循环
int isRool;
snake.c
#include "snake.h"
void init_snake()
{
//蛇初始长度为3
snake.size = 3;
//蛇头位置
snake.body[0].x = WIDTH / 2;
snake.body[0].y = HEIGHT / 2;
//蛇身位置
snake.body[1].x = WIDTH / 2 - 1;
snake.body[1].y = HEIGHT / 2;
snake.body[2].x = WIDTH / 2 - 2;
snake.body[2].y = HEIGHT / 2;
}
food.h
#pragma once
#include<stdio.h>
#include "snake.h"
#include "wall.h"
struct Food
{
int x;
int y;
}food;
void init_food();
food.c
#include "food.h"
void init_food()
{
int flag = 0;//食物是否出现在蛇身上的标志,=0表示没有出现在蛇身上
while (1)
{
food.x = rand() % (WIDTH - 2) + 1;
food.y = rand() % (HEIGHT - 2) + 1;
for (int i = 0; i < snake.size; i++)
{
if (food.x == snake.body[i].x || food.y == snake.body[i].y)
{
flag = 1;
break;
}
}
if (flag == 0)
{
break;
}
}
}