学习C++第十周 优化贪吃蛇 形成项目体系

在经过了一段时间的C++语言学习后,或许是由于有关知识点的学习已经逐渐趋于饱和,我感觉到进步速度已经越来越慢了。

为了维持学习的积极性,我开始在各个刷题平台奋战:力扣、洛谷、acwing......在本周我也初次参加了力扣的周赛和双周赛,并且取得了自己比较满意的成绩,以后或许我会分享。

本周我还回顾了以前写过的贪吃蛇程序,正如我之前所说的那样,它是存在许多不足之处的,所以我抽出一点时间对其做出了优化,并且也加入了一些新元素。

本次项目的提升主要有:修改为多文件进行、丰富游戏玩法、游戏互动性增强、画面品质的大幅度优化、加入游戏背景音乐。

以下是我的代码分享。

//gamebody.h
#pragma once

#include<iostream>
#include<stdio.h>
#include<conio.h>// _getch() _khbit() 所在的头文件
#include<cstdlib>
#include<Windows.h>
#include<mmsystem.h>
#include<setjmp.h>
#pragma comment(lib,"winmm.lib")

using namespace std;

//宏定义的常量
#define height 20
#define width 40
#define board 60
#define slow 240
#define middle 200
#define fast 160
#define divil 100

//蛇的结构体 统计蛇的每个坐标数据
struct Snake;


void Game_Menu();//打印菜单
void OutRule();//打印规则
void Init_Game();//游戏初始初始化工作
bool Rgt(char a);//判断蛇的误食
void New_Move();//新的移动方向
void Speed_up();//控制速度
void Flush_food();//刷新果实
void Grow_Alive();//蛇的成长和判断是否死亡
void Print_Helpboard();//打印出属性板
void Game_over();//蛇死亡后工作
void placechange(int x, int y,short col);

//gamebody.cpp
#include"Gamebody.h"

struct Snake {
	int snX[200];
	int snY[200];
}snake;

jmp_buf jump;
int slong = 3;//蛇的长度
int m = 0;
int fx = 0, fy = 0;
char now = 'a';//自动位移的方向
int sp = slow;//图像变化速度 蛇的长度越长 速度越快 此数据越低
int score = 0;//计分
int start = 0;

void Game_Menu()
{
	system("cls");
	placechange(0, 3, 7);
	cout << "      --------------------------------------------" << endl;
	cout << "      |           Welcome to MySnake.            |" << endl;
	cout << "      |     GAME START  ----  Enter any key...   |" << endl;
	cout << "      |      GAME RULE  ----  Input R            |" << endl;
	cout << "      |           QUIT  ----  Input Q            |" << endl;
	cout << "      --------------------------------------------" << endl;
	char t = _getch();
	if (t == 'q' || t == 'Q')
		exit(0);
	else if (t == 'r' || t == 'R')
		OutRule();
	else
		system("cls");
}

void OutRule()
{
	system("cls");
	printf("——贪吃蛇游戏——\n");
	printf("规则如下:\n");
	printf("玩家使用方向键 WASD 操控一条长长的蛇不断吞下豆子,\n同时蛇身随着吞下的豆子不断变长,当蛇头撞到蛇身或障壁时蛇就会死亡。\n");
	printf("本游戏分为四个难度:简单,中等,困难,地狱\n");
	printf("贪吃蛇死亡后,玩家可以选择复活它继续游戏或者重新开始新一轮游戏,不过要注意,地狱难度不能重生!\n");
	printf("Enter any key to return to menu...");
	system("pause");
	Game_Menu();
}

void Init_Game()
{
	sp = 100;
	//蛇的初始化
	{
		snake.snX[0] = height / 2;
		snake.snY[0] = width / 2;
		for (int i = 1; i < slong; i++)
			snake.snX[i] = snake.snX[0] + i;
	}
	placechange(0, 0, 3);
	//初始化地图
	for (int i = 0; i < height; i++)//每列
	{
		for (int j = 0; j < width; j++)
		{
			if (i == 0 || i == height - 1)cout << "#";
			else if (j == 0 || j == width - 1)cout << "#";
			else cout << " ";
		}
		cout << endl;
	}
	Print_Helpboard();
}

void Game_over()
{
	system("cls");
	cout << "Game over." << endl;
	cout << "Enter any key to quit game, input c to continue, or input r to restart." << endl;
	char temp = _getch();
	if (slong < 25 && temp == 'c' || temp == 'C')
	{
		now = 'a';
		longjmp(jump, 1);
	}
	else if (temp == 'r' || temp == 'Q')
	{
		slong = 3;
		now = 'a';
		score = 0;
		sp = slow;
		placechange(0, 0, 7);
		longjmp(jump, 1);
	}
	else
		exit(0);
}

