-
Notifications
You must be signed in to change notification settings - Fork 0
/
tsnake.cpp
executable file
·163 lines (132 loc) · 4.52 KB
/
tsnake.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <algorithm>
#include <cstdlib>
#include <deque>
#include <ncurses.h>
#include <random>
#include <string>
#include <unistd.h>
#include "tsnake.hpp"
#define height 25
#define width (height * 2)
int main(int argc, char *argv[]) {
std::random_device rd;
std::uniform_int_distribution<int> randX(1, width - 3);
std::uniform_int_distribution<int> randY(1, height - 3);
initscr();
curs_set(0); // hide terminal cursor
cbreak(); // read individual keY hits rather than complete lines of text
noecho(); // stop echoing keYboard inputs
refresh(); // refresh stdscr
WINDOW *board = createWin();
int input;
int highscore = 0;
do {
int X = width / 2, Y = height / 2;
int tailY = Y, tailX = X;
int appleX = randX(rd), appleY = randY(rd);
int score = 0;
int nextdireciton = -1, direction = KEY_UP;
char body = 'o', apple = 'A';
std::vector<char> snake(10, 'X');
std::deque<int> moves;
std::vector<std::pair<int, int>> positons;
printHomeScreen(board, highscore);
wgetch(board);
redraw(board);
printScore(board, score);
// print snake
for (char c : snake) {
mvwaddch(board, tailY++, tailX, body);
positons.push_back(std::make_pair(tailX, tailY));
}
wrefresh(board);
// print the first apple
mvwaddch(board, appleY, appleX, apple);
for (int i = 0; i < snake.size(); i++)
moves.push_back(KEY_UP); // record initial moves for tail end
auto pos = std::find(positons.begin(), positons.end(),
std::make_pair(tailX, tailY));
auto it = std::find(positons.begin(), positons.end(),
std::make_pair(appleX, appleY));
mvwaddch(board, tailY, tailX, ' ');
while (Y < height - 1 && Y > 0 && X < width - 1 && X > 0) // main game loop
{
// print new head positon
mvwaddch(board, Y, X, body);
positons.push_back(std::make_pair(X, Y));
wrefresh(board);
// wait and take input
do {
wtimeout(board, 200);
nextdireciton = wgetch(board);
} while (nextdireciton != KEY_UP && nextdireciton != KEY_DOWN &&
nextdireciton != KEY_LEFT && nextdireciton != KEY_RIGHT &&
nextdireciton != -1);
// if there is change in direction
if (nextdireciton != -1) {
if ((direction == KEY_RIGHT && nextdireciton != KEY_LEFT) ||
(direction == KEY_LEFT && nextdireciton != KEY_RIGHT) ||
(direction == KEY_DOWN && nextdireciton != KEY_UP) ||
(direction == KEY_UP && nextdireciton != KEY_DOWN))
direction = nextdireciton;
}
// updtae next head direction from input
if (direction == KEY_UP)
--Y;
else if (direction == KEY_DOWN)
++Y;
else if (direction == KEY_LEFT)
--X;
else if (direction == KEY_RIGHT)
++X;
// if the snake eat the apple
if (Y == appleY && X == appleX) {
// increase score bY 5 and print it
score += 5;
printScore(board, score);
// print new apple in another random location
do {
appleY = randY(rd);
appleX = randX(rd);
mvwaddch(board, appleY, appleX, apple);
auto it = std::find(positons.begin(), positons.end(),
std::make_pair(appleX, appleY));
} while (it == positons.end()); // new apple location must note be
// inside the snake body
moves.push_back(direction); // record the next move
} else {
moves.push_back(direction); // record the next move
// update tail end
if (moves.front() == KEY_UP)
--tailY;
else if (moves.front() == KEY_DOWN)
++tailY;
else if (moves.front() == KEY_LEFT)
--tailX;
else if (moves.front() == KEY_RIGHT)
++tailX;
// remove the current tail end piece
moves.pop_front();
positons.erase(positons.begin());
mvwaddch(board, tailY, tailX, ' ');
}
// check if the snake bite itself
auto pos =
std::find(positons.begin(), positons.end(), std::make_pair(X, Y));
if (pos != positons.end())
break;
}
if (highscore < score)
highscore = score;
printEndScreen(board, highscore, score);
// take input
do {
wtimeout(board, -1);
input = wgetch(board);
} while (input != 10 &&
input != 113); // input must be either 'ENTER' or 'Q';
} while (input == 10);
destroy_win(board);
endwin();
return 0;
}