C++贪吃蛇小游戏

简介
大学生活闲的蛋疼没事做写出来的小游戏。

功能

  1. 控制蛇的上下左右移动;
  2. 蛇触碰到自己的身体后会触发游戏结束;
  3. 蛇每吃到一个食物(“F”)积分(“SCORE”)增加200;
  4. 蛇吃到一定的食物后身体长度会增加。

环境
推荐使用VS2015或以上版本(支持C11或以上)的编译器运行代码。

结构
双向链表

运行效果:
在这里插入图片描述
源码(4个文件)
在这里插入图片描述

Main.cpp

#include"Action.h"
#include<conio.h>
#include<iostream>
using namespace std;

extern Action act;

int main()
{
	while (1)
	{
		int a = 1;
		system("cls");
		act.GetInput(&a);
		//act.GameMenu();
		act.RemoveNotAll();
		//break;
		//act1.getInput();
		//getInput();
	}
}

GetInput.cpp

#include<Windows.h>
#include<conio.h>



void PrintChar(const char * ch, UINT count, COORD coord)
{
	COORD pos;
	pos.X = coord.X;
	pos.Y = coord.Y;
	CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息
	ULONG unuse;
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(h, &bInfo);
	WriteConsoleOutputCharacterA(h, ch, count, pos, &unuse);
}

char getInput()
{
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	int ch; //输入字符串
	COORD coord; //屏幕上的坐标
	CONSOLE_SCREEN_BUFFER_INFO csbi; //控制台屏幕缓冲区信息
	coord.X = 10;
	coord.Y = 10;
	ch = _getch();
	//0x0d表示回车,0XE0表示上下左右等键的键码
	while (ch == 0xE0 || ch == 0x0d)
	{
		GetConsoleScreenBufferInfo(hout, &csbi);
		coord.X = csbi.dwCursorPosition.X; //得到坐标X的值
		coord.Y = csbi.dwCursorPosition.Y; //得到坐标Y的值

										   //如果是回车
		if (ch == 0x0d)
		{
			coord.X = 0;
			coord.Y++;
			SetConsoleCursorPosition(hout, coord);
			break;
		}
		ch = _getch();
		//上
		if (ch == 0x48)
		{
			if (coord.Y != 0)coord.Y--;
			if (coord.Y == 0)coord.Y = 14;
		}
		//下
		else if (ch == 0x50)
		{
			if (coord.Y != 14)coord.Y++;
			else
				coord.Y = 0;
		}
		//左
		else if (ch == 0x4b)
		{
			if (coord.X == 0) { coord.X = 80; };
			if (coord.X != 0) { coord.X--; };

		}
		//右
		else if (ch == 0x4d)
		{
			if (coord.X != 80)coord.X++;
			else
			{
				coord.X = 0;
			}
		}
		SetConsoleCursorPosition(hout, coord);
		PrintChar("*", 1, coord);
		//cout << "*";
		ch = _getch();
	}
	return ch;
}

Action.h

#pragma once
#include <Windows.h>

struct snake
{
	COORD coord;
	snake*Next;
	snake*Prev;
};

class Action
{
public:
	int m_Score = 0;			//分数
	int m_Times = 0;			//循环次数
	int m_FoodAteAmount=0;		//所吃到的食物的数量
	snake *Head = new snake;	//蛇的头坐标
	snake *Tail = new snake;	//蛇的尾坐标
	snake*FoodLine = new snake;
	int EatItself();										//判断是否咬到自己
	char GetInput(int *Switch);								//吸收上下左右按钮
	void PrintChar(const char *ch, UINT count, snake s);			//指定位置上打印字符串ch
	void PrintChar(const char * ch, UINT count, COORD coord);		//指定位置上打印字符串ch
	void RemoveNotAll();									//程序退出时对内存进行清除
	bool SetBodyCoord(int* a);								//判断并增加贪吃蛇的长度
	bool SetBodyCoord2(int* a);								//判断并增加贪吃蛇的长度
	void PrintScore();										//打印分数
	bool Overlap(COORD*p)const;								//判断即将打印的食物坐标是否与蛇重合
	COORD SetFood(COORD* T);								//设置食物的坐标
	Action();
	~Action();
	//bool(*p[2]) (int *a) = { SetBodyCoord ,SetBodyCoord2 };
	void GameMenu();										//入口函数
};

Action.cpp

