C++ 面向对象控制台贪吃蛇思路代码

总体思路是不断维护一个二维字符数组,不断更新二维字符串数组,并不断清屏,显示到控制台上

主函数

#include <iostream>
#include <ctime>
#include <Windows.h>
#include <conio.h>
#include "BackGround.h"
#include "Food.h"
#include "Snake.h"

int main()
{
	srand(unsigned int(time(NULL)));
	bool isDead = false;
	BackGround bg;
	bg.initBackGround();
	Food food(bg);
	Snake snake(bg,food);
	snake.initSnake();
	food.setFood();
	bg.DrawBackGround();
	char preKey = NULL;
	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 = preKey;
				else if (key == snake.RIGHT && preKey == snake.LEFT)
					key = preKey;
				else if (key == snake.UP && preKey == snake.DOWN)
					key = preKey;
				else if (key == snake.DOWN && preKey == snake.UP)
					key = preKey;
				else {
					preKey = key;
				}

				if (snake.move(key)) {
					system("cls");
					bg.DrawBackGround();
					Sleep(300);
				}
				else {
					isDead = true;
					break;
				}
				
			}
			
			else {
				key = preKey;

			}
			
		} while (!_kbhit());
		
	}
}

BackGround.h

可以将ROW和COL设为静态变量

#pragma once
class BackGround
{
public:
	enum {
		ROW = 26,
	    COL = 26
	};
	BackGround()  {};
	~BackGround() {};
	void initBackGround();
	void DrawBackGround();
	void setBackGround(int x, int y, char c);
	char getBackGround(int x, int y);


private:
	char gameArray[ROW][COL];
};

 BackGround.cpp

#include "BackGround.h"
#include <iostream>

