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

本文介绍了使用C语言开发贪吃蛇游戏的过程,包括游戏功能如加速、暂停、存档、自定义地图等,以及应用到的基础知识如函数、链表、指针和结构体。详细讲解了游戏的墙模块、元素实现、规则和接口设计,同时分享了游戏截图和源代码文件结构。
摘要由CSDN通过智能技术生成

游戏功能介绍

/如果各种问题,请各位大神评论区指出/
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
  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值