C++控制檯迴圈連結串列實現貪吃蛇
阿新 • • 發佈:2019-01-02
-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;
}