当你闲得无聊去编 C++「贪吃蛇」小游戏

前言

昨天下午在机房闲得无聊,然后就萌生了写一个简单的小游戏的想法。
贪吃蛇算是很多小游戏之间比较简单易懂的一个。码起来也相对简单。所以就选择了贪吃蛇来编。
编完之后发现代买超级无敌短,只有128行,随便敲一个平衡树或树剖就不止130行了。


代码主体

首先我们需要维护贪吃蛇的一下操作:

  1. 下一秒的贪食蛇的位置在哪里
  2. 获取按键并且让贪吃蛇转弯
  3. 打印贪吃蛇的位置

-   操作1   下一秒的贪食蛇的位置在哪里 \color{blue}\texttt{- 操作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 获取按键并且让贪吃蛇转弯} 操作获取按键并且让贪吃蛇转弯
这里我们需要用到两个函数

#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 打印贪吃蛇的位置} 操作打印贪吃蛇的位置
这个是最无脑的了。。。
我们之前记录了数组 n u m num num,那么打印时如果 n u m [ i ] [ j ] &gt; 0 num[i][j]&gt;0 num[i][j]>0,那么这个位置就有贪吃蛇。如果这个位置是食物所在的位置,那么就打印食物即可。
注意为了界面美观,每两列之间最好用空格隔开,因为C++每两行之间是有一个间距的。
例如下列两图分别为有空格 / / /无空格的贪吃蛇。两图大小均为 15 × 15 15\times 15 15×15,差距是很明显的。
在这里插入图片描述
在这里插入图片描述

然后大部分内容就搞定了。


注意事项

  • 请务必使用英文输入法游玩本小游戏。因为中文输入法的字母C++经常无法读入
  • 建议C++窗口背景调成淡黄色(编号 E E E),文字依然是黑色(编号 0 0 0),这样可能看着比较好看?(雾
system("color E0"); 
//影藏光标
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;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值