贪吃蛇案例

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include "wall.h"
#include "snake.h"
#include "food.h"
#include <ctime>
#include <conio.h>
#include <Windows.h>

void gotoxy(HANDLE hOut, int x, int y)
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut, pos);
}
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量




int main() {

	//添加随机种子
	srand((unsigned int)time(NULL));

	//是否死亡标示
	bool isDead = false;

	char preKey = NULL;

	Wall wall;
	wall.initWall();
	wall.drawWall();

	Food food(wall);
	food.setFood();

	Snake snake(wall, food);
	snake.initSnake();

	gotoxy(hOut, 0, Wall::ROW);
	cout << "得分:" << snake.getScore() << "分" << endl;
	


	//接受用户输入


	while (!isDead)
	{
		char key = _getch();

		//判断 如果是第一次按了 左键 才不能激活游戏
		// 判断 上一次 移动方向
		if (preKey == NULL && key == snake.LEFT)
		{
			continue;
		}

		do
		{
			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))
				{
					key = preKey;
				}
				else
				{
					preKey = key; //不是冲突按键  可以更新按键
				}


				if (snake.move(key) == true)
				{
					移动成功 代码
					//system("cls");
					//wall.drawWall();
					//Sleep(100);

					gotoxy(hOut, 0, Wall::ROW);

					cout << "得分:" << snake.getScore() << "分" << endl;
					Sleep(snake.getSleepTime());
				}
				else
				{
					isDead = true;
					break;
				}
			}
			else
			{
				key = preKey; //强制将错误按键变为 上一次移动的方向
			}


		} while (!_kbhit()); //当没有键盘输入的时候 返回0


	}


	system("pause");
	return EXIT_SUCCESS;
}
#ifndef _WALL_HEAD
#define _WALL_HEAD
//#pragma  once

#include <iostream>
using namespace std;

class Wall
{
public:
	enum {
		ROW = 26,
		COL = 26
	};


	//初始化墙壁
	void initWall();

	//画出墙壁
	void drawWall();

	//根据索引设置 二维数组里的内容
	void setWall(int x, int y, char c);

	//根据索引获取当前位置的符号
	char getWall(int x, int y);

private:
	char gameArray[ROW][COL];
};
#endif
#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)
			{
				gameArray[i][j] = '*';
			}
			else
			{
				gameArray[i][j] = ' ';
			}
		}
	}
}

void Wall::drawWall()
{
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			cout << gameArray[i][j] << " ";
		}
		if (i == 5)
		{
			cout << "create by xx";
		}
		if (i == 6)
		{
			cout << "a : left";
		}
		if (i == 7)
		{
			cout << "d : right";
		}
		if (i == 8)
		{
			cout << "w : up";
		}
		if (i == 9)
		{
			cout << "s : down";
		}
		cout << endl;
	}
}

void Wall::setWall(int x, int y, char c)
{
	gameArray[x][y] = c;
}

char Wall::getWall(int x, int y)
{
	return gameArray[x][y];
}

#pragma  once
#include <iostream>
#include<list>
#include "wall.h"
#include "food.h"
using namespace std;

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;
	//};
	list<pair<int, int>> pHead;
	//初始化蛇
	void initSnake();

	// 销毁节点
	void destroyPoint();

	// 添加节点
	void addPoint(int x, int y);


	// 删除节点
	void delPoint();

	//移动蛇操作
	//返回值代表 移动是否成功
	bool move(char key);

	//设定难度
	//获取刷屏时间
	int getSleepTime();
	//获取蛇身段
	int countList();

	//获取分数
	int getScore();

	//Point* pHead;

	Wall& wall;

	Food& food;

	bool isRool; //判断循环标示
};

#include "snake.h"
#include <windows.h>
void gotoxy1(HANDLE hOut1, int x, int y)  //光标定位
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut1, pos);
}
HANDLE hOut1 = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量

Snake::Snake(Wall& tempWall, Food& tmpFood) : wall(tempWall), food(tmpFood)
{
	//pHead = NULL;
	pHead.clear();
	isRool = false;
}


void Snake::initSnake()
{
	destroyPoint();

	addPoint(5, 3);
	addPoint(5, 4);
	addPoint(5, 5);
}

//销毁所有节点
void Snake::destroyPoint()
{
	/*Point* pCur = pHead;

	while (pHead != NULL)
	{
		pCur = pHead->next;
		delete pHead;

		pHead = pCur;
	}*/
	while (!pHead.empty()) {
		//pair<int, int> p = pHead.front();
		pHead.pop_front();
	}
}

void Snake::addPoint(int x, int y)
{
	创建新节点
	//Point* newPoint = new Point;
	//newPoint->x = x;
	//newPoint->y = y;
	//newPoint->next = NULL;

	/*//如果原来头不为空 改为 身子

	if (pHead != NULL)
	{
		wall.setWall(pHead->x, pHead->y, '=');
		gotoxy1(hOut1, pHead->y * 2, pHead->x);
		cout << "=";
	}*/
	pair<int, int> p;
	if (!pHead.empty()) {
		p = pHead.front();
		wall.setWall(p.first, p.second, '=');
		gotoxy1(hOut1, p.second * 2, p.first);
		cout << "=";
	}
	pHead.push_front(make_pair(x, y));
	p = pHead.front();
	wall.setWall(p.first, p.second, '@');
	gotoxy1(hOut1, p.second * 2, p.first);
	cout << "@";

	//newPoint->next = pHead;
	//pHead = newPoint; //更新头部
	//wall.setWall(pHead->x, pHead->y, '@');
	//gotoxy1(hOut1, pHead->y * 2, pHead->x);
	//cout << "@";

}

