C++控制台循环链表实现贪吃蛇

原创 2015年11月21日 14:46:51

-stdafx.h 为了简化程序定义一些宏和全局变量

#ifndef __STDAFX_H__
#define __STDAFX_H__

// ============上下左右=============
const int UP = 72;
const int DOWN = 80;
const int LEFT = 75;
const int RIGHT = 77;

// ==============宽高===============
#define HEIGHT 20
#define WIDTH 39

// ==============输出===============
#define cout_food std::cout<<"*"
#define cout_snake std::cout<<"■"
#define cout_space std::cout << " "
#define cout_snake_xy(x,y) SnakeUI::gotoXY(x,y);cout_snake
#define cout_food_xy(x,y) SnakeUI::gotoXY(x,y);cout_food
#define cout_space_xy(x,y) SnakeUI::gotoXY(x,y);cout_space

// =============结束?==============
#define OVER false
#define RUN true

#endif


-SnakeUI.h 

主要是初始化UI,初始化蛇,还有生产食物,判断食物和蛇有没有相撞,还有对界面的一些操作

#ifndef __SNAKE_UI_H__
#define __SNAKE_UI_H__

#include <iostream>
#include <Windows.h>
#include "Snake.h"

struct Food {
	int x;
	int y;
};

class SnakeUI {
public:
	static void initUI();
	static void initSnake();
	static void gotoXY(int x, int y);

	static void productFood(Snake& snake);
	static bool meetWithFood(int x, int y);
	
private:
	static Food food;

};


#endif

-SnakeUI.cpp

#include "stdafx.h"
#include "SnakeUI.h"
#include <ctime>
using namespace std;

Food SnakeUI::food = { 0, 0 };

// init UI
void SnakeUI::initUI() {
	cout << "┏";
	for (int i = 1; i < WIDTH; ++i) cout << "━"; 
	cout << "┓";
	gotoXY(0, HEIGHT);
	cout << "┗";
	for (int i = 1; i < WIDTH; ++i) cout << "━"; 
	cout << "┛";
	for (int y = 1; y < HEIGHT; ++y) {
		gotoXY(0, y); cout << "┃";
		gotoXY(WIDTH, y); cout << "┃";
	}
}

// init snake: three points
void SnakeUI::initSnake() {
	gotoXY(2, 10); cout_snake;
	gotoXY(3, 10); cout_snake;
	gotoXY(4, 10); cout_snake;
}

