#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <conio.h>
#define WALL "■" //墙壁
#define EMPTY " " //空白
#define FOOD "¥" //食物
#define SNAKE "■" //蛇
#define MAP_WIDTH 32 //地图宽度
#define MAP_HEIGHT 16 //地图高度
#define SNAKE_MAX_LEN 100//蛇的最大长度
#define UP 72 //↑键
#define DOWN 80 //↓键
#define LEFT 75 //←键
#define RIGHT 77 //→键
struct {
unsigned int max_y; //地图高度
unsigned int max_x; //地图宽度
} map; //地图
struct {
int len; //长度
int direction; //方向
int x[SNAKE_MAX_LEN]; //每一个节的横坐标
int y[SNAKE_MAX_LEN]; //每一个节的纵坐标
} snake; //蛇
struct {
int x; //横坐标
int y; //纵坐标
} food; //食物
//光标移动到(x,y)
void gotoxy(int x, int y)
{
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
//影藏光标
void hide_cursor()
{
CONSOLE_CURSOR_INFO cur_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cur_info);
}
//设置颜色
//0=黑色,1=蓝色,2=绿色,3=湖蓝色,4=红色,5=紫色,6=黄色,7=白色
//8=灰色,9=淡蓝色,10=淡绿色,11=浅绿色,12=淡红色,13=淡紫色,14=淡黄色,15=亮白色
void set_color(int color)
{
if(color >= 0 && color <= 15)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
}
//创建地图
void create_map()
{
map.max_x = MAP_WIDTH * 2; //最大横坐标
map.max_y = MAP_HEIGHT; //最大纵坐标
}
//显示地图
void show_map()
{
int i;
//显示上下的墙壁
for (i = 0; i <= map.max_x; i += 2)//i+=2是因为横向占用的是两个位置
{
gotoxy(i, 0); //将光标移动依次到(i,0)处打印上边框
printf(WALL);
gotoxy(i, map.max_y); //将光标移动依次到(i,MAPHEIGHT)处打印下边框
printf(WALL);
}
//显示左右的墙壁
for (i = 0; i < map.max_y; i++)
{
gotoxy(0, i); //在坐标(0, i)显示墙壁
printf(WALL);
gotoxy(map.max_x, i); //在坐标(map.max_y, i)显示墙壁
printf(WALL);
}
}
//随机生成食物
void create_food()
{
int i;
//生成食物的坐标,并确保坐标位于地图内部
food.x = (rand() % (MAP_WIDTH - 2) + 1) * 2;
food.y = (rand() % (map.max_y - 2)) + 1;
//随机生成的食物不能在蛇的身体上
for (i = 0; i < snake.len; i++)
{
if (snake.x[i] == food.x && snake.y[i] == food.y)
{
create_food(); //如果在蛇身上就重新生成
break;
}
}
}
//在对应的坐标显示食物
void show_food()
{
set_color(6);
gotoxy(food.x, food.y);
printf(FOOD);
}
//生成蛇
void create_snake()
{
int i;
//蛇的初始长度和移动方向
snake.len = 3;
snake.direction = LEFT;
//蛇的初始位置在地图右侧
snake.x[0] = map.max_x / 2; //map.max_x - 2 * snake.len;
snake.y[0] = map.max_y / 2;
//横向生成蛇身
for (i = 1; i < snake.len; i++)
{
//蛇的上一节坐标为(x,y),则这一节的坐标为(x+2,y)
snake.x[i] = snake.x[i - 1] + 2;
snake.y[i] = snake.y[i - 1];
}
}
//显示蛇
void show_snake()
{
int i;
set_color(2);
for (i = 0; i < snake.len; i++)
{
gotoxy(snake.x[i], snake.y[i]);
printf(SNAKE);
}
}
//隐藏蛇
void hide_snake()
{
int i;
for (i = 0; i < snake.len; i++)
{
gotoxy(snake.x[i], snake.y[i]);
printf(EMPTY);
}
}
//移动蛇的位置
void move_snake()
{
int i;
//蛇的每一节的坐标移动到前一节的坐标
for (i = snake.len - 1; i > 0; i--)
{
snake.x[i] = snake.x[i - 1];
snake.y[i] = snake.y[i - 1];
}
//最前面的蛇头根据移动方向移动坐标
if (snake.direction == UP)
{
snake.y[0] --; //往上
}
else if (snake.direction == DOWN)
{
snake.y[0] ++; //往下
}
else if (snake.direction == LEFT)
{
snake.x[0] -= 2; //往左
}
else if (snake.direction == RIGHT)
{
snake.x[0] += 2; //往右
}
}
//改变蛇的移动方向,不允许往反方向移动
void change_snake_direction(int direction)
{
if ((direction == UP) && (snake.direction != DOWN))
{
snake.direction = UP;
}
else if ((direction == DOWN) && (snake.direction != UP))
{
snake.direction = DOWN;
}
else if ((direction == LEFT) && (snake.direction != RIGHT))
{
snake.direction = LEFT;
}
else if ((direction == RIGHT) && (snake.direction != LEFT))
{
snake.direction = RIGHT;
}
}
int is_game_over()
{
int i;
//蛇头碰到边界,游戏结束
if (snake.y[0] == 0 || snake.y[0] == map.max_y || snake.x[0] == 0 || snake.x[0] == map.max_x)
{
return 1;
}
//蛇头碰到蛇身,游戏结束
for (i = 1; i < snake.len; i++)
{
if (snake.x[i] == snake.x[0] && snake.y[i] == snake.y[0])
{
return 1;
}
}
return 0;
}
int get_key()
{
_getch();//第一次调用的返回值没用
return _getch(); //第二次调用返回的是按键号码
}
//改变蛇的长度
void change_snake_lenth()
{
if(snake.len < SNAKE_MAX_LEN)
{
snake.len ++;
snake.x[snake.len - 1] = snake.x[(snake.len - 1) - 1];
snake.y[snake.len - 1] = snake.y[(snake.len - 1) - 1];
}
}
//显示文字信息
void show_text()
{
set_color(7);
gotoxy(map.max_x + 4, 0);
printf("↑:向上移动");
gotoxy(map.max_x + 4, 1);
printf("↓:向下移动");
gotoxy(map.max_x + 4, 2);
printf("←:向左移动");
gotoxy(map.max_x + 4, 3);
printf("→:向右移动");
gotoxy(map.max_x + 4, 6);
printf("长度:%d",snake.len);
}
//游戏主体
void main()
{
//创建地图、蛇、食物
create_map();
create_snake();
create_food();
//显示地图、蛇、食物、文字信息
// color(6);
show_map();
show_snake();
show_food();
show_text();
//隐藏光标
hide_cursor();
while(1)
{
//如果有按键按下,根据按键改变蛇的移动方向
if (_kbhit())
{
change_snake_direction(get_key());
}
//把蛇隐藏,换个位置重新显示
hide_snake();
move_snake();
if (snake.x[0] == food.x && snake.y[0] == food.y) //判定蛇吃到食物
{
change_snake_lenth();
create_food();
show_food();
show_text();
}
show_snake();
//判定游戏结束
if (is_game_over())
{
break;
}
//隐藏光标
hide_cursor();
//每隔200毫秒刷新一次
Sleep(200);
}
gotoxy(map.max_x / 2 - 4, map.max_y / 2);
printf("游戏结束");
getchar();
}