贪吃蛇--小白学习C语言一周产出--《C语言基础知识点罗列》--适合新手

游戏功能介绍

/如果各种问题,请各位大神评论区指出/
1.J:蛇移动加速
2. 空格:游戏暂停
3.K:游戏存档(只支持一次存档)
4.自定义地图(使用鼠标)
5.多种功能食物
6.背景音乐与音效
7.蛇的多级速度
8.固定障碍物
9.esc返回游戏大厅
10.简单的积分功能
####### 使用的VS编辑器###########

应用到的基础知识

函数 链表 指针 结构体 类(这个属于C++)

功能分析

实现

墙模块

经过项目分析,可以得出再墙模块中,需要维护一个二维数组,对整个游戏中的元素进行设置,所以可以声明一个二维数组,char gameArray[][],具体的行数和列数可以定义出一个枚举,比如本游戏中设置的是26行,26列,enum{ROW=26,COL=26};
那么墙模块开发阶段,需要提供得主要接口是 初始化墙initwall,以及打印墙,也就是将二维数组中得内容打印到控制台中,draw方法,当然对外还要提供出一个可以修改二维数组元素的方法以及根据索引获取二维数组元素的方法:getWall,setWall

游戏中的实现元素

游戏中元素分为:墙壁,蛇,事物以及蛇的可行区域和右侧的版本号和游戏玩法提示
墙壁
*号表示,代表一个区域范围,也就是蛇的可移动区域,蛇如果碰到墙壁视为死亡,

分为蛇头,蛇身,蛇头用@符号表示,蛇身用=等号表示,当蛇吃到食物时候,蛇身+1,一意为着长度变长,贪吃蛇可以通过不断地吃食物来增加自己的身体
食物
#井号表示,蛇碰到食物会将食物吃掉
可移动区域
空格 表示,代表蛇可以移动的区域
提示信息
右侧展示,可以显示当前贪吃蛇版本号,制作人员,游戏玩法等提示信息

游戏规则

当运行游戏时候,画面静止不动,可以默认让蛇头超右,游戏中设置w s a d 4个按键分别代表,上,下,左,右,也是用户比较常用的方向按键,当用户输入w或者s或者d时候激活游戏,注意输入a不可以激活,因为蛇不可以180°转弯,因此蛇的移动方向只可以一直向前或者920°旋转
当蛇吃掉食物时候,此时蛇会增加一个身段,另外食物需要重新随机的设置到屏幕上
游戏结束方式有两种:

蛇碰到墙壁为死亡
蛇碰到蛇身子,把自己吃掉也视为死亡
游戏移动
当激活游戏后,也分为两种,一种是死亡,这个是当 蛇头碰到蛇身或者是碰到墙壁两种死亡,这个暂时先不考虑,第二种是正常移动,先分析下正常移动
在正常移动的时候,也分为两种状态

第一种:蛇没吃到食物
这个时候,蛇只是单纯的移动,没吃到食物的时候,蛇会更新蛇头的位置,并且将之前蛇尾巴的位置为空格,也就是表示向前移动

第二种:蛇吃到食物
当吃到食物时,当前的蛇头的位置应该为之前食物的位置,那么蛇尾由于吃到了食物,就还是在原有位置,然后食物再重新分配到一个其他的位置,这个位置不能是蛇,也不能是墙。

游戏截图

在这里插入图片描述
在这里插入图片描述

main()函数中用到了鼠标与键盘控制的函数(鼠标响应)

