自制C++控制台小游戏—贪吃蛇

个人练习程序,使用Windows.h库简单制作了一个传统的贪吃蛇游戏。

直接复制到Dev-C++中,就可以运行了。

效果如下:

#include <iostream>
#include <windows.h>
#include <conio.h>
#include <cstdio>
#include <ctime>

using std::cout;
using std::cin;

#define MaxWidth 30
#define MaxHeight 30
#define MaxLenght MaxHeight*MaxWidth

enum mapSize
{
	Small=0,
	Middle,
	Big
};
enum deriction
{
	Left=0,
	Right,
	Up,
	Down
};
struct Position
{
	int x;
	int y;
};

void gotoxy(short x,short y)
{
	COORD pos={x,y};
	HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(hout,pos);
}

char getScrChar(short x,short y)
{
	char out[2]={0};
	DWORD num=0;
	HANDLE hout=GetStdHandle(STD_OUTPUT_HANDLE);
	
	COORD cod={x,y};
	ReadConsoleOutputCharacterA(hout,out,1,cod,&num);
	return out[0];
}
class Snake {
		Position pos;
		Position body[MaxLenght];
		int lenght;
		int mlen;
		deriction MoveDerict;
		int mode;
	public:
		Snake(){};
		~Snake(){cout<<"snake deleted";};
		void Init();
		void ModeChoose(int m);
		void MaxlenSet(int &n);
		void Move();
		int Getlen();
		Position getPos(int n);
		void Eat(Position);
		Position getHeadPos();
		bool HitSelf();
};
void Snake::Init()
{
	pos={2,2};
	body[0]={1,1};
	body[1]={2,1};
	body[2]={2,2};
	body[3]={2,3};
	body[4]={3,3};
	lenght=5;
	mlen=5;
	MoveDerict=Right;
	mode=0;
}
void Snake::ModeChoose(int m){mode=m;}
void Snake::MaxlenSet(int &n){mlen=n;}
int Snake::Getlen(){return lenght;}
Position Snake::getPos(int n){return body[n];}
Position Snake::getHeadPos(){Position p=pos;return p;}
bool Snake::HitSelf()
{
	for(int i=0;i<lenght-1;i++){		
		if((body[i].x==pos.x)&&(body[i].y==pos.y)){
			return true;
		}
	}
	return false;
}
void Snake::Move(){
	char mv;
	if(kbhit()){
		mv=getch();
		switch (mv) {
			case 'w':
				if(MoveDerict!=Down){
					MoveDerict=Up;
				}
				break;
			case 's':
				if(MoveDerict!=Up){
				MoveDerict=Down;}
				break;
			case 'a':
				if(MoveDerict!=Right){
				MoveDerict=Left;}
				break;
			case 'd':
				if(MoveDerict!=Left){
				MoveDerict=Right;}
				break;
			default:
				break;
		}
	}
}
void Snake::Eat(Position p)
{
	switch (MoveDerict) {
		case Left:
			if(p.x==(pos.x-1)&&p.y==(pos.y)){	
				pos.x--;
				body[lenght]=pos;
				lenght++;
			}
			else{
				for(int i=0;i<lenght-1;i++){
					body[i]=body[i+1];
				}
				pos.x--;
				body[lenght-1]=pos;				
			}
			break;
		case Right:
			if(p.x==(pos.x+1)&&p.y==pos.y){
				pos.x++;
				body[lenght]=pos;
				lenght++;
			}
			else{
				for(int i=0;i<lenght-1;i++){
					body[i]=body[i+1];
				}
				pos.x++;
				body[lenght-1]=pos;				
			}			
			break;
		case Up:
			if(p.x==pos.x&&p.y==(pos.y-1)){
				pos.y--;
				body[lenght]=pos;
				lenght++;
			}
			else{
				for(int i=0;i<lenght-1;i++){
					body[i]=body[i+1];
				}
				pos.y--;
				body[lenght-1]=pos;				
			}			
			break;
		default:
			if(p.x==pos.x&&p.y==(pos.y+1)){
				pos.y++;
				body[lenght]=pos;
				lenght++;
			}
			else{
				for(int i=0;i<lenght-1;i++){
					body[i]=body[i+1];
				}
				pos.y++;
				body[lenght-1]=pos;				
			}			
			break;
	}
}

