前言
昨天下午在机房闲得无聊,然后就萌生了写一个简单的小游戏的想法。
贪吃蛇算是很多小游戏之间比较简单易懂的一个。码起来也相对简单。所以就选择了贪吃蛇来编。
编完之后发现代买超级无敌短,只有128行,随便敲一个平衡树或树剖就不止130行了。
代码主体
首先我们需要维护贪吃蛇的一下操作:
- 下一秒的贪食蛇的位置在哪里
- 获取按键并且让贪吃蛇转弯
- 打印贪吃蛇的位置
-
操作1
下一秒的贪食蛇的位置在哪里
\color{blue}\texttt{- 操作1 下一秒的贪食蛇的位置在哪里}
- 操作1 下一秒的贪食蛇的位置在哪里
其实这个就是编贪吃蛇的核心操作了。虽然这个实在来说也不是很难。
我们只要记录
n
u
m
[
i
]
[
j
]
num[i][j]
num[i][j]表示位置
(
i
,
j
)
(i,j)
(i,j)还有多少秒蛇就会离开。也就是说,如果
n
u
m
[
i
]
[
j
]
>
0
num[i][j]>0
num[i][j]>0,那么此时贪吃蛇的一部分就位于位置
(
i
,
j
)
(i,j)
(i,j)上,且移动
n
u
m
[
i
]
[
j
]
num[i][j]
num[i][j]步之后贪吃蛇就不会再位于
(
i
,
j
)
(i,j)
(i,j)上了。
所以对于每一次移动,我们就把贪吃蛇即将到达的位置
n
u
m
num
num赋值为贪吃蛇的长度
l
e
n
len
len,然后就把所有大于0的
n
u
m
num
num全部减一。
如果即将到达的位置为食物所在的位置,我们就把所有的大于0的
n
u
m
num
num加一,然后把
l
e
n
len
len也加一,相当于增加了一格的长度。
bool move()
{
int xx=sx+dx[f],yy=sy+dy[f]; //即将到达的位置
if (xx<1 || xx>n || yy<1 || yy>m) return 0; //超界直接退出
if (a[xx][yy]>1) return 0; //访问过这个点 也就是撞到自己
if (xx==tx && yy==ty) //吃到食物
{
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]) a[i][j]++;
len++;
tx=rand()%n+1; ty=rand()%m+1; //随机下一个食物的位置
while (a[tx][ty]) tx=rand()%n+1,ty=rand()%m+1;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]) a[i][j]--;
a[xx][yy]=len; //往前一格
sx=xx; sy=yy;
return 1;
}
-
操作2
获取按键并且让贪吃蛇转弯
\color{blue}\texttt{- 操作2 获取按键并且让贪吃蛇转弯}
- 操作2 获取按键并且让贪吃蛇转弯
这里我们需要用到两个函数
#include <conio.h>
kbhit(); //检测现在输入框内是否有字符
ch=getch(); //直接读取输入框内的字符,不需要回车
这样的话,我们就可以用一个变量 f f f记录贪吃蛇的方向。每次移动前判断输入框内是否有字符,如果有,那么久读取该字符并更新方向。
void press()
{
if (kbhit()) ch=getch(); //读取字符
if (ch=='w' || ch=='W') f=1;
if (ch=='s' || ch=='S') f=2;
if (ch=='a' || ch=='A') f=3;
if (ch=='d' || ch=='D') f=4;
}
-
操作3
打印贪吃蛇的位置
\color{blue}\texttt{- 操作3 打印贪吃蛇的位置}
- 操作3 打印贪吃蛇的位置
这个是最无脑的了。。。
我们之前记录了数组
n
u
m
num
num,那么打印时如果
n
u
m
[
i
]
[
j
]
>
0
num[i][j]>0
num[i][j]>0,那么这个位置就有贪吃蛇。如果这个位置是食物所在的位置,那么就打印食物即可。
注意为了界面美观,每两列之间最好用空格隔开,因为C++每两行之间是有一个间距的。
例如下列两图分别为有空格
/
/
/无空格的贪吃蛇。两图大小均为
15
×
15
15\times 15
15×15,差距是很明显的。
然后大部分内容就搞定了。
注意事项
- 请务必使用英文输入法游玩本小游戏。因为中文输入法的字母C++经常无法读入
- 建议C++窗口背景调成淡黄色(编号 E E E),文字依然是黑色(编号 0 0 0),这样可能看着比较好看?(雾
system("color E0");
- 游戏时可能会看到光标一闪一闪,影响体验。其实C++的光标是可以影藏的。在百度搜索一下就可以找到影藏的程序。例如下面这一段就来源于这里 https://blog.csdn.net/nocomment_84/article/details/53992730
//影藏光标
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible = false;
SetConsoleCursorInfo(handle, &CursorInfo);
代码
// ===================
// from stoorz
// 2019.8.24
// ===================
#include <bits/stdc++.h>
#include <windows.h>
#include <conio.h>
using namespace std;
const int N=110;
const int dx[]={0,-1,1,0,0};
const int dy[]={0,0,0,-1,1};
int n,m,v,f,len,sx,sy,tx,ty,a[N][N];
char ch;
void press()
{
if (_kbhit()) ch=getch();
if (ch=='w' || ch=='W') f=1;
if (ch=='s' || ch=='S') f=2;
if (ch=='a' || ch=='A') f=3;
if (ch=='d' || ch=='D') f=4;
}
bool move()
{
int xx=sx+dx[f],yy=sy+dy[f];
if (xx<1 || xx>n || yy<1 || yy>m) return 0;
if (a[xx][yy]>1) return 0;
if (xx==tx && yy==ty)
{
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]) a[i][j]++;
len++;
tx=rand()%n+1; ty=rand()%m+1;
while (a[tx][ty]) tx=rand()%n+1,ty=rand()%m+1;
}
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
if (a[i][j]) a[i][j]--;
a[xx][yy]=len;
sx=xx; sy=yy;
return 1;
}
void output()
{
putchar('+');
for (int i=1;i<m*2;i++) putchar('-');
putchar('+'); putchar(10);
for (int i=1;i<=n;i++)
{
putchar('|');
for (int j=1;j<=m;j++)
{
if (a[i][j]>0) putchar('o');
else if (i==tx && j==ty) putchar('*');
else putchar(' ');
if (j!=m) putchar(' ');
}
putchar('|'); putchar(10);
}
putchar('+');
for (int i=1;i<m*2;i++) putchar('-');
putchar('+'); putchar(10); putchar(10);
printf("> len = %d \n",len);
}
int main()
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible = false;
SetConsoleCursorInfo(handle, &CursorInfo);
system("color E0");
printf("> 请输入行数以及列数:\n");
scanf("%d%d",&n,&m);
while (n<5 || m<5 || n>40 || m>40)
{
printf("> 行数以及列数的范围必须在5-40之间qwq\n");
printf("> 请输入行数以及列数:\n");
scanf("%d%d",&n,&m);
}
system("cls");
printf("> 请输入速度(1~3):\n");
scanf("%d",&v);
while (v<1 || v>3)
{
printf("> 速度必须在1至3之间!\n");
printf("> 请输入速度:\n");
scanf("%d",&v);
}
if (v==3) v=300;
if (v==2) v=200;
if (v==1) v=100;
printf("> 游戏将在3秒后开始\n"); Sleep(1000);
printf("> 游戏将在2秒后开始\n"); Sleep(1000);
printf("> 游戏将在1秒后开始\n"); Sleep(1000);
printf("> 游戏开始!\n"); Sleep(500);
system("cls");
// 1上 2下 3左 4右
sx=n-1; sy=m/2; f=1; len=2;
a[sx][sy]=2; a[sx+1][sy]=1;
tx=rand()%n+1; ty=rand()%m+1;
while (a[tx][ty]) tx=rand()%n+1,ty=rand()%m+1;
while (1)
{
press();
if (!move()) break;
output();
Sleep(v);
if (len==n*m)
{
printf("\n> 你赢了!!!");
break;
}
system("cls");
}
output();
Sleep(500);
printf("\n> 你死了!\n");
Sleep(500);
printf("> 最终长度为 %d",len);
return 0;
}