我的第一个c++贪吃蛇游戏(控制台版)
首先说明这是我看了别人的文章,编译成功后,写下自己的理解,仅供参考。
原文章为:https://blog.csdn.net/everlasting_20141622/article/details/52252098
贪吃蛇游戏需要有地图,蛇,食物,积分。
1.地图:可以分为四方的墙壁和中间的空地。
2.蛇:控制的主体,分为头部、身体、尾部和前进的方向。
3.食物:随机出现,判断是否和蛇有接触(即是否被吃)。
4.积分:每当食物被吃,积分应该增加并显示。
首先贴出用到的函数。
gotoxy函数,获取括号中x,y的坐标。
void gotoxy(int y, int x) {
COORD pos;
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}
color函数,选择颜色。
void color(int a) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), a);
/*
字
1 深蓝色
2 深绿色
3 深青色
4 深红色
5 深粉色
6 深黄色
7 深白色
8 灰色
9 浅蓝色
10 浅绿色
11 浅青色
12 浅红色
13 浅粉色
14 浅黄色
15 浅白色
背景
1~15 黑色
16~31 深蓝色
32~47 深绿色
48~63 深青色
64~79 深红色
80~95 深粉色
96~111 深黄色
112~127 深白色
128~143 灰色
144~159 浅蓝色
160~175 浅绿色
176~191 浅青色
192~207 浅红色
208~223 浅粉色
224~239 浅黄色
240~255 浅白色
*/
}
那么一步步来制作
1.画地图:
将画地图的过程封装成map_view方法
void map_view()
{
for (int i = 0; i <= 21; i++) //打印地图顶部的边框□,表示边界,不能触碰
{
color(11);
cout << "□";
}
cout << endl; //回车到下一行进行打印
for (int i = 1; i <=20; i++) //从第二行开始打印,到20行为止
{
color(11); //格子的颜色,color函数中,下面展示
cout << "□"; //打印每行的左边第一个格子
for (int j = 1; j <=20; j++) //循环打印每行除第一个和末尾的格子,打印为■,表示空地可以穿过
{
color(10); //换颜色加以和边框区分
cout << "■";
}
color(11); //再换回边框的颜色
cout << "□"<<endl; //打印每行最后一个格子,打印完后换行,知道打印完全部19行
}
for (int i = 0; i <= 21; i++) //打印最后一行
{
color(11);
cout << "□";
}
}
上面的代码使地图打印完毕,接下来进行蛇的编写。
编写一个蛇的结构snake
struct snake
{
int x, y;
};
x,y代表蛇的每一个部分的坐标,通过坐标的改变进行蛇的移动和增加
蛇包括蛇身,头部,尾部。食物位置也需坐标表示,所以也用蛇的结构体
snake s[110], food, tail; //s是蛇的身体的坐标 food是食物坐标 tail是尾部坐标,你要在移动后将它覆盖
int len = 3, face = 4; //len是蛇的初始长度 face是朝向
int speed = 0, Min = 0; //speed是蛇的移动速度(游戏的刷新速度) Min是移动速度上限
int score = 0; //游戏得分
bool eat=true; //判断食物是否被吃的状态
初始化蛇的函数 init_snake
void init_sanke()
{
s[1].x = 10;
s[1].y = 11;
s[2].x = 10;
s[2].y = 10;
s[3].x = 10;
s[3].y = 9;
tail.x = 10;
tail.y = 8;
}
蛇构造好了,接下来是食物和积分的显示,需要显示在主界面上。
while (1) {
Sleep(speed);
if (eat == true) { //吃过食物
srand(unsigned(time(NULL))); //当srand()的参数值固定的时候,rand()获得的数也是固定的,所以一般srand的参数用time(NULL)
food.x = rand() % 20 + 1; //随机生成食物的x,y坐标
food.y = rand() % 20 + 1;
eat = false; //eat的状态变为false
for (int i = 1; i <= len; i++) {
if (s[i].x == food.x && s[i].y == food.y) { //当吃到食物
eat = true;
break;
}
}
if (eat == true) {
continue;
}
}
gotoxy(food.x, food.y * 2); //食物坐标
color(12);
cout << "●"; //打印食物
color(14);
gotoxy(9, 24 * 2); //显示得分坐标
cout << "目前得分:" << score << endl;
color(14);
gotoxy(10, 24 * 2); //显示速度坐标
cout << "当前速度:" << speed << "(越小越快)" << endl;
注意上面的代码里while循环并没有结束,因为还有生成蛇和移动蛇等代码
1.判断蛇是否和自身相撞,不相撞就打印蛇身
for (int i = 1; i <= len; i++) {
if (i != 1 && s[1].x == s[i].x && s[1].y == s[i].y) { //当头与身体相撞
system("cls"); //清除屏幕
putchar(7); //结束后,终端回响
system("cls");
cout << "您最后的得分为:" << score << endl;
system("pause");
return 0;
}
gotoxy(s[i].x, s[i].y * 2);
color(14);
cout << "★"; //★表示蛇身
}
2.刷新窗体
gotoxy(tail.x, tail.y * 2);
color(10);
cout << "■";
gotoxy(0, 0);
color(11);
cout << "□"; //(0,0)处会刷新一个■,需要覆盖掉
3.键盘事件
if (kbhit()) { //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。
char c;
c = getch(); //获取到键盘输入的值
if (c == 'w' && face != 2) { //按下w且朝向不为下
face = 1;
}
if (c == 's' && face != 1) { //按下s且朝向不为上
face = 2;
}
if (c == 'a' && face != 4) { //按下a且朝向不为左
face = 3;
}
if (c == 'd' && face != 3) { //按下a且朝向不为右
face = 4;
}
}
4.生成蛇
snake x; //生成一条蛇
if (face == 1) { //蛇朝上
x.x = s[1].x - 1; //头部往上移动一行,y值不变,x-1为向上
x.y = s[1].y;
}
if (face == 2) { //蛇朝下
x.x = s[1].x + 1; //头部往下移动一行,y值不变,x+1
x.y = s[1].y;
}
if (face == 3) { //蛇朝左
x.x = s[1].x; //头部往左移动一行,x值不变,y-1
x.y = s[1].y - 1;
}
if (face == 4) { //蛇朝右
x.x = s[1].x; //头部往右移动一行,x值不变,y+1
x.y = s[1].y + 1;
}
5.判断是否撞墙和是否接触食物事件
if (s[1].x == food.x && s[1].y == food.y) { //蛇头部触碰到食物
score++; //分数+1
eat = true; //eat为true
len++;
speed -= 5; //速度减少5,刷新速度加快
if (speed < Min)speed = Min; //锁定速度,当为最小速度时不再减小
continue;
}
if (s[1].x > 20) { //当触碰到底部格子时
system("cls");
putchar(7);
break;
}
if (s[1].x < 1) { //当触碰到顶部格子时
system("cls");
putchar(7);
break;
}
if (s[1].y > 20) { //当触碰到右边格子时
system("cls");
putchar(7);
break;
}
if (s[1].y < 1) { //当触碰到左边格子时
system("cls");
putchar(7);
break;
}
6.蛇身向前推进
for (int i = 1; i <= len; i++) { //格子逐个替换,向前推进
swap(x.x, s[i].x); //swap(x,y),交换x,y
swap(x.y, s[i].y);
}
tail.x = x.x;
tail.y = x.y;
上面的6个单独的代码需要放入表示主界面的while循环中,注意结尾再加一个“ } ”结束循环。
循环结束后可以将写入一个返回类型为int的方法中调用,也可以直接写入main中。
main函数体
int main()
{
main_view();
system("cls");
init_sanke();
map_view();
op(); //op为封装了while循环的方法
system("cls");
cout << "您最后的得分为:" << score << endl;
system("pause");
return 0;
}
还得加入头文件和命名空间
#include "stdlib.h"
#include <iostream>
#include<windows.h>
#include<conio.h>
#include<time.h>
using namespace std;