步骤:
1、建立蛇对象、食物对象
坐标:
struct COOR{
int X;
int Y;
};
//蛇对象
struct SANKE{
struct COOR snake[MAXSIZE];
int size;
}snake;
//食物对象
struct FOOD{
struct COOR food;
}food;
//定义分数
int score=0;
2、初始化蛇、初始化食物
//初始化蛇
void InitSnake()
{
snake.size=2;
//蛇头
snake.snake[0].X=WIDE/2;
snake.snake[0].Y=HEIGHT/2;
//蛇身
snake.snake[1].X=WIDE/2-1;
snake.snake[1].Y=HEIGHT/2;
}
//初始化食物
void InitFood()
{
food.food.X = rand() % HEIGHT;
food.food.Y = rand() % WIDE;
}
//修改控制台光标的位置 把光标移动到蛇头的位置 同理可以修改光标到食物的位置
COORD coord;
coord.X=snake.snake[0].X;
coord.Y=snake.snake[0].Y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
3、控制流程
1)结束条件:蛇头碰墙 蛇头和蛇身相碰
//蛇头碰墙 如果已经碰墙则不执行后序操作
while(
snake.snake[0].X >=0 && snake.snake[0].X<WIDE
&&
snake.snake[0].Y >=0 && snake.snake[0].Y<height
)
//蛇头碰蛇身
for(int i=1;i<snake.size;i++)
{
if(snake.snake[0].X==snake.snake[i].X && snake.snake[0].Y==snake.snake[i].Y )
return;
}
2)蛇头和食物碰撞:
蛇身增长 食物消失产生新的食物 分数增加 移动速度增加
if(snake.snake[0].X==food.food.X && snake.snake[0].Y==food.food.Y)
{
//蛇身增长
snake.size++;
//食物消失产生新的食物
InitSnake();
//分数增加
score+=10;
//移动速度增加
}
3)蛇的移动: 自动移动 控制移动
void SnakeMove()
{
if(_kbhit()) //检查是否有输入 有则执行
{
char key=_getch();
}
switch (key)
{
case 'w':kx = 0; ky = -1; break;//上
case 's':kx = 0; ky = +1 ; break;//下
case 'd':kx = +1; ky = 0; break;//右
case 'a':kx = -1; ky = 0; break;//左
default:
break;
}
//移动 前一个给后一个
for (int i = snake.size - 1; i > 0; i--)
{
snake.snake[i].X = snake.snake[i - 1].X;
snake.snake[i].Y = snake.snake[i - 1].Y;
}
snake.snake[0].X += kx;
snake.snake[0].Y += ky;
}
4)显示分数 : 排行榜
void ShowScore()
{
COORD coord;
coord.X = 0;
coord.Y = HEIGHT + 2;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
printf("Game Over!!!\n");
printf("最终得分为:%d\n", score);
return;
}
4、图形界面
//设置墙
void SnakeWall()
{
for (int i = 0; i <= HEIGHT; i++)
{
for (int j = 0; j <= WIDE; j++)
{
if (j == WIDE)
{
printf("|");
}
else if (i == HEIGHT)
{
printf("_");
}
else
printf(" ");
}
printf("\n");
}
}
扩展知识:
1、SetConsoleCursorPosition函数
头文件:#include<conio.h>
#include<Windows.h>
typedef struct _COORD{
SHORT X;
SHORT Y;
}COORD;//是Windows API中定义的一种结构,表示一个字符在控制台屏幕上的坐标
COORD coord;//定义结构体变量
//设置坐标
coord.X=10;
coord.Y=20
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),coord);
2、getch() 从控制台无回显的取一个字符
返回值:读取字符的ASCII码
头文件:#include<conio.h>
用法:char key=_getch();
3、kbhit() 以非阻塞方式,检查当前是否有键盘输入
用法:if(kbhit()){……}
返回值:有则为非零值,无则为假0
头文件:#include<conio.h>
编译出错尝试 :_kbhit();
4、SetConsoleCursorInfo() //放到main()函数中
typedef struct _CONSOLE_CURSOR_INFO
{
DWORD dwSize;//大小
BOOL bVisible;//是否可见
}CONSOLE_CURSOR_INFO;//描述光标信息 隐藏光标位置
用法:
CONSOLE_CURSOR_INFO cci;
cci.dwSize=sizeof(cci);
cci.bVisible=FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cci)
综合代码:
头文件snake.h中:
#ifndef __OJ_H__
#define __OJ_H__
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<math.h>
#include<time.h>
#include<conio.h>
#include<Windows.h>
#define MAXSIZE 10
#define WIDE 60
#define HEIGHT 20
struct COOR {
int X;
int Y;
};
//蛇对象
struct SANKE {
struct COOR snake[MAXSIZE];
int size;
}snake;
//食物对象
struct FOOD {
struct COOR food;
}food;
//初始化蛇
void InitSnake();
//初始化食物
void InitFood();
void SnakeMove();
void SnakeWall();
void InitCursorPosition();
void ShowScore();
#endif // !__OJ_H__
text.c 中:
#include"oj.h"
int main()
{
//隐藏光标
CONSOLE_CURSOR_INFO cci;
cci.dwSize = sizeof(cci);
cci.bVisible = FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
_kbhit();
srand((unsigned int)time(NULL));
SnakeWall();
InitSnake();
InitFood();
InitCursorPosition();
SnakeMove();
return 0;
}
snake.c中 :
#define _CRT_SECURE_NO_WARNINGS
#include"oj.h"
//成绩
int score = 0;
//移动后的坐标
int kx = 0;
int ky = 0;
//记录蛇尾坐标
int lastX = 0;
int lastY = 0;
//速度
int sleepSpeed = 400;
//初始化蛇
void InitSnake()
{
snake.size = 2;
//蛇头
snake.snake[0].X = WIDE / 2;
snake.snake[0].Y = HEIGHT / 2;
//蛇身
snake.snake[1].X = WIDE / 2 - 1;
snake.snake[1].Y = HEIGHT / 2;
}
//初始化食物
void InitFood()
{
food.food.X = rand() % WIDE;
food.food.Y = rand() % HEIGHT;
}
//设置坐标在控制台的位置
void InitCursorPosition()
{
COORD coord = { 0 };
for (int i = 0; i < snake.size; i++)
{
coord.X = snake.snake[i].X;
coord.Y = snake.snake[i].Y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
if (i == 0)
{
putchar('@');
}
else
putchar('*');
}
//除去蛇尾
coord.X = lastX;
coord.Y = lastY;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
putchar(' ');
//食物的坐标
coord.X = food.food.X;
coord.Y = food.food.Y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
putchar('#');
}
//设置墙
void SnakeWall()
{
for (int i = 0; i <= HEIGHT; i++)
{
for (int j = 0; j <= WIDE; j++)
{
if (j == WIDE)
{
printf("|");
}
else if (i == HEIGHT)
{
printf("_");
}
else
printf(" ");
}
printf("\n");
}
}
//蛇移动
void SnakeMove()
{
char key = 'd';//默认往右走
while (snake.snake[0].X >= 0 && snake.snake[0].X < WIDE
&&
snake.snake[0].Y >= 0 && snake.snake[0].Y < HEIGHT)
{
//SnakeWall();
InitCursorPosition(); //重画蛇身
if (_kbhit()) //检查是否有输入 有则执行
{
key = _getch();
}
switch (key)
{
case 'w':kx = 0; ky = -1; break;//上
case 's':kx = 0; ky = +1; break;//下
case 'd':kx = +1; ky = 0; break;//右
case 'a':kx = -1; ky = 0; break;//左
default:
break;
}
//蛇头碰蛇身
for (int i = 1; i < snake.size; i++)
{
if (snake.snake[0].X == snake.snake[i].X && snake.snake[0].Y == snake.snake[i].Y)
{
ShowScore();
return;
}
}
//蛇头和食物碰撞
if (snake.snake[0].X == food.food.X && snake.snake[0].Y == food.food.Y)
{
//蛇身增长
snake.size++;
//食物消失产生新的食物
InitFood();
//分数增加
score += 10;
//移动速度增加
sleepSpeed -= 50;
}
//存储蛇尾
lastX = snake.snake[snake.size - 1].X;
lastY = snake.snake[snake.size - 1].Y;
//移动 前一个给后一个
for (int i = snake.size - 1; i > 0; i--)
{
snake.snake[i].X = snake.snake[i - 1].X;
snake.snake[i].Y = snake.snake[i - 1].Y;
}
snake.snake[0].X += kx;
snake.snake[0].Y += ky;
//视觉上让蛇移动
Sleep(sleepSpeed);
//system("cls");
}
ShowScore();
}
void ShowScore()
{
COORD coord;
coord.X = 0;
coord.Y = HEIGHT + 2;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
printf("Game Over!!!\n");
printf("最终得分为:%d\n", score);
return;
}