void BackGround::initBackGround() {
	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 BackGround::DrawBackGround()
{
	for (int i = 0; i < ROW; i++) {
		for (int j = 0; j < COL; j++) {
			std::cout << gameArray[i][j] << " ";
		}
		if ( i == 5)
			std::cout << "create by XieYang";
		if (i == 6) 
			std::cout << "a : left";
		if (i == 7) 
			std::cout << "d : left";
		if (i == 8)
			std::cout << "w : top";
		if (i == 9)
			std::cout << "s : buttom";

		std::cout << std::endl;

	}
}

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

char BackGround::getBackGround(int x, int y)
{
	return gameArray[x][y];
}

因为food类也需要使用背景,所以使用委托的设计方法,放一个对象的引用(或指针)

food.h

#pragma once
#include <iostream>
#include "BackGround.h"

class Food
{
private:
	BackGround &bg;

public:
	Food(BackGround &bg_);
	~Food();
	void setFood();
	int foodX;
	int foodY;
	
};

food.cpp

#include "Food.h"


Food::Food(BackGround &bg_):bg(bg_)
{

}


Food::~Food()
{
}

void Food::setFood()
{
	while (true) {
		foodX = rand() % (BackGround::ROW - 2) + 1;
		foodY = rand() % (BackGround::COL - 2) + 1;
		if (bg.getBackGround(foodX, foodY) == ' ') {
			bg.setBackGround(foodX, foodY, '#');
			break;
		}
			
	}
	
	
}

蛇的实现是用一个链表实现的,Snake.h,蛇的类的设计同样采用委托的方法,传入BackGround和Food类的引用。

#include "Food.h"
class Snake
{
private:

	

	struct Point {
		int x;
		int y;
		Point* next;
		Point(int x_,int y_):x(x_),y(y_),next(nullptr){}
	};

	Point* pHead;
	BackGround & bg;
	Food & food;


public:
	enum { UP = 'w', DOWN = 's', LEFT = 'a', RIGHT = 'd' };
	Snake(BackGround &bg_, Food & food);
	~Snake();
	void initSnake();
	void destroyPoint();
	void addPoint(int x,int y);
	void delPoint();
	bool move(char key);
};

蛇的移动只是坐标的变化,注意,这里坐标的变化只是改变蛇头,即新添加一个节点到蛇头,如果吃到食物,就不变,如果没有吃到,那么就删除蛇尾,那么就涉及到链表的基本操作。另外,为了规则的方便,还可以维护一个蛇头方向的变量

#include "Snake.h"


Snake::Snake(BackGround &bg_, Food &food_): bg(bg_),pHead(nullptr),food(food_)
{
	
}


Snake::~Snake()
{
	Point* pCur = pHead;
	while (pHead) {
		pCur = pHead->next;
		delete pHead;
		pHead = pCur;
	}
}

void Snake::initSnake()
{
	destroyPoint();
	addPoint(5, 3);
	addPoint(5, 4);
	addPoint(5, 5);
}

void Snake::destroyPoint()
{
	Point* pCur = pHead;
	while (pHead) {
		pCur = pHead->next;
		delete pHead;
		pHead = pCur;
	}
}

void Snake::addPoint(int x, int y)
{
	Point* newPoint = new Point(x, y);

	if (pHead != nullptr) {
		bg.setBackGround(pHead->x, pHead->y, '=');
	}

	newPoint->next = pHead;

	pHead = newPoint;
	bg.setBackGround(pHead->x, pHead->y, '@');
}

void Snake::delPoint()
{
	if (pHead == nullptr || pHead->next == nullptr)
		return;

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

	while (pCur->next) {
		pPre = pPre->next;
		pCur = pCur->next;
	}

	bg.setBackGround(pCur->x, pCur->y, ' ');
	delete pCur;
	pCur = nullptr;
	pPre->next = nullptr;

}

bool Snake::move(char key)
{
	int x = pHead->x;
	int y = pHead->y;

	switch (key)
	{
	case UP:
		x--;
		break;
	case DOWN:
		x++;
		break;
	case LEFT:
		y--;
		break;
	case RIGHT:
		y++;
		break;
	default:
		return true;
		break;
	}

	if (bg.getBackGround(x, y) == '*' || bg.getBackGround(x, y) == '=')
		return false;

	if (bg.getBackGround(x, y) == '#') {
		addPoint(x, y);
		food.setFood();
	}
	else {
		addPoint(x,y);
		delPoint();
	}

	return true;

}

 

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的C++面向对象贪吃蛇游戏的完整代码: ```cpp #include <iostream> #include <vector> #include <cstdlib> #include <ctime> #include <conio.h> using namespace std; class Snake { public: vector<pair<int, int>> body; int length; int direction; Snake(int x, int y, int len, int dir) { length = len; direction = dir; for (int i = 0; i < len; i++) { body.push_back(make_pair(x - i, y)); } } void move() { pair<int, int> head = body[0]; switch (direction) { case 0: // Up head.second--; break; case 1: // Down head.second++; break; case 2: // Left head.first--; break; case 3: // Right head.first++; break; default: break; } body.insert(body.begin(), head); body.pop_back(); } bool is_dead(int width, int height) { pair<int, int> head = body[0]; if (head.first < 0 || head.first >= width || head.second < 0 || head.second >= height) { return true; } for (int i = 1; i < body.size(); i++) { if (head == body[i]) { return true; } } return false; } void eat() { pair<int, int> head = body[0]; switch (direction) { case 0: // Up head.second--; break; case 1: // Down head.second++; break; case 2: // Left head.first--; break; case 3: // Right head.first++; break; default: break; } body.insert(body.begin(), head); length++; } }; class Food { public: pair<int, int> position; Food() { position = make_pair(0, 0); } void generate(int width, int height) { srand(time(NULL)); position.first = rand() % width; position.second = rand() % height; } }; class Game { public: int width; int height; Snake snake; Food food; Game(int w, int h) { width = w; height = h; snake = Snake(width / 2, height / 2, 3, 3); food = Food(); } void init() { snake = Snake(width / 2, height / 2, 3, 3); food.generate(width, height); } void run() { char key = ' '; while (key != 'q') { system("cls"); // Draw the map for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { if (i == 0 || i == height - 1 || j == 0 || j == width - 1) { cout << "*"; } else if (snake.body[0] == make_pair(j, i)) { cout << "O"; } else if (food.position == make_pair(j, i)) { cout << "X"; } else { bool is_body = false; for (int k = 1; k < snake.body.size(); k++) { if (snake.body[k] == make_pair(j, i)) { cout << "o"; is_body = true; break; } } if (!is_body) { cout << " "; } } } cout << endl; } // Handle user input if (_kbhit()) { key = _getch(); switch (key) { case 'w': if (snake.direction != 1) { snake.direction = 0; } break; case 's': if (snake.direction != 0) { snake.direction = 1; } break; case 'a': if (snake.direction != 3) { snake.direction = 2; } break; case 'd': if (snake.direction != 2) { snake.direction = 3; } break; default: break; } } // Move the snake snake.move(); // Check if the snake is dead if (snake.is_dead(width, height)) { cout << "Game over!" << endl; break; } // Check if the snake eats the food if (snake.body[0] == food.position) { snake.eat(); food.generate(width, height); } // Sleep for a while Sleep(100); } } }; int main() { Game game(20, 10); game.init(); game.run(); return 0; } ``` 这个代码实现了一个基本的贪吃蛇游戏,包含了移动、判断死亡、吃到食物等功能。你可以根据需要进一步扩展和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值