// _怎么添加鼠标响应.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Windows.h>
void WriteChar(int x, int y, const char* szInfo)
{
    
    
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = {
    
     x * 2,y };
	SetConsoleCursorPosition(hOut, pos);
	printf(szInfo);
}
int main()
{
    
    
	HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
	SetConsoleMode(hIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
	//PINPUT_RECORD p=NULL;
	INPUT_RECORD stcInput;
	DWORD dwSize = 0;
	while (true)
	{
    
    
		ReadConsoleInput(
			hIn,
			&stcInput, //这里应该传什么,传递一个有效的内存区域
			1,
			&dwSize
		);
		//我们判断结构体中的EventType去确定是不是一个鼠标事件
		if (stcInput.EventType ==  MOUSE_EVENT)
		{
    
    
			int nButtonState = stcInput.Event.MouseEvent.dwButtonState;
			if (nButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
			{
    
    
				int x = stcInput.Event.MouseEvent.dwMousePosition.X;
				int y = stcInput.Event.MouseEvent.dwMousePosition.Y;
				WriteChar(x / 2, y, "☆");
			}
		}
	}
}

拿这段代码运行一下,用鼠标在cmd中按住左拖拽一下
---------------------------------------------------------------------------------------我是分割线-------------------------------------------------------------

各个头文件功能简介

//控制台
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "main.h"
#include "Wall.h"    //墙类
#include "Snake.h"   //蛇类
#include "Food.h"    //食物类
#include "Scene.h"   //基类
#include "Hall.h"    //主界面
#include "Game.h"    //功能按键设置类
#include "Editor.h"  //地图编辑与废弃

上代码–(头文件与cpp文件已分开写-----内含注释)

common.h

#ifndef __COMMON_H__
#define __COMMON_H__
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
#define MAX_LINE 1024
#pragma comment(lib,"winmm.lib")
/*
	设置光标位置
*/
static void gotoxy(int x, int y)
{
    
    
	COORD c;
	c.X = x;
	c.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
/******************************************************************************************/
/*
	文字颜色函数
*/
static int color(int c)
{
    
    
	//SetConsoleTextAttribute是API设置控制台窗口字体颜色和背景色的函数
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);        //更改文字颜色
	return 0;
}
#endif

食物类头文件Food.h

#ifndef __FOOD_H__
#define __FOOD_H__
#include "common.h"
#include "Wall.h"
//食物类
class Food
{
    
    
public:
	Food(Wall *tempWall);
	void setFood();
	int foodX;
	int foodY;
	Wall *wall;
};
#endif

Food.cpp

#include "Food.h"
#include <Windows.h>
#include <time.h>
Food::Food(Wall *tempWall) :wall(tempWall)
{
    
    
}
/******************************************************************************************/
void Food::setFood()
{
    
    
	while (true)
	{
    
    
		srand((unsigned)time(NULL));
		foodX = rand() % (Wall::ROW - 2) + 1;
		foodY = rand() % (Wall::COL - 2) + 1;
		//如果随机的位置是蛇头或蛇身,就重新生成随机数
		if (wall->getWall(foodX, foodY) == ' ')
		{
    
    
			int rnd = rand() % 2;
			if (rnd == 0)
			{
    
    
				color(5);
				wall->setWall(foodX, foodY, '#');  //普通食物
				gotoxy(foodY * 2, foodX);
				printf("#");
			}
			else if (rnd == 1)
			{
    
    
				color(5);
				wall->setWall(foodX, foodY, '$');  //使蛇变短食物
				gotoxy(foodY * 2, foodX);
				printf("$");
			}
			else
			{
    
    
				color(5);
				wall->setWall(foodX, foodY, '&');  //加速食物
				gotoxy(foodY * 2, foodX);
				printf("&");
			}
			break;
		}
	}
}

Game.h

#ifndef __GAME_H__
#define __GAME_H__
#include "Wall.h"
#include "Snake.h"
#include "Food.h"
#include "Scene.h"
//游戏功能类
class Game : public Scene
{
    
    
public:
	Game();
	virtual ~Game();
public:
	virtual bool init(bool load);
	//virtual void destroy();
	virtual void draw();
	virtual void keyEventProc(char key, bool down);
	virtual void mouseEventProc(int x, int y);
	void onGameOver();
private:
	bool isDead;
	char curKey;
	char preKey;
	Wall *wall;
	Food *food;
	Snake *snake;
	bool pause;
};
#endif

Game.cpp

#include "Game.h"
#include "main.h"
Game::Game()
{
    
    
	isDead = false;
	pause = false;
	curKey = 0;
	preKey = 0;
	wall = new Wall;
	food = new Food(wall);
	snake = new Snake(wall, food);
}
/******************************************************************************************/
Game::~Game()
{
    
    
}
/******************************************************************************************/
bool Game::init(bool load)
{
    
    
	cleanScreen();
	wall->initWall();
	if (load)
	{
    
    
		wall->loadMap();
	}
	wall->drawWall();
	if (!wall->hasFood())
	{
    
    
		food->setFood();
	}
	if (load)
	{
    
    
		snake->load();
	}
	else
	{
    
    
		snake->InitSnake();
	}
	PlaySound(NULL, NULL, NULL);
	return true;
}
/******************************************************************************************/
//void Game::destroy()
//{
    
    
//}
/******************************************************************************************/
void Game::draw()
{
    
    
	//判断如果是第一次按了,左键,才不能激活游戏
    //判断上一次移动方向
	if (preKey == 0 )
	{
    
    
		return;
	}
	if (curKey == 0)
	{
    
    
		return;
	}
	if (isDead)
	{
    
    
		return;
	}
	if (pause)
	{
    
    
		return;
	}
	if (snake->move(curKey) == true)
	{
    
    
		gotoxy(0, Wall::ROW);
		printf("得分:%d分", snake->getScore());
		Sleep(snake->getSleepTime());
	}
	else
	{
    
    
		isDead = true;
		onGameOver();
	}
}
/******************************************************************************************/
void Game::keyEventProc(char key, bool down)
{
    
    
	if (key == 106) //j加速
	{
    
    
		if (down)
		{
    
    
			snake->setSpeedUp(true);
		}
		else
		{
    
    
			snake->setSpeedUp(false);
		}			
	}
	if (!down)
	{
    
    
		return;
	}
	if (key == Snake::UP || key == Snake::DOWN || key == Snake::LEFT || key == Snake::RIGHT)
	{
    
    
		//判断本次按键是否与上次冲突
		if ((key == Snake::LEFT && preKey == Snake::RIGHT) ||
			(key == Snake::RIGHT && preKey == Snake::LEFT) ||
			(key == Snake::UP && preKey == Snake::DOWN) ||
			(key == Snake::DOWN && preKey == Snake::UP)
			)
		{
    
    
			curKey = preKey;
		}
		else
		{
    
    
			curKey = key;
			preKey = curKey; //不是冲突按键,可以更新按键
		}
	}
	else
	{
    
    
		curKey = preKey;   //强制将错误按键变为上一次移动的方向
	}
	if (key == 27)  //esc
	{
    
    
		enterScene(SCENE_TYPE_HALL, false);
		return;
	}
	if (key == 32)  //空格/暂停
	{
    
    
		if (pause)
		{
    
    
			pause = false;
		}
		else
		{
    
    
			pause = true;
		}
	}
	if (key == 107)  //k存档
	{
    
    
		wall->saveMap();
		snake->save();
	}
}
/******************************************************************************************/
void Game::mouseEventProc(int x, int y)
{
    
    
}
/******************************************************************************************/
void Game::onGameOver()
{
    
    
	cleanScreen();
	wall->drawWall();
	gotoxy(0, Wall::ROW + 1);
	printf("GAME OVER\n");
}

Hall.h

#ifndef __HALL_H__
#define __HALL_H__
#include "Scene.h"
class Hall : public Scene
{
    
    
public:
	Hall();
	virtual ~Hall();
public:
	virtual bool init(bool load);
	//virtual void destroy();
	virtual void keyEventProc(char key, bool down);
	virtual void mouseEventProc(int x, int y);
	void printSnake();
	void welcomeToGame();
	void explation();
	void openMap();
};
#endif

Hall.cpp

#include "Hall.h"
#include "main.h"
Hall::Hall()
{
    
    
}
/******************************************************************************************/
Hall::~Hall()
{
    
    
}
/******************************************************************************************/
bool Hall::init(bool load)
{
    
    
	cleanScreen();
	printSnake();
	welcomeToGame();
	PlaySound("sound/bgm_server.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
	return true;
}
/******************************************************************************************/
//void Hall::destroy()
//{
    
    
//}
/******************************************************************************************/
void Hall::keyEventProc(char key, bool down)
{
    
    
	if (!down)
	{
    
    
		return;
	}
	switch (key)
	{
    
    
	case 49:					//选择开始游戏
		enterScene(SCENE_TYPE_GAME, false);
		break;
	case 50:					//选择读取进度开始
		enterScene(SCENE_TYPE_GAME, true);
		break;
	case 51:					//选择编辑地图
		enterScene(SCENE_TYPE_EDITOR, false);
		//openMap();
		break;

	default:				//输入非1~3之间的选项
		cleanScreen();		//清屏
		printSnake();
		welcomeToGame();
		break;
	}
}
/******************************************************************************************/
void Hall::mouseEventProc(int x, int y)
{
    
    
}
/******************************************************************************************/
/*
	字符拼成英文图案
*/
void Hall::printSnake()
{
    
    
	color(2);
	printf("                                                                              \n");
	printf("            __________       ___                                              \n");
	printf("           /          \\     / \\ \\    |____      __\\__                     \n");
	printf("          /  ________  \\   / ___ \\  _/ __     | |   /                       \n");
	printf("          |  |      |__|     _/_   |_|  /    [|] |/                           \n");
	printf("          |  |              | | |      /     _|_ \\__/                        \n");
	printf("          \\  \\_______        / \\      |___/        ____                    \n");
	printf("           \\         \\    ____ ____      ____   __ |  |  ___   ______       \n");
	printf("            \\_______  \\   |  |/    \\    /    \\_/ / |  | /  /  /      \\   \n");
	printf("                    \\  \\  |    ___  \\  / ____   /  |  |/  /  /  ____  \\   \n");
	printf("          __        |  |  |   /   \\  \\ | |  |  /   |     /  |  /____\\  |   \n");
	printf("         \\  \\_______|  |  |  |    |  | | |__|  |   |     \\  |  ________/   \n");
	printf("          \\            /  |  |    |  |  \\       \\  |  |\\  \\  \\  \\____  \n");
	printf("           \\__________/   |__|    |__|   \\___/\\__\\ |__| \\__\\  \\______/ \n");
}
/******************************************************************************************/
/*
	开始界面
*/
void Hall::welcomeToGame()
{
    
    
	int n;
	int i, j = 1;
	gotoxy(34, 15);
	color(11);
	printf("贪 吃 蛇 游 戏");
	color(14);          			//黄色边框
	for (i = 17; i <= 23; i++)   	//输出上下边框┅
	{
    
    
		for (j = 16; j <= 68; j++)  //输出左右边框┇
		{
    
    
			gotoxy(j, i);
			if (i == 17 || i == 23)
			{
    
    
				printf("-");
			}
			else if (j == 16 || j == 68)
			{
    
    
				printf("|");
			}
		}
	}
	color(10);
	gotoxy(26, 19);
	printf("1.纯净模式");
	gotoxy(46, 19);
	printf("2.DIY与进度读取");
	gotoxy(26, 21);
	printf("3.DIY障碍物");
	gotoxy(46, 21);
	printf("祝天天好心情O(∩_∩)O");
	gotoxy(10000, 10000);
}
/******************************************************************************************/
/*
	鼠标编辑地图
*/
void Hall::explation()
{
    
    
	//int i, j = 1;
	//system("cls");
	//color(15);
	//gotoxy(44, 3);
	//printf("游戏说明");
	//color(2);
	//for (i = 6; i <= 22; i++)   //输出上下边框===
	//{
    
    
	//	for (j = 20; j <= 76; j++)  //输出左右边框||
	//	{
    
    
	//		gotoxy(j, i);
	//		if (i == 6 || i == 22) printf("=");
	//		else if (j == 20 || j == 75) printf("||");
	//	}
	//}
	//color(3);
	//gotoxy(30, 8);
	//printf("tip1: 不能撞墙,不能咬到自己");
	//color(10);
	//gotoxy(30, 11);
	//printf("tip2: 用w.a.s.d分别控制蛇的移动");
	//color(14);
	//gotoxy(30, 14);
	//printf("tip3: 按空格键暂停游戏,再按空格键继续");
	//color(11);
	//gotoxy(30, 17);
	//printf("tip4: 按ESC键退出游戏返回大厅");


}
/******************************************************************************************/
void Hall::openMap()
{
    
    
	ShellExecute(NULL, TEXT("open"), "notepad.exe", "save/default.map", TEXT(""), SW_SHOWNORMAL);
}
/******************************************************************************************/

main.h

#ifndef __MAIN_H__
#define __MAIN_H__
enum Scene_Type
{
    
    
	SCENE_TYPE_HALL = 0,
	SCENE_TYPE_GAME ,
	SCENE_TYPE_EDITOR ,
};
void cleanScreen();
void enterScene(Scene_Type type, bool load);
#endif

main.cpp

//控制台
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "main.h"
#include "Wall.h"    //墙类
#include "Snake.h"   //蛇类
#include "Food.h"    //食物类
#include "Scene.h"   //基类
#include "Hall.h"    //主界面
#include "Game.h"    //功能按键设置类
#include "Editor.h"  //地图编辑与废弃
Scene *scene;
HANDLE hStdin;
int init();
void keyEventProc(char key, bool down);
void mouseEventProc(int x, int y);
/******************************************************************************************/
int main(const char* user) 
{
    
    
	keybd_event(VK_SHIFT,0,0,0);                             //自动切换英文
	Sleep(100);
	keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);

	hStdin = GetStdHandle(STD_INPUT_HANDLE);          //句柄控制
	INPUT_RECORD stcRecord[128] = {
    
     0 };
	DWORD dwRead = 0;
	SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);   //获取操作

	init();

	while (1)
	{
    
    
		GetNumberOfConsoleInputEvents(hStdin, &dwRead);
		if (dwRead > 0)
		{
    
    
			ReadConsoleInput(hStdin, &stcRecord[0], 128, &dwRead);     //获取数据
			for (int i = 0; i < dwRead; i++)
			{
    
    
				if (stcRecord[i].EventType == KEY_EVENT)
				{
    
    
					keyEventProc(stcRecord[i].Event.KeyEvent.uChar.AsciiChar, stcRecord[i].Event.KeyEvent.bKeyDown);
				}
				else if (stcRecord[i].EventType == MOUSE_EVENT)
				{
    
    
					if (stcRecord[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED 
						&& stcRecord[i].Event.MouseEvent.dwEventFlags != MOUSE_MOVED)
					{
    
    
						mouseEventProc(stcRecord[i].Event.MouseEvent.dwMousePosition.Y, stcRecord[i].Event.MouseEvent.dwMousePosition.X);
					}
				}
			}			
		}
		if (scene)
		{
    
    
			scene->draw();
		}
		Sleep(50);
	}
	return 0;
}
/******************************************************************************************/
int init()
{
    
    
	scene = NULL;
	enterScene(SCENE_TYPE_HALL, false);	
	return 1;
}
/******************************************************************************************/
void enterScene(Scene_Type type, bool load)
{
    
    
	if (scene)
	{
    
    
		scene->destroy();
		//delete scene;
	}
	if (type == SCENE_TYPE_HALL)
	{
    
    
		scene = new Hall;
		scene->init(load);
	}
	else if (type == SCENE_TYPE_GAME)
	{
    
    
		scene = new Game;
		scene->init(load);
	}
	else if (type == SCENE_TYPE_EDITOR)
	{
    
    
		scene = new Editor;
		scene->init(load);
	}
}
/******************************************************************************************/
void keyEventProc(char key, bool down)
{
    
    
	if (scene)
	{
    
    
		scene->keyEventProc(key, down);
	}
}
/******************************************************************************************/
void mouseEventProc(int x, int y)
{
    
    
	if (scene)
	{
    
    
		scene->mouseEventProc(x, y);
	}
}

void cleanScreen()
{
    
    
	system("cls");
	SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
}

Scene.h

#ifndef __SCENE_H__
#define __SCENE_H__
#include "common.h"
//GAME与HALL的基类
class Scene
{
    
    
public:
	Scene();
	virtual ~Scene();
public:
	virtual bool init(bool load);
	virtual void destroy();
	virtual void draw();
	virtual void keyEventProc(char key, bool down);
	virtual void mouseEventProc(int x, int y);
};
#endif

Scene.cpp

#include "Scene.h"
#include "main.h"
Scene::Scene()
{
    
    
}
/******************************************************************************************/
Scene::~Scene()
{
    
    
}
/******************************************************************************************/
bool Scene::init(bool load)
{
    
    
	return false;
}
/******************************************************************************************/
void Scene::destroy()
{
    
    
	cleanScreen();
	gotoxy(0, 0);
}
/******************************************************************************************/
void Scene::draw()
{
    
    
}
/******************************************************************************************/
void Scene::keyEventProc(char key, bool down)
{
    
    
}
/******************************************************************************************/
void Scene::mouseEventProc(int x, int y)
{
    
    
}

Snake.h

#ifndef __SNAKE_H__
#define __SNAKE_H__
#include "common.h"
#include "Wall.h"
#include "Food.h"
class Snake
{
    
    
public:
	Snake(Wall *tempWall, Food* food);
	enum
	{
    
    
		UP = 'w',
		DOWN = 's',
		LEFT = 'a',
		RIGHT = 'd'
	};
	struct Point
	{
    
    
		//数据域
		int x;
		int y;

		//指针域
		Point *next;
	};
	//初始化结点
	void InitSnake();
	//销毁结点
	void destroyPoint();
	//添加结点
	void addPoint(int x, int y);
	//移动时删除结点
	void delPoint();
	//移动操作
	//返回值代表是否成功
	bool move(char key);
	//设定难度
	//获取刷屏时间
	int getSleepTime();
	//获取蛇的身段
	int countList();
	//获取分数
	int getScore();
	//加速
	void setSpeedUp(bool speedUp);
	void load();
	void save();
private:
	Point *pHead;
	Wall *wall;
	Food *food;
	bool isRool; //循环的标识
	int sleepTime;
	float speedUp;   //加速速度
	bool bSpeedUp;  //加速标志
};
#endif

Snake.cpp

#include "Snake.h"
#include "Wall.h"
#include <Windows.h>
Snake::Snake(Wall *tempWall, Food* tempFood) : wall(tempWall), food(tempFood)
{
    
    
	pHead = NULL;
	isRool = false;
	sleepTime = 300;
	speedUp = 0.5f;
	bSpeedUp = false;
}
/******************************************************************************************/
void Snake::destroyPoint()
{
    
    
	Point * pCur = pHead;
	while (pHead != NULL)
	{
    
    
		pCur = pHead->next;
		delete pHead;
		pHead = pCur;
	}
}
/******************************************************************************************/
void Snake::addPoint(int x, int y)
{
    
    
	//创建新结点
	Point * newpoint = new Point;
	newpoint->x = x;
	newpoint->y = y;
	newpoint->next = NULL;
	//如果原来头不为空,改为身子
	if (pHead != NULL)
	{
    
    
		color(3);
		wall->setWall(pHead->x, pHead->y, '=');
		gotoxy(pHead->y * 2, pHead->x);
		printf("=");
	}
	color(4);
	newpoint->next = pHead;
	pHead = newpoint;//更新头部
	wall->setWall(pHead->x, pHead->y, '@');
	gotoxy(pHead->y * 2, pHead->x);
	printf("@");
}
/******************************************************************************************/
//初始化坐标
void Snake::InitSnake()
{
    
    
	destroyPoint();
	addPoint(5, 3);
	addPoint(5, 4);
	addPoint(5, 5);
	addPoint(5, 6);
	addPoint(5, 7);
	addPoint(5, 8);
	addPoint(5, 9);
}
/******************************************************************************************/
//移动时删除结点
void Snake::delPoint()
{
    
    
	//三个以上结点 才去做删除操作
	if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL)
	{
    
    
		return;
	}
	//当前结点
	Point *pCur = pHead->next;
	//上一个结点
	Point *pPre = pHead;
	while (pCur && pCur->next != NULL)
	{
    
    
		pPre = pPre->next;
		pCur = pCur->next;
	}
	//删除尾结点
	wall->setWall(pCur->x, pCur->y, ' ');
	gotoxy(pCur->y * 2, pCur->x);
	printf(" ");
	delete pCur;
	pCur = NULL;
	pPre->next = NULL;
}
/******************************************************************************************/
bool Snake::move(char key)
{
    
    
	int x = pHead->x;
	int y = pHead->y;                     /*蛇的移动*/
	switch (key)
	{
    
    
	case UP:
		x--;
		break;
	case DOWN:
		x++;
		break;
	case LEFT:
		y--;
		break;
	case RIGHT:
		y++;
		break;
	default:
		return true;
	}
	//判断 如果下一步碰到的是尾巴,不应该死亡
	Point *pCur = pHead->next;
	//上一个结点
	Point *pPre = pHead;
	while (pCur && pCur->next != NULL)
	{
    
    
		pPre = pPre->next;
		pCur = pCur->next;
	}
	if (pCur->x == x && pCur->y == y)
	{
    
    
		//碰到尾巴的循环
		isRool = true;
	}
	else
	{
    
    
		//判断用户要到达的位置是否成功
		if (wall->getWall(x, y) == '*' || wall->getWall(x, y) == '=')
		{
    
    
			addPoint(x, y);
			delPoint();

			return false;
		}
	}
	//移动成功 分两种
	//吃到食物,未吃到食物
	if (wall->getWall(x, y) == '#')
	{
    
    
		addPoint(x, y);
		//重新设置食物
		food->setFood();
		PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
	}
	else if (wall->getWall(x, y) == '$')
	{
    
    
		addPoint(x, y);
		delPoint();
		delPoint();
		//重新设置食物
		food->setFood();
		PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
	}
	else if (wall->getWall(x, y) == '&')
	{
    
    
		sleepTime -= 30;
		addPoint(x, y);
		//重新设置食物
		food->setFood();
		PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
	}
	//蛇头
	else
	{
    
    
		addPoint(x, y);
		delPoint();
		if (isRool == true)
		{
    
    
			color(4);
			wall->setWall(x, y, '@');
			gotoxy(y * 2, x);
			printf("@");
		}
	}
	return true;
}
/******************************************************************************************/
int Snake::getSleepTime()                        /*蛇长与速度*/
{
    
    
	if (sleepTime < 0)
	{
    
    
		sleepTime = 0;
	}
	int size = countList();
	if (size < 5)
	{
    
    
		sleepTime = 300;
	}
	else if (size >= 5 && size <= 10)
	{
    
    
		sleepTime = 200;
	}
	else if (size >= 10 && size <= 30)
	{
    
    
		sleepTime = 150;
	}
	else if (size >= 30 && size <= 60)
	{
    
    
		sleepTime = 100;
	}
	else if (size >= 60 && size <= 100)
	{
    
    
		sleepTime = 50;
	}
	if (bSpeedUp)
	{
    
    
		sleepTime = speedUp * sleepTime;
	}
	return sleepTime;
}
/******************************************************************************************/
//获得蛇身段
int Snake::countList()
{
    
    
	int size = 0;
	Point * curPoint = pHead;
	while (curPoint != NULL)
	{
    
    
		size++;
		curPoint = curPoint->next;
	}
	return size;
}
/******************************************************************************************/
//分数
int Snake::getScore()
{
    
    
	int size = countList();
	int score = (size - 3) * 100;
	return score;
}
/******************************************************************************************/
//加速
void Snake::setSpeedUp(bool speedUp)
{
    
    
	bSpeedUp = speedUp;
}
/******************************************************************************************/
void Snake::load()            //蛇状态加载
{
    
    
	destroyPoint();
	char buf[MAX_LINE];
	FILE *fp;
	if ((fp = fopen("save/default.snake", "r")) == NULL)
	{
    
    
		perror("fail to read");
		exit(1);
	}
	while (fgets(buf, MAX_LINE, fp) != NULL)
	{
    
    
		int len = strlen(buf);
		buf[len - 1] = '\0';
		len = len - 1;
		int x = 0;
		int y = 0;
		sscanf(buf, "%d,%d", &x, &y);
		addPoint(x, y);
	}
	fclose(fp);
}
/******************************************************************************************/
void Snake::save()              //蛇状态存档
{
    
    
	int count = 0;
	Point *points[2048] = {
    
     0 };

	FILE *fp;
	int len = 0;
	if ((fp = fopen("save/default.snake", "w")) == NULL)
	{
    
    
		perror("fail to read");
		exit(1);
	}
	Point * pCur = pHead;
	while (pCur != NULL)
	{
    
    
		points[count++] = pCur;
		pCur = pCur->next;
	}
	for (int i = count-1; i >= 0; i--)
	{
    
    
		char buf[MAX_LINE] = {
    
     0 };
		sprintf(buf, "%d,%d\n", points[i]->x, points[i]->y);
		fwrite(buf, strlen(buf), 1, fp);
	}
	fclose(fp);
}

Wall.h

#ifndef __WALL_H__
#define __WALL_H__
#include "common.h"
class Wall
{
    
    
public:
	enum
	{
    
    
		ROW = 26, //行数
		COL = 26//列数
	};
	//初始化墙壁
	void initWall();
	//画出墙壁
	void drawWall();
	void loadMap();
	void saveMap();
	//根据索引来设置 二维数组里的内容
	//设置蛇的部分的时候和设置食物要用
	void setWall(int x, int y, char c);
	//根据索引来获取当前位置的符号
	char getWall(int x, int y);
	bool hasFood();
private:
	char gameArray[ROW][COL];
};
#endif

Wall.cpp

#include "Wall.h"
void Wall::initWall() //初始化墙壁,用二维数组
{
    
    
	for (int i = 0; i < ROW; i++)
	{
    
    
		for (int j = 0; j < COL; j++)
		{
    
    
			//放墙壁的地方
			if (i == 0 || j == 0 || i == ROW - 1 || j == COL - 1)
			{
    
    
				color(6);
				gameArray[i][j] = '*';
			}
			else
			{
    
    
				color(3);
				gameArray[i][j] = ' ';
			}
		}
	}
	for (int i = 19; i < 23; i++)
	{
    
    
		gameArray[15][i] = '*'; //地图内障碍物
	}
}
/******************************************************************************************/
void Wall::drawWall()
{
    
    
	for (int i = 0; i < ROW; ++i)
	{
    
    
		for (int j = 0; j < COL; ++j)
		{
    
    
			if (gameArray[i][j] == '*')
			{
    
    
				color(6);
			}
			else if (gameArray[i][j] == '#')
			{
    
    
				color(5);
			}
			else if (gameArray[i][j] == '$')
			{
    
    
				color(5);
			}
			else if (gameArray[i][j] == '&')
			{
    
    
				color(5);
			}

			//画的时候多加一个空格,看起来好看一些
			printf("%c ", gameArray[i][j] );
		}
		printf("\n");
	}
	color(18);
	gotoxy(55, 6);
	printf("j加速");
	color(3);
	gotoxy(55, 8);
	printf("撞到墙与自己会死");
	color(49);
	gotoxy(55, 11);
	printf("w.a.s.d控制方向");
	color(14);
	gotoxy(55, 14);
	printf("#普通/$变短/&加速");
	color(11);
	gotoxy(55, 17);
	printf("空格/暂停");
	color(15);
	gotoxy(55, 20);
	printf("ESC返回大厅");
	color(10);
	gotoxy(55, 22);
	printf("k存档");
	gotoxy(0, Wall::ROW+1);
}
/******************************************************************************************/
void Wall::loadMap()                //地图加载
{
    
    
	char buf[MAX_LINE];             /*缓冲区*/
	FILE *fp;                       /*文件指针*/
	int i = 0, len = 0;             /*行字符个数*/
	if ((fp = fopen("save/default.map", "r")) == NULL)
	{
    
    
		perror("fail to read");
		exit(1);
	}
	while (fgets(buf, MAX_LINE, fp) != NULL)
	{
    
    
		len = strlen(buf);
		buf[len - 1] = '\0';
		len = len - 1;
		if (len > COL)
		{
    
    
			break;
		}
		for (int j = 0; j < len; j++)
		{
    
    
			if ((buf[j]) == '1')
			{
    
    
				gameArray[i][j] = '*';
			}
			else if ((buf[j]) == '2')
			{
    
    
				gameArray[i][j] = '#';
			}
			else if ((buf[j]) == '3')
			{
    
    
				gameArray[i][j] = '$';
			}
			else if ((buf[j]) == '4')
			{
    
    
				gameArray[i][j] = '&';
			}
			else
			{
    
    
				gameArray[i][j] = ' ';
			}
		}		
		i++;
		if (i > ROW)
		{
    
    
			break;
		}
	}
	fclose(fp);
}
/******************************************************************************************/
void Wall::saveMap()                  //地图保存
{
    
    
	char buf[MAX_LINE];              /*缓冲区*/
	FILE *fp;                        /*文件指针*/
	int i = 0, len = 0;              /*行字符个数*/
	if ((fp = fopen("save/default.map", "w")) == NULL)
	{
    
    
		perror("fail to read");
		exit(1);
	}
	for (int i = 0; i < ROW; i++)
	{
    
    
		for (int j = 0; j < COL; j++)
		{
    
    
			if (gameArray[i][j] == '*')
			{
    
    
				fwrite("1", sizeof(char), 1, fp);
			}
			else if (gameArray[i][j] == '#')
			{
    
    
				fwrite("2", sizeof(char), 1, fp);
			}
			else if (gameArray[i][j] == '$')
			{
    
    
				fwrite("3", sizeof(char), 1, fp);
			}
			else if (gameArray[i][j] == '&')
			{
    
    
				fwrite("4", sizeof(char), 1, fp);
			}
			else
			{
    
    
				fwrite("0", sizeof(char), 1, fp);
			}
		}
		fwrite("\n", sizeof(char), 1, fp);
	}
	fclose(fp);
}
/******************************************************************************************/
void Wall::setWall(int x, int y, char c)
{
    
    
	gameArray[x][y] = c;
}
/******************************************************************************************/
char Wall::getWall(int x, int y)
{
    
    
	return gameArray[x][y];
}

bool Wall::hasFood()
{
    
    
	for (int i = 0; i < ROW; i++)
	{
    
    
		for (int j = 0; j < COL; j++)
		{
    
    
			if (gameArray[i][j] == '#')
			{
    
    
				return true;
			}
			else if (gameArray[i][j] == '$')
			{
    
    
				return true; 
			}
			else if (gameArray[i][j] == '&')
			{
    
    
				return true;
			}
		}
	}

	return false;
}

猜你喜欢

转载自blog.csdn.net/qq_29697965/article/details/109297031