#include "Action.h"
#include<conio.h>
#include<iostream>
#include<stdlib.h>
using namespace std;

Action act;

void Action::PrintChar(const char  *ch, UINT count, snake s)
{
	COORD pos;
	pos.X = s.coord.X;
	pos.Y = s.coord.Y;
	CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息
	ULONG unuse;
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(h, &bInfo);
	WriteConsoleOutputCharacterA(h, ch, count, pos, &unuse);
}

void Action::PrintChar(const char * ch, UINT count, COORD coord)
{
	COORD pos;
	pos.X = coord.X;
	pos.Y = coord.Y;
	CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息
	ULONG unuse;
	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(h, &bInfo);
	WriteConsoleOutputCharacterA(h, ch, count, pos, &unuse);
}

//void Action::PrintChar(int Score, UINT count, COORD coord)//fail
//{
//	char*ch;
	ultoa(Score, ch, 10);
//	COORD pos;
//	pos.X = coord.X;
//	pos.Y = coord.Y;
//	CONSOLE_SCREEN_BUFFER_INFO bInfo; // 窗口缓冲区信息
//	ULONG unuse;
//	HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
//	GetConsoleScreenBufferInfo(h, &bInfo);
//	WriteConsoleOutputCharacterA(h, ch, sizeof(ch), pos, &unuse);
//
//}

void Action::RemoveNotAll()
{
	int TNum = 0;
	snake *p = Head;
	while (p)
	{
		snake *Del = p;
		p = p->Next;
		if (TNum < 5)
			continue;
		delete Del;
	}
}

bool Action::SetBodyCoord2(int *a)
{
	snake*WillBeTail = NULL;
	snake*TSnake = Tail;
	if (m_FoodAteAmount - *a == 2)
	{
		*a = m_FoodAteAmount;
		FoodLine->Next = new snake;
		FoodLine->Next->Next = nullptr;
		FoodLine->Next->coord = Head->coord;
//		Tail->Next = new snake;
//		Tail->Next->Next = nullptr;
//		Tail->Next->Prev = Tail;
//		Tail->Next->coord = Head->coord;
//		Tail = Tail->Next;
		return true;
	}
	else
		TSnake = Tail;
	while (TSnake->Prev)
	{
		TSnake->coord = TSnake->Prev->coord;
		TSnake = TSnake->Prev;
	}

		//TSnake->Next = Head->Next->Next;
		//Head->Next = TSnake;
		//WillBeTail->Next = nullptr;
		return false;
}

//bool Action::SetBodyCoord2(int *a)
//{
//	snake*WillBeTail = NULL;
//	snake*TSnake = Head;
//	while (TSnake->Next)
//	{
//		WillBeTail = TSnake;
//		TSnake = TSnake->Next;
//	}
//	if (m_FoodAteAmount - *a == 2)
//	{
//		*a = m_FoodAteAmount;
//		TSnake->Next = new snake;
//		TSnake->Next->Next = nullptr;
//		TSnake->Next->coord = Head->coord;
//		return true;
//	}
//	else
//		//TSnake->Next = Head->Next->Next;
//		//Head->Next = TSnake;
//		//WillBeTail->Next = nullptr;
//		return false;
//}

bool Action::SetBodyCoord(int *a)
{
	snake*WillBeTail = NULL;
	snake*TSnake = Head;
	if (m_FoodAteAmount - *a == 2)
	{
		*a = m_FoodAteAmount;
		Tail->Next = new snake;
		Tail->Next->Next = nullptr;
		Tail->Next->Prev = Tail;
		Tail = Tail->Next;
		TSnake = Tail;
		while (TSnake->Prev)
		{
			TSnake->coord = TSnake->Prev->coord;
			TSnake = TSnake->Prev;
		}
		return true;
	}
	TSnake = Tail;
	while (TSnake->Prev)
	{
		TSnake->coord = TSnake->Prev->coord;
		TSnake = TSnake->Prev;
	}
	return false;
}



void Action::PrintScore()
{
	COORD coord = { 0,15 };
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hout, coord);
	//if (m_FoodAteAmount == 0)
	//{
	//	cout << "SCORE:\t" << "0";
	//	return;
	//}
	cout <<"SCORE:\t"<< m_FoodAteAmount*200;
}

COORD Action::SetFood(COORD* T)
{
	while (1)
	{
		T->X = (rand() % 79)+1;
		T->Y = (rand() % 14)+1;
		if (act.Overlap(T))
			continue;
		return *T;

	}
}

