大一的时候,一直想做贪吃蛇,问了舍友很多次,思路讲了,但自己动手却发现各种难点,后来我指针用得多了,一天晚上,躺在床上,想了一会,就想出来了,原来贪吃蛇真的很简单。
基本思路:
- 初始化地图,在特定的地方打印符号即可
- 初始化食物,随机产生一个食物,就是在某一个地方打印出一个食物
- 初始化蛇头,蛇头也是随机的,都是打印
- 通过上下左右不同按键,进入不同函数操作
- 蛇头和身体,都是靠打印出来的,蛇是一个结构体,里面存x,y坐标,然后在特定位置开始打印就可以了
- 当蛇移动一格的时候,坐标是往前一格的,这就是坐标的运算了。
- 蛇往前移动一格,当没有吃到食物的时候,蛇的身体长度是不变的,所以,把蛇头坐标往前移一格,然后把蛇尾巴那点去掉,也就是删除尾节点
- 当蛇吃到食物的时候,不用删除尾节点
- 如果不按方向键的话,蛇是会一直动的,那么用要用循环了
下面附上代码,绝对是一个完整的代码,可以运行。
#include<iostream>
#include<stdlib.h>
#include<time.h>
#include <windows.h>
#include<conio.h> //跳到屏幕指定坐标
//到特定的坐标
void gotoxy(int ,int );
void gotoxy(int x,int y) {
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
HANDLE hConsoleOut;
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleOut,&csbiInfo);
csbiInfo.dwCursorPosition.X = x;
csbiInfo.dwCursorPosition.Y = y;
SetConsoleCursorPosition(hConsoleOut,csbiInfo.dwCursorPosition);
}
using namespace std;
#define random(num)(rand()%num+1) //用来生存随机数1--num
//蛇
struct Snake {
int x;
int y;
struct Snake *next;
};
Snake *sHead;//蛇头
struct Food {//食物
int x;
int y;
};
Food food;
void initMap();//初始化地图
void startGame(Snake *sHead);//游戏中
void snakeRun(int key);//控制蛇的移动
void deleteTail(Snake *sHead);//删除蛇的尾巴
int main() {
//删除光标
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(handle, &CursorInfo);//设置控制台光标状态
srand((int)time(0));//随机种子
initMap();
startGame(sHead);
return 0;
}
void initMap() {
//初始化地图
for(int i = 0; i <= 54; i+=2 ) {//横坐标每个光标点占两个字符,所以乘2
for(int j = 0; j <= 27; j++) {//纵坐标每个光标点占一个字符
if(i == 0 ||i == 54 || j == 0 || j == 27) {
gotoxy(i,j);
cout<<"□";
}
}
}
//初始化食物的位置
food.x = random(25)*2;
food.y = random(25);
gotoxy(food.x,food.y);//到随机的坐标打印
cout<<"*";
//初始化蛇头的位置
sHead = new Snake;
sHead->x = random(25)*2;
sHead->y = random(25);
sHead->next = NULL;
gotoxy(sHead->x,sHead->y);
cout<<'@';
}
void startGame(Snake *sHead) {//按键控制
int key = 72;
while(1) {
while(kbhit())
key = getch();//有按键输入时,结束循环,即蛇头换方向,因方向键有两个值,所以套一个while,否则会延迟两倍
switch(key) {
case 72: {//上
snakeRun(key);
break;
}
case 80: {//下
snakeRun(key);
break;
}
case 75: {//左
snakeRun(key);
break;
}
case 77: {//右
snakeRun(key);
break;
}
}
Sleep(200); //进程睡眠,控制蛇移动的速度
}
}
void snakeRun(int key) {
if(key == 72) {
//新建节点,让新建的节点等于蛇头前面的坐标,然后再用头指针指向新建节点
Snake *snake = new Snake;
snake->x = sHead->x;
snake->y = sHead->y-1;
snake->next = sHead;
sHead = snake;
if(!(food.x == snake->x && food.y == snake->y)) deleteTail(sHead);//删除尾巴
else {
food.x = random(25)*2;
food.y = random(25);
gotoxy(food.x,food.y);
cout<<"*";
}
gotoxy(sHead->x,sHead->y);
cout<<'@';
} else if(key == 80) {
Snake *snake = new Snake;
snake->x = sHead->x;
snake->y = sHead->y+1;
snake->next = sHead;
sHead = snake;
if(!(food.x == snake->x && food.y == snake->y)) deleteTail(sHead);
else {
food.x = random(25)*2;
food.y = random(25);
gotoxy(food.x,food.y);
cout<<"*";
}
gotoxy(sHead->x,sHead->y);
cout<<'@';
} else if(key == 75) {
Snake *snake = new Snake;
snake->x = sHead->x-2;
snake->y = sHead->y;
snake->next = sHead;
sHead = snake;
if(!(food.x == snake->x && food.y == snake->y)) deleteTail(sHead);
else {
food.x = random(25)*2;
food.y = random(25);
gotoxy(food.x,food.y);
cout<<"*";
}
gotoxy(sHead->x,sHead->y);
cout<<'@';
} else if(key == 77) {
Snake *snake = new Snake;
snake->x = sHead->x+2;
snake->y = sHead->y;
snake->next = sHead;
sHead = snake;
if(!(food.x == snake->x && food.y == snake->y)) deleteTail(sHead);
else {
food.x = random(25)*2;
food.y = random(25);
gotoxy(food.x,food.y);
cout<<"*";
}
gotoxy(sHead->x,sHead->y);
cout<<'@';
}
}
void deleteTail(Snake *sHead) {//删除尾巴
Snake *p = sHead,*temp = NULL;
while(p->next != NULL) {
if(p->next->next == NULL) {
temp = p;
}
p = p->next;
}
gotoxy(p->x,p->y);//删除尾巴后,把之前的尾巴打印成空格
cout<<' ';
delete p;
p = NULL;
temp->next = NULL;
}
缺少的功能有
- 撞墙死亡
- 碰到自己死亡
- 回头死亡
有兴趣的可以自己加,本文主要是把能动能吃食物的贪吃蛇做出来。