// goto point(x, y) in console
void SnakeUI::gotoXY(int x, int y) {
	COORD coord = { x * 2, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

// random product food
void SnakeUI::productFood(Snake& snake) {
	srand((unsigned)time(NULL));
	int x, y;	// x from 1 to 38, y from 1 to 19
	bool productOK;
	for (;;) {
		productOK = true;
		x = rand() % 38 + 1;
		y = rand() % 19 + 1;
		// 不和蛇身碰撞1->检查身体和尾部
		for (SnakeNode* sn = snake.last; sn != snake.first; sn = sn->prev) {
			if (sn->x == x && sn->y == y) {
				productOK = false;
				break;
			}
		}
		// 不和蛇身碰撞2->检查头部
		if (x == snake.first->x && y == snake.first->y)
			productOK = false;

		if (productOK)
			break;
	}
	food.x = x; 
	food.y = y;
	cout_food_xy(food.x, food.y);
}

// is snake's head meet with food?
bool SnakeUI::meetWithFood(int x, int y) {
	return (food.x == x && food.y == y);
}

-Snake.h

蛇类,蛇的移动和状态

#ifndef __SNAKE_H__
#define __SNAKE_H__

struct SnakeNode {
	int x;
	int y;
	SnakeNode* prev;
	SnakeNode(int x_t, int y_t){ x = x_t; y = y_t; }
	SnakeNode(){}
};

class Snake {
	friend class SnakeUI;

public:
	Snake();
	~Snake();
	bool snakeMove(char& dir);

private:
	void getKey(char& dir);

private:
	SnakeNode* first;
	SnakeNode* last;
	char state;
};

#endif

-Snake.cpp

#include "stdafx.h"
#include "Snake.h"
#include "SnakeUI.h"

Snake::Snake() {
	// 状态:向右
	state = RIGHT;
	// 创建循环链表
	first = new SnakeNode(4, 10);
	last = new SnakeNode(2, 10);
	last->prev = new SnakeNode(3, 10);
	last->prev->prev = first;
	first->prev = last;
	// UI
	SnakeUI::initSnake();
	SnakeUI::productFood(*this);
}

Snake::~Snake() {
	SnakeNode* tmp = last;
	while (last != last) {
		last = last->prev;
		delete tmp;
		tmp = last;
	}
	delete last;
}

bool Snake::snakeMove(char& dir) {
	int x = first->x;
	int y = first->y;
	getKey(dir);
	// 撞墙->Game Over
	switch (state)
	{
	case UP: --y; if (y == 0) return OVER; break;
	case DOWN: ++y; if (y == HEIGHT) return OVER; break;
	case LEFT: --x; if (x == 0) return OVER; break;
	case RIGHT: ++x; if (x == WIDTH) return OVER; break;
	}

	// 撞到了自己
	SnakeNode* tmp = last;
	for (; tmp != first; tmp = tmp->prev) {
		if (first->x == tmp->x && first->y == tmp->y)
			return OVER;
	}

	// 吃食物
	if (SnakeUI::meetWithFood(x, y)) {
		SnakeNode* newHead = new SnakeNode(x, y);
		first->prev = newHead;
		newHead->prev = last;
		first = newHead;
		cout_snake_xy(x, y);
		SnakeUI::productFood(*this);
	}
	else {
		cout_space_xy(last->x, last->y);
		last->x = x;
		last->y = y;
		first = last;
		last = last->prev;
		cout_snake_xy(x, y);
	}

	return RUN;
}

void Snake::getKey(char& dir) {
	switch (dir)
	{
	case UP: if (state == LEFT || state == RIGHT) state = UP; return;
	case DOWN: if (state == LEFT || state == RIGHT) state = DOWN; return;
	case LEFT: if (state == UP || state == DOWN) state = LEFT; return;
	case RIGHT: if (state == UP || state == DOWN) state = RIGHT; return;
	}
}

-main.cpp

#include "stdafx.h"
#include "SnakeUI.h"
#include "Snake.h"
#include <iostream>
#include <conio.h>
using namespace std;

DWORD WINAPI ThreadProc1(LPVOID lpParameter);

char dir = RIGHT;

int main()
{
	SnakeUI::initUI();
	Snake snake;
	
	CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
	while (snake.snakeMove(dir)) Sleep(100);

	system("pause");
	return 0;
}


DWORD WINAPI ThreadProc1(LPVOID lpParameter)
{
	for (;;) {
		dir = _getch();
	}
	return 1;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

C语言游戏之贪吃蛇--链表实现

早自习时突然想到怎么写贪吃蛇,话不多说,代码如下: 开发环境:vs2015 虽然开始还是出了很多指针问题。。。(很烦C语言指针)调试了很久也大概是可以畅快的玩了。 C语言新手,有很多写得不好的...

C++控制台循环链表实现贪吃蛇

-stdafx.h 为了简化程序定义一些宏和全局变量 #ifndef __STDAFX_H__ #define __STDAFX_H__ // ============上下左右==========...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

贪吃蛇~~C++控制台实现!

刚学完了C语言,便尝试的写了贪吃蛇的代码,但是效果不佳,很多的bug,所以,这个学了C++,便重新的写了这个小游戏,用类来封装!~ 先是头文件: struct Snake { int x, y;...

C++控制台贪吃蛇

软件实训作品, 现放出个人源代码, 供需要的同学参考运行效果 #include #include #include #include #include #include #inc...

贪吃蛇-控制台

本文把游戏区域就行编号,第一行从0到WIDTH-1,…… 到HEIGHT-1 到 WIDTH*HEIGHT-1(二维数组)。并用trace[LEN]数组保存snake移动的轨迹(保存的是数值,数值就能...

C++ 双人贪吃蛇

这篇代码基于博主的“C++ 贪吃蛇基本算法”,加入第二只蛇让他移动并不难,但考虑到要让两只蛇的移动互不干扰那还真是破事真多。博主将“C++ 贪吃蛇基本算法”中的while(1)改成了goto,以用来将...

C++ 贪吃蛇基本算法

博主的思想是将贪吃蛇蛇身的走向储存在二维数组中,只保留两个坐标:蛇头与蛇身,同时利用控制输出光标位置来做到不使用system(“cls”)来移动蛇身,同时纠正了大多数百度的代码的一些问题,比如按反方向...

C++ 贪吃蛇自噬

这篇代码基于博主的“C++ 贪吃蛇基本算法”通过加入另一个二维数组maps以用来储存蛇身的来源,并通过简单的递归算法在蛇自噬时清除蛇的后半部分,并且修复了一些原来没发现的BUG。#include #...

C++ 贪吃蛇穿墙与自定义地图

博主在上一篇的代码中做了一些修改,使得贪吃蛇能够穿过边界并且将地图的长宽都换成了变量,这样既可自定义地图可以做出诺基亚上的战役模式。为了区分没有墙的边界与控制台背景,可以修改地图底色,虽然颜色搭配实在...

C语言控制台贪吃蛇

/* //这个蛇是怎么变长的..... 游戏就是方块和空格的更新 没有墙的地方初始化为0, 有墙的地方初始化为1, 有蛇的地方初始化为2, 食物初始化为3; 所有的操作都在SnakeGroup里面进...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)