Last active
August 29, 2015 14:19
-
-
Save poseidon4o/3a13c54f3f85de2dfacb to your computer and use it in GitHub Desktop.
Snake
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <Windows.h> | |
#include <iostream> | |
using namespace std; | |
enum Dir { | |
Up = 0, Left = 1, Down = 2, Right = 3 | |
}; | |
struct coord { | |
int x, y; | |
bool operator==(const coord & o) const { | |
return x == o.x && y == o.y; | |
} | |
}; | |
struct Food { | |
coord pos; | |
char texture = '@'; | |
}; | |
class Snake { | |
coord body[1000]; | |
coord & head; | |
int size; | |
bool hasGrown; | |
Dir dir; | |
public: | |
Dir getDir() const { | |
return dir; | |
} | |
static const char body_texture, head_texture; | |
Snake(): head(body[0]), dir(Right), size(1), hasGrown(false) { | |
for (int c = 0; c < 1000; ++c) { | |
body[c] = { -1, -1 }; | |
} | |
head = { 5, 5 }; | |
} | |
void turn(Dir dir) { | |
this->dir = dir; | |
} | |
const coord & getHead() { | |
return head; | |
} | |
bool inside(coord pos) { | |
for (int c = 0; c < size; ++c) { | |
if (pos == body[c]) { | |
return true; | |
} | |
} | |
return false; | |
} | |
void step() { | |
coord newPos = head; | |
switch (dir) { | |
case Up: newPos.y -= 1; break; | |
case Left: newPos.x -= 1; break; | |
case Down: newPos.y += 1; break; | |
case Right: newPos.x += 1; break; | |
} | |
if (newPos == body[1]) { | |
return; | |
} | |
if (hasGrown) { | |
++size; | |
hasGrown = false; | |
} | |
for (int c = size - 1; c > 0; --c) { | |
body[c] = body[c - 1]; | |
} | |
head = newPos; | |
} | |
void grow() { | |
hasGrown = true; | |
} | |
}; | |
const char Snake::body_texture = 'x'; | |
const char Snake::head_texture = 'X'; | |
class Game { | |
Snake snake; | |
Food food; | |
coord board; | |
friend class Drawer; | |
public: | |
Game(coord board) : board(board) { | |
spawnFood(); | |
} | |
void spawnFood() { | |
do { | |
food.pos.x = rand() % board.x; | |
food.pos.y = rand() % board.y; | |
} while (snake.inside(food.pos)); | |
} | |
bool step() { | |
snake.step(); | |
coord head = snake.getHead(); | |
if (food.pos == head) { | |
snake.grow(); | |
spawnFood(); | |
} | |
if (head.x < 0 || head.y < 0 | |
|| head.x > board.x || head.y > board.y) { | |
return false; | |
} | |
return true; | |
} | |
void read_input() { | |
if (GetAsyncKeyState(VK_LEFT)) { | |
snake.turn(Left); | |
} | |
else if (GetAsyncKeyState(VK_RIGHT)) { | |
snake.turn(Right); | |
} | |
else if (GetAsyncKeyState(VK_UP)) { | |
snake.turn(Up); | |
} | |
else if (GetAsyncKeyState(VK_DOWN)) { | |
snake.turn(Down); | |
} | |
} | |
}; | |
class Drawer { | |
Game & game; | |
public: | |
Drawer(Game & g) : game(g) {} | |
void draw() { | |
for (int row = 0; row < game.board.y; ++row) { | |
for (int col = 0; col < game.board.x; ++col) { | |
coord current = { col, row }; | |
if (game.food.pos == current) { | |
std::cout << game.food.texture; | |
} | |
else if (game.snake.inside(current)) { | |
std::cout << | |
(game.snake.getHead() == current ? | |
game.snake.head_texture : | |
game.snake.body_texture); | |
} | |
else { | |
std::cout << ' '; | |
} | |
} | |
} | |
} | |
void clear() { | |
system("cls"); | |
} | |
private: | |
}; | |
int main() { | |
Game g({ 80, 21 }); | |
Drawer d(g); | |
while (true) { | |
if (!g.step()) { | |
cout << "You lost"; | |
} | |
g.read_input(); | |
d.draw(); | |
Sleep(100); | |
d.clear(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Cool :)