bool Action::Overlap(COORD*p)const
{
	snake*T = Head;
	while (T)
	{
		if (p->X == T->coord.X&&p->X == T->coord.Y)
			return true;
		T = T->Next;
	}
	return false;
}


int Action::EatItself()
{
	snake *p;
		p= Head;
	while (p->Next)
	{
		p = p->Next;

		if (p->coord.X == Head->coord.X&&p->coord.Y == Head->coord.Y)
		{
			system("cls");
			COORD a = { 0,15 };
			act.PrintChar("Game over,you eat your itself!!!", sizeof("Game over,you eat youself!!!"), a);
			//act.PrintChar(123456, sizeof(123456), a);
			system("pause"); 
			return 1;
		}
	}
	return 0;
}


char Action::GetInput(int* Switch)
{
	int FoodAteAmountPrev = m_FoodAteAmount;
	int m = 0;//记录循环的次数
	COORD Food = { 100,100 };//先随机申请一个食物的坐标
	CONSOLE_SCREEN_BUFFER_INFO csbi; //控制台屏幕缓冲区信息
	Head->coord.X = 10;
	Head->coord.Y = 10;
	HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);
	int ch; //输入字符串
	ch = _getch();
	while (ch == 0xE0 || ch == 0x0d)//0x0d表示回车,0XE0表示上下左右等键的键码
	{
		GetConsoleScreenBufferInfo(hout, &csbi);
		m++;
		if(*Switch==1)
			act.SetBodyCoord(&FoodAteAmountPrev);
		else
		act.SetBodyCoord2(&FoodAteAmountPrev);
		
		if (ch == 0x0d)//如果是回车
		{
			Head->coord.X = 0;
			Head->coord.Y++;
			SetConsoleCursorPosition(hout, Head->coord);
			break;
		}
		ch = _getch();
		
		if (ch == 0x48||ch=='W')//上
		{
			if (Head->coord.Y != 0)Head->coord.Y--;
			if (Head->coord.Y == 0)Head->coord.Y = 14;
		}
		
		else if (ch == 0x50||ch=='S')//下
		{
			if (Head->coord.Y != 14)Head->coord.Y++;
			else
				Head->coord.Y = 0;
		}
		
		else if (ch == 0x4b||ch=='A')//左
		{
			if (Head->coord.X == 0) { Head->coord.X = 80; };
			if (Head->coord.X != 0) { Head->coord.X--; };

		}
		
		else if (ch == 0x4d||ch=='D')//右
		{
			if (Head->coord.X != 80)Head->coord.X++;
			if (Head->coord.X == 80)Head->coord.X = 0;
		}
		system("cls");

		act.PrintScore();
		if(m==1)//m是循环次数
			Food = Head->coord;//初始化这个食物的坐标
		if (Food.X == Head->coord.X&&Food.Y == Head->coord.Y)
		{
			act.SetFood(&Food);
			if(m!=1)
				m_FoodAteAmount++;
		}
		SetConsoleCursorPosition(hout, Head->coord);
		PrintChar("F", 1, Food);
		PrintChar("0", 1, Head->coord);//打印蛇头
		snake* TSnake = Head->Next;
		while (TSnake)
		{
			PrintChar("*", 1, *TSnake);//打印蛇身
			TSnake = TSnake->Next;
		}
		if (1 != *Switch)
		{
			TSnake = FoodLine;
			while (TSnake)
			{
				PrintChar("s", 1, *TSnake);//打印
				TSnake = TSnake->Next;
			}
		}
			if (act.EatItself())//判断是否撞到自己
				return 0;
		ch = _getch();
	}
	return 0;
}

Action::Action()
{
	FoodLine->Next = nullptr;

	Head->Prev = nullptr;

	Head->Next = new snake;
	Head->Next->Prev = Head;

	Head->Next->Next = new snake;
	Head->Next->Next->Prev = Head->Next;

	Head->Next->Next->Next = Tail;
	Tail->Prev = Head->Next->Next;
	Tail->Next = nullptr;
}


Action::~Action()
{
	act.RemoveNotAll();
}

void Action::GameMenu()
{
	char a[30];
	cout << "asdasd" << endl;
	cin >> a;
	int Switch = atof(a);
		act.GetInput(&Switch);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值