//删除节点
void Snake::delPoint()
{
	if (pHead.empty() || pHead.size() == 1) {
		return;
	}
	两个节点以上 才去做删除操作
	//if (pHead == NULL || pHead->next == NULL)
	//{
	//	return;
	//}

	//Point* pCur = pHead->next;
	//Point* pPre = pHead;

	//while (pCur->next != NULL)
	//{
	//	pPre = pPre->next;
	//	pCur = pCur->next;
	//}
	删除尾节点
	pair<int, int> p = pHead.back();
	wall.setWall(p.first, p.second, ' ');
	pHead.pop_back();
	gotoxy1(hOut1, p.second * 2, p.first);
	cout << " ";

	//wall.setWall(pCur->x, pCur->y, ' ');
	//gotoxy1(hOut1, pCur->y * 2, pCur->x);
	//cout << " ";

	//delete pCur;
	//pCur = NULL;
	//pPre->next = NULL;

}

bool Snake::move(char key)
{
	/*int x = pHead->x;
	int y = pHead->y;
	*/
	pair<int, int> p = pHead.front();
	int x = p.first;
	int y = p.second;
	switch (key)
	{
	case UP:
		x--;
		break;
	case DOWN:
		x++;
		break;
	case LEFT:
		y--;
		break;
	case RIGHT:
		y++;
		break;
	default:
		break;
	}

	判断 如果是下一步碰到的是尾巴,不应该死亡
	//Point* pCur = pHead->next;
	//Point* pPre = pHead;

	//while (pCur->next != NULL)
	//{
	//	pPre = pPre->next;
	//	pCur = pCur->next;
	//}
	//if (pCur->x == x && pCur->y == y)
	//{
	//	//碰到尾巴 循环
	//	isRool = true;
	//}
	p = pHead.back();
	if (p.second == y && p.first == x) {
		isRool = true;
	}
	else
	{
		//判断用户到达位置是否成功
		if (wall.getWall(x, y) == '*' || wall.getWall(x, y) == '=')
		{
			addPoint(x, y);
			delPoint();
			system("cls");
			wall.drawWall();
			cout << "得分:" << getScore() << "分" << endl;
			cout << "GAME OVER!!!" << endl;
			return false;
		}
	}

	//移动成功 分两种  
	//吃到食物  未吃到食物
	if (wall.getWall(x, y) == '#')
	{
		addPoint(x, y);

		//重新设置食物
		food.setFood();
	}
	else
	{
		addPoint(x, y);
		delPoint();
		if (isRool == true)
		{
			wall.setWall(x, y, '@');
			gotoxy1(hOut1, 2 * y, x);
			cout << "@";
		}
	}
	return true;
}

int Snake::getSleepTime()
{
	int sleepTime = 0;

	int size = countList();
	if (size < 5)
	{
		sleepTime = 300;
	}
	else if (size >= 5 && size <= 8)
	{
		sleepTime = 200;
	}
	else
	{
		sleepTime = 100;
	}
	return sleepTime;
}

int Snake::countList()
{
	int size = pHead.size();
	/*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;
}
#pragma  once
#include <iostream>
#include "wall.h"
using namespace std;

class Food
{
public:
	Food(Wall& tempWall);
	//设置食物
	void setFood();
	int foodX;
	int foodY;

	Wall& wall;
};

#include "food.h"
#include <windows.h>
void gotoxy2(HANDLE hOut2, int x, int y)
{
	COORD pos;
	pos.X = x;             //横坐标
	pos.Y = y;            //纵坐标
	SetConsoleCursorPosition(hOut2, pos);
}
HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量

Food::Food(Wall& tempWall) : wall(tempWall)
{
}

void Food::setFood()
{
	while (true)
	{
		foodX = rand() % (Wall::ROW - 2) + 1;
		foodY = rand() % (Wall::COL - 2) + 1;

		//如果随机的位置是蛇头或蛇身 就重新生成随机数
		if (wall.getWall(foodX, foodY) == ' ')
		{

			wall.setWall(foodX, foodY, '#');
			gotoxy2(hOut2, foodY * 2, foodX);
			cout << "#";
			break;
		}
	}
}

积累:
(1)void gotoxy2(HANDLE hOut2, int x, int y) { COORD pos; pos.X = x; //横坐标 pos.Y = y; //纵坐标 SetConsoleCursorPosition(hOut2, pos); } HANDLE hOut2 = GetStdHandle(STD_OUTPUT_HANDLE);//定义显示器句柄变量

实现光标定位,在贪吃蛇游戏中,每次更新改变的蛇及食物后让光标定位到改变地方,以实现屏幕刷新的禁止。
(2)kbhit()函数
功能及返回值: 检查当前是否有键盘输入,若有则返回一个非0值,否则返回0。 贪吃蛇中用于判断用户是否输入
(3)list容器使用
简化代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值