```
#include<iostream>
#include<utility>
#include<set>
#include<deque>
#include<Windows.h>
#include <ctime>
#include <stdexcept>
#include<string>
#include<conio.h>
WORD SQUARE_COLOR[7] = { FOREGROUND_RED | FOREGROUND_INTENSITY,
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
FOREGROUND_BLUE | FOREGROUND_INTENSITY,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
};义方向
#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_ESC 27
//边框属性
#define MAPW 30
#define MAPH 20
#define OFFSET_L 2
#define OFFSET_U 2
using namespace std;
class Bitmap;
class Feed;
class Snake;
//获取句柄函数
HANDLE initiate() {
HANDLE hOutput;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
return hOutput;
}
//控制台输出函数
bool textout(HANDLE hOutput, int x, int y, LPTSTR lpszCtring,WORD wColors[], int nColors) {
DWORD cWritten;
BOOL fSuccess;
COORD coord;
coord.X = x;
coord.Y = y;
fSuccess = WriteConsoleOutputCharacter(
hOutput,
lpszCtring,
lstrlen(lpszCtring),
coord,
&cWritten
);
for (;fSuccess && coord.X < lstrlen(lpszCtring) + x;coord.X += nColors) {
fSuccess = WriteConsoleOutputAttribute(
hOutput,
wColors,
nColors,
coord,
&cWritten
);
}
if (!fSuccess)
cout << "error:WriteConsoleOutputCharacter" << endl;
return 0;
}//end
bool textout1(HANDLE hOutput,int x,int y,LPTSTR lpszCtring) {
DWORD cWritten;
BOOL fSuccess;
COORD coord;
coord.X = x;
coord.Y = y;
fSuccess = WriteConsoleOutputCharacter(
hOutput,
lpszCtring,
lstrlen(lpszCtring),
coord,
&cWritten
);
if (!fSuccess)
cout << "error:WriteConsoleOutputCharacter" << endl;
return 0;
}
enum type {
bitmap_type,
feed_type,
snake_type,
none_type,
};
extern HANDLE handle;
//打印游戏界面
template<typename T> void print(T &t, enum type ty) {
LPTSTR lpszText = TEXT("◆") ;
switch (ty) {
case bitmap_type:
lpszText = TEXT("◆");
break;
case feed_type:
lpszText = TEXT("●");
break;
case snake_type:
lpszText = TEXT("■");
break;
case none_type:
lpszText = TEXT(" ");
break;
default:
runtime_error("无效的背景框!");
break;
}
for (T::iterator it = t.begin();it != t.end();++it)
textout(handle, OFFSET_L + 2 * it->coord.first, OFFSET_U + it->coord.second, lpszText, SQUARE_COLOR+it->color,1);
}
//Node
struct Node {
pair<int, int> coord;
int color;
Node(int x,int y,int c):coord(x,y),color(c){}
friend inline bool operator<(const Node &lhs, const Node &rhs);
};
//比较两个节点是否相同的函数
bool equalNode(Node node1, Node node2) {
if (node1.coord.first == node2.coord.first && node1.coord.second == node2.coord.second)
return true;
else
return false;
}
//运算符重载(因为set需要排序)
inline bool operator<(const Node &lhs, const Node &rhs)
{
if (lhs.coord.second < rhs.coord.second)
{
return true;
}
else if (lhs.coord.second == rhs.coord.second)
{
return lhs.coord.first < rhs.coord.first;
}
else
{
return false;
}
}
//Bitmap 类
class Bitmap{
public:
friend class Feed;
friend class Snake;
Bitmap(int map_x,int map_y,int map_w,int map_h,int map_c):x(map_x),y(map_y),w(map_w),h(map_h),c(map_c){}
void printBitmap();
void Insert(pair<int, int> edge);
private:
int x, y, w, h, c;
set<Node> bm;
};
void Bitmap::Insert(pair<int, int> edge) {
if (edge.first >= x && edge.first <= x + w - 1 && edge.second >= y && edge.second <= y + h - 1)
bm.insert(Node(edge.first, edge.second,c));
else
throw runtime_error("无效的背景框!");
}
void Bitmap::printBitmap() {
print(bm, bitmap_type);
}
//feed类
class Feed {
public:
friend class Snake;
void PrintFeed();
private:
set<Node> fd;
};
void Feed::PrintFeed() {
print(fd, feed_type);
}
class Snake {
public:
friend class Feed;
enum direction {
up,
down,
left,
right
};
Snake(pair<int, int> head, pair<int, int> tail);
void PrintSnake();
void EraseSnake();
void MoveFront(pair<int,int> t);
bool NextStep(direction d,Bitmap &b,Feed &fd,bool &eat);
void Snake::AddNewFeed(Bitmap &b, Feed &f);
direction GetDir() {
return this->dir;
}
bool ChangeDirection(direction d, Bitmap &b, Feed &f, bool &eat); //判断方向改变是否合法
private:
deque<Node> sn;
direction dir;
void AddFrontNode(Node n, Feed &f);
};
Snake::Snake(pair<int, int> head, pair<int, int> tail) {
srand(static_cast<unsigned int>(time(NULL)));
if (head.first == tail.first) {
if (head.second < tail.second) {
dir = up;
for (int i = head.second;i <= tail.second;++i)
sn.push_back(Node(head.first, i,rand()%7));
}
else if (head.second > tail.second) {
dir = down;
for (int i = head.second;i >= tail.second;--i)
sn.push_back(Node(head.first, i, rand() % 7));
}
else
throw runtime_error("无法绘蛇");
}
else if (head.second == tail.second) {
if (head.first > tail.first) {
dir = right;
for (int i = head.first;i >= tail.first;--i)
sn.push_back(Node(head.second, i, rand() % 7));
}
else if (head.first < tail.first) {
dir = left;
for (int i = head.first;i <= tail.first;++i)
sn.push_back(Node(head.second, i, rand() % 7));
}
}
else
throw runtime_error("无法绘蛇");
}
void Snake::PrintSnake() {
print(sn, snake_type);
}
void Snake::EraseSnake() {
print(sn, none_type);
}
void Snake::AddFrontNode(Node n, Feed &f) {
sn.push_front(n);
f.fd.erase(n);
}
void Snake::MoveFront(pair<int,int> t) {
for (deque<Node>::reverse_iterator it = sn.rbegin();it != sn.rend();it++) {
if (it != sn.rend() - 1) {
it->coord.first = (it + 1)->coord.first;
it->coord.second = (it + 1)->coord.second;
}
else {
it->coord.first = t.first;
it->coord.second = t.second;
}
}
}
bool Snake::NextStep(direction d, Bitmap &b, Feed &f, bool &eat) {
pair<int, int> temp; //存放头节点
switch (d)
{
case up:
temp.first = sn[0].coord.first;
temp.second = sn[0].coord.second - 1;
break;
case down:
temp.first = sn[0].coord.first;
temp.second = sn[0].coord.second + 1;
break;
case left:
temp.first = sn[0].coord.first - 1;
temp.second = sn[0].coord.second;
break;
case right:
temp.first = sn[0].coord.first + 1;
temp.second = sn[0].coord.second;
break;
default:
throw runtime_error("反向无效");
break;
}
dir = d;
for (set<Node>::iterator it = b.bm.cbegin();it != b.bm.cend();it++)
if (equalNode(*it, Node(temp.first, temp.second,6)))
return false;
for (deque<Node>::iterator it = sn.begin();it != sn.end() - 1;it++)
if (equalNode(*it, Node(temp.first, temp.second,6)))
return false;
for (set<Node>::iterator it = f.fd.begin();it != f.fd.end();it++) {
if (equalNode(*it, Node(temp.first, temp.second,6))) {
eat = true;
AddFrontNode(*it, f);
AddNewFeed(b, f);
f.PrintFeed();
EraseSnake();
PrintSnake();
return true;
}
}
EraseSnake();
MoveFront(temp);
PrintSnake();
return true;
}
bool Snake::ChangeDirection(direction d, Bitmap &b, Feed &f, bool &eat) {
if (d == dir) return true; //不执行操作,但继续执行下面的代码
if (dir == up && d == down ||
dir == down && d == up ||
dir == left && d == right ||
dir == right && d == left)
return true;
return NextStep(d, b, f, eat);
}
void Snake::AddNewFeed(Bitmap &b, Feed &f) {
pair<int, int> temp;
bool ok = false;
set<Node>::iterator it;
srand(static_cast<unsigned int>(time(NULL)));
while (1) {
temp.first = rand() % b.w + b.x;
temp.second = rand() % b.h + b.y;
Node node(temp.first, temp.second,6);
for (it = b.bm.begin();it != b.bm.end(); it++) {
if (equalNode(*it, node)) {
ok = false;
break;
}
ok = true;
}
if (!ok) continue;
for (it = f.fd.begin();it != f.fd.end(); it++) {
if (equalNode(*it, node)) {
ok = false;
break;
}
ok = true;
}
if (!ok) continue;
deque<Node>::iterator dit;
for (dit = sn.begin();dit != sn.end();dit++) {
if (equalNode(*dit, node)) {
ok = false;
break;
}
ok = true;
}
if (!ok) continue;
f.fd.insert(Node(temp.first, temp.second,rand()%7));
break;
}
}
HANDLE handle;
void init(Bitmap &b,Feed &feed,Snake &s){
handle = initiate();
for (int i = 0; i < MAPW; i++)
{
b.Insert(make_pair(i, 0));
b.Insert(make_pair(i, MAPH - 1));
}
for (int j = 1; j < MAPH - 1; j++)
{
b.Insert(make_pair(0, j));
b.Insert(make_pair(MAPW - 1, j));
}
b.printBitmap();
for (int i = 0;i < 3;++i)
s.AddNewFeed(b, feed);
feed.PrintFeed();
s.PrintSnake();
LPTSTR Text1 = TEXT("SCORE:");
LPTSTR Text2 = TEXT("LEVEL:");
LPTSTR Text = TEXT("❤按任意键开始!❤");
textout1(handle, 1, 1, Text);
textout1(handle, OFFSET_L + 2*MAPW , OFFSET_U, Text1);
textout1(handle, OFFSET_L + 2 * MAPW, OFFSET_U + 5, Text2);
char c = _getch();
}
int main() {
srand(static_cast<unsigned int>(time(NULL)));
Bitmap myBitmap(0, 0, MAPW, MAPH,rand()%7);
Snake mySnake(make_pair(10, 10), make_pair(10, 12));
Feed myFeed;
init(myBitmap,myFeed,mySnake);
int score = 0, level = 0, max_delay = 70 - 10 * level, uplevel = 5, speed = 6, minspeed = 4;
bool ret = true, eat = false;
while (1)
{
//textout(handle, OFFSET_L + 2 * MAPW + 2, 4, string);
/*_itoa_s(level, string, 10);
textout(handle, OFFSET_L + 2 * MAPW + 2, 15, string);*/
int delay = 0;
max_delay = 35 - 5 * level;
while (delay < max_delay)
{
if (_kbhit())
{
int key = _getch();
switch (key)
{
case KEY_UP:
ret = mySnake.ChangeDirection(Snake::up, myBitmap, myFeed, eat);
break;
case KEY_DOWN:
ret = mySnake.ChangeDirection(Snake::down, myBitmap, myFeed, eat);
break;
case KEY_LEFT:
ret = mySnake.ChangeDirection(Snake::left, myBitmap, myFeed, eat);
break;
case KEY_RIGHT:
ret = mySnake.ChangeDirection(Snake::right, myBitmap, myFeed, eat);
break;
case KEY_ESC:
exit(EXIT_SUCCESS);
}
if (!ret) {
textout1(handle, OFFSET_L + MAPW / 2, OFFSET_U + MAPH / 2, TEXT("游戏结束"));
char c = _getch();
exit(EXIT_SUCCESS);
}
if (eat) {
eat = false;
score++;
if (score%uplevel == 0) {
level++;
uplevel += 3;
--speed;
speed = ((speed == minspeed) ? minspeed : speed);
}
}
}
Sleep(speed);
delay++;
} //while (delay < max_delay)
ret = mySnake.NextStep(mySnake.GetDir(), myBitmap, myFeed, eat);
if (!ret) {
textout1(handle, OFFSET_L + MAPW / 2, OFFSET_U + MAPH / 2, TEXT("游戏结束"));
char c = _getch();
exit(EXIT_SUCCESS);
}
if (eat) {
eat = false;
score++;
if (score%uplevel == 0) {
level++;
uplevel += 3;
--speed;
speed = ((speed == minspeed) ? minspeed : speed);
}
}
}//while(1)
return 0;
}
c++实现贪吃蛇
最新推荐文章于 2024-05-13 10:29:46 发布