简介
大学生活闲的蛋疼没事做写出来的小游戏。
功能
- 控制蛇的上下左右移动;
- 蛇触碰到自己的身体后会触发游戏结束;
- 蛇每吃到一个食物(“F”)积分(“SCORE”)增加200;
- 蛇吃到一定的食物后身体长度会增加。
环境
推荐使用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);
}