void New_Move()
{
	Sleep(sp);
	while (_kbhit()&&clock()-start>20)
	{
		char a;
		start = clock();
		a = _getch();
		if (Rgt(a) == true)
			now = a;
	}
	// 生成蛇头 清除蛇尾 从而使蛇移动
	if(snake.snY[slong-1]>0&&snake.snX[slong-1]>0)
	{
		placechange(snake.snY[slong - 1], snake.snX[slong - 1],-1); cout << " ";
	}
	snake.snY[slong - 1] = 0;
	snake.snX[slong - 1] = 0;
	//蛇身体各部分坐标相互传递
	for (int k = slong - 1; k > 0; k--)
	{
		snake.snX[k] = snake.snX[k - 1];
		snake.snY[k] = snake.snY[k - 1];
	}
	//重新定义并生成蛇头
	switch (now)
	{
	case 'w':
		snake.snX[0]--; break;
	case 'a':
		snake.snY[0]--; break;
	case 'd':
		snake.snY[0]++; break;
	case 's':
		snake.snX[0]++; break;
	default:
		break;
	}
	placechange(snake.snY[0], snake.snX[0], 10);
	if(slong>24)placechange(snake.snY[0], snake.snX[0], 4);
	cout<<"@";
}

//刷新果实
void Flush_food()
{
	if (m < 1)
	{
		fx = rand() % (height - 2) + 1;
		fy = rand() % (width - 2) + 1;
		m++;	
	}
	placechange(fy, fx, 6);
	if (sp == divil)placechange(fy, fx, 4);
	cout << "$" << endl;
}

//判断玩家的操作是否合法 防止因为反方向操作导致蛇误食自身 游戏强制结束 同时规避玩家输入其他键导致游戏的不可控性 加强程序健壮性
bool Rgt(char a)
{
	if (a == 'a' || a == 's' || a == 'd' || a == 'w')
	{
		if (a == 'a' && now == 'd')return 0;
		if (a == 'd' && now == 'a')return 0;
		if (a == 's' && now == 'w')return 0;
		if (a == 'w' && now == 's')return 0;
		else return 1;
	}
	else return 0;
}

//控制速度函数
void Speed_up()
{
	if (slong <= 8) 
	{
		sp = slow;
		placechange(board+2, 3, 7);
		cout << "slow";
	}
	else if (slong <= 16)
	{
		sp = middle;
		placechange(board, 3, 7);
		cout << "middle";
	}
	else if(slong <= 24) 
	{
		sp = fast;
		placechange(board, 3, 7);
		cout << "  fast";
	}
	else {
		sp = divil;
		placechange(board-12, 3, 4);
		cout << "Welcome to Hell difficulty!";
	}
}

void Grow_Alive()
{
	if (snake.snX[0] == fx && snake.snY[0] == fy)
	{
		m--; slong++; score += 10;
		placechange(board+4, 2, 7);
		cout << score;
		placechange(board+4, 4, 7);
		cout << slong;
	}
	if (snake.snX[0] == 0 || snake.snY[0] == 0 || snake.snX[0] == height - 1 || snake.snY[0] == width - 1)
		Game_over();
	for (int i = 1; i < slong; i++)
	{
		if (snake.snX[0] == snake.snX[i] && snake.snY[0] == snake.snY[i])
			Game_over();
	}

}
//参数表 便于调试
void Print_Helpboard()
{	
	placechange(board-10, 2, 7);
	cout << "|  Score:          |";
	placechange(board-10, 3, 7);
	cout << "|  Speed:          |";
	placechange(board-10, 4, 7);
	cout << "|  蛇长:       0   |";
	placechange(board-10, 15, 7);
	cout << "Production Author :  Ripuka ";
}

void placechange(int x, int y,short col)
{
		COORD p;
		HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
		p.X = x;
		p.Y = y;
		SetConsoleCursorPosition(handle, p);
		if (col >= 0 && col <= 15)
			SetConsoleTextAttribute(handle, col);
		else
			SetConsoleTextAttribute(handle, 7);
}

//main.cpp
#include"gamebody.h"
#include<iostream>

using namespace std;
extern int gamedo;
extern jmp_buf jump;

int main()
{
	srand(time(NULL));
	setjmp(jump);
	Game_Menu();
	Init_Game();
	PlaySound(TEXT("02 Approval desire.wav"), NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
	while (1)
	{
		New_Move();
		Speed_up();
		Grow_Alive();
		Flush_food();
		placechange(0, height, 7);
	}
	return 0;
}

当然,由于时间的缘故,很多有趣的想法我还并没有实现,比如加入特殊果实触发的彩蛋模式等等......这些都是后话了。

虽然我关于代码的分享频率降低了,但是这并不代表我没有提升,相信刷题对于我而言也不失为另一种磨练。学习编程的所有人,我们共勉!

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没啥基础的小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值