在经过了一段时间的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;
}
当然,由于时间的缘故,很多有趣的想法我还并没有实现,比如加入特殊果实触发的彩蛋模式等等......这些都是后话了。
虽然我关于代码的分享频率降低了,但是这并不代表我没有提升,相信刷题对于我而言也不失为另一种磨练。学习编程的所有人,我们共勉!