class Map {
		int width,height;
		int blankNum;
		mapSize size;
		Position foodPos;
		Snake *snake;
		bool initFirst;
		int mode;
	public:
		Map();
		~Map();
		void Init();
		void Choose();
		void Draw();
		void Scores();
		void FoodMv(int);
		bool LoseCheck();
		int flash();
};
Map::Map()
{
	snake=new Snake();
	Init();
	snake->Init();
}
Map::~Map(){
	delete snake;
	cout<<"Map deleted";
}
void Map::Init()
{
	width=20;
	height=20;
	blankNum=0;
	size=Small;
	foodPos={0,0};	
	initFirst=false;
}
void Map::Choose(){
	
	cout<<"请输入要选择的地图尺寸:"<<"\n";
	cout<<"小型地图:1"<<"\n";
	cout<<"中型地图:2"<<"\n";
	cout<<"大型地图:2"<<"\n";
	int choice=0;
	bool exitLoop=false;
	while(!exitLoop){
		cin>>choice;
		switch (choice) {
			case 1:
				size=Small;
				exitLoop=true;
				break;
			case 2:
				size=Middle;
				exitLoop=true;
				break;
			case 3:
				size=Big;
				exitLoop=true;
				break;
			default:
				cout<<"输出有误请重试!";
				break;
		}
	}
	
	system("cls");
	cout<<"地图尺寸选择为:"<<size<<"\n";
	cout<<"请输入要难度:"<<"\n";
	cout<<"简单:1"<<"\n";
	cout<<"一般:2"<<"\n";
	cout<<"困难:3"<<"\n";
	choice=0;
	exitLoop=false;
		while(!exitLoop){
			cin>>choice;
			switch (choice) {
				case 1:
					mode=3;
					exitLoop=true;
					break;
				case 2:
					mode=2;
					exitLoop=true;
					break;
				case 3:
					mode=1;
					exitLoop=true;
					break;
				default:
					cout<<"输出有误请重试!";
					break;
			}
		}
}
void Map::FoodMv(int lenRecord)
{
	if(lenRecord<snake->Getlen()||!initFirst){
		srand(time(NULL));
		short x,y;
		bool foodputed=false;
		while(!foodputed){
			x=rand()%width+1;
			y=rand()%height+1;
			if(getScrChar(x,y)==' '){
				foodPos.x=x;
				foodPos.y=y;
				foodputed=true;
			}
		}
		initFirst=true;
	}
	gotoxy(foodPos.x,foodPos.y);
	cout<<"0";	
}
void Map::Draw()
{
	//system("cls");
	switch (size) {
		case Small:
			width=20;
			height=15;
			break;
		case Middle:
			width=25;
			height=20;
			break;
		default:
			width=30;
			height=25;
			break;
	}
	blankNum=width*height;
	snake->MaxlenSet(blankNum);
	//SetConsoleOutputCP(437);
	gotoxy(0,1);
	for(int i=0;i<height;i++){
		cout<<"|";
		for(int j=0;j<width;j++){
			//cout<<static_cast<char>(197);
			cout<<" ";
		}
		cout<<"|"<<"\n";
	}
	int lenRecord=snake->Getlen();
	snake->Move();
	snake->Eat(foodPos);	
	for(int k;k<snake->Getlen();k++){
		Position lp=snake->getPos(k);
		gotoxy(lp.x,lp.y);
		cout<<'8';
	}
	FoodMv(lenRecord);
	Scores();
}
void Map::Scores()
{
	gotoxy(0,height+1);
	cout<<"当前分数:"<<snake->Getlen()<<"\n";
	//cout<<"Food位置:"<<foodPos.x<<","<<foodPos.y<<"\n";
	//cout<<"Head 位置:"<<snake->getHeadPos().x<<","<<snake->getHeadPos().y<<"\n";	
}
int Map::flash()
{
	int m;
	m=mode;
	return m;
}
bool Map::LoseCheck()
{
	Position p=snake->getHeadPos();
	gotoxy(0,0);
	//cout<<"kaishi"<<"\n";
	if((p.x<=0||p.x>width)||(p.y<=0||p.y>height)) {
		
		return true;
	}
	else if(snake->HitSelf()){
			return true;
		}
	return false;
}

int main()
{
	//Map *mymap= new Map;
	Map mymap;
	mymap.Choose();
	system("cls");
	while(1){
		mymap.Draw();
		Sleep(100*mymap.flash());
		if(mymap.LoseCheck()){
			break;
		}
	}
	
	gotoxy(0,25+2);
	cout<<"游戏结束"<<"\n";

	//delete mymap;
	return 0;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值