/*
* Snake.cpp
* Coco07
* 2020.8.28
*/
#include <Windows.h>
#include <stdio.h>
#include "Snake.h"
#include "Canvas.h"
#define SNAKE_INIT_X 10
#define SNAKE_INIT_Y 10
using namespace std;
Snake snake(SNAKE_INIT_X, SNAKE_INIT_Y);
int Get_Message(){
if(GetAsyncKeyState(VK_SPACE)) return -1;
else if(GetAsyncKeyState(VK_LEFT)) return 1;
else if(GetAsyncKeyState(VK_RIGHT)) return 2;
else if(GetAsyncKeyState(VK_UP)) return 3;
else if(GetAsyncKeyState(VK_DOWN)) return 4;
return 0;
}
const int PATH_X[4] = {0, 0, -1, 1}, PATH_Y[4] = {-1, 1, 0, 0};
bool mirr(int msg){
if(msg < 1) goto ret;
snake.next = snake.body.back();
snake.next.first += PATH_X[msg-1];
snake.next.second += PATH_Y[msg-1];
ret:return snake.move();
}
void SetConsoleCursor(const bool bo){
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(handle, &CursorInfo);
CursorInfo.bVisible = bo;
SetConsoleCursorInfo(handle, &CursorInfo);
}
void welcome(){
system("cls");
system("mode con:cols=50 lines=25");
system("title Snake1.1");
system("color 0f");
printf("Copyright Coco07\n");
printf("https://www.coco07.com/\n\n");
for(int i = 0; i < 50; ++i){
putchar('.');
Sleep(20);
}
Sleep(500);
putchar('\n');
system("pause");
system("cls");
SetConsoleCursor(0);
}
void game_over(){
system("color 0c");
Sleep(2000);
system("cls");
SetConsoleCursor(1);
Set_Cursor(0, 0);
printf("GAME OVER\n\n");
Sleep(500);
}
void DEBUG(){
Set_Cursor(0, 24);
printf("%d %d %d ", snake.body.front().first, snake.body.front().second, snake.body.size());
}
int main(){
welcome();
while(1){
DEBUG();
int msg = Get_Message();
if(msg == -1){ //wait
system("color 0a");
while(Get_Message() == -1){}
system("color 0f");
}
else if(!mirr(msg)){
game_over();
goto program_exit;
}
snake.canvas.draw();
Sleep(120);
}
program_exit:
system("pause");
return 0;
}
/*
* Snake.h
* Coco07
* 2020.8.27
*/
#ifndef SNAKE_H
#define SNAKE_H
#include <queue>
#include <utility>
#include "Canvas.h"
#define SNAKE_CHAR '*'
#define WALL_CHAR '#'
#define SPACE_CHAR ' '
#define SUPRISE_CHAR_L '1'
#define SUPRISE_CHAR_H '5'
using std::pair;
using std::queue;
class Snake{
public:
queue<pair<int, int> > body;
pair<int, int> next;
Canvas canvas;
Snake(const int x, const int y);
bool move();
char Make_Suprise();
private:
int tail_size;
};
Snake::Snake(const int x, const int y){
while(!body.empty()) body.pop();
body.push((pair<int, int>){x, y});
next = (pair<int, int>){x, y};
tail_size = 0;
canvas.init();
canvas[x+1][y+1] = SNAKE_CHAR;
Make_Suprise();
}
bool Snake::move(){
int nextX = next.first, nextY = next.second,
headX = body.back().first, headY = body.back().second,
tailX = body.front().first, tailY = body.front().second;
if(canvas[nextX+1][nextY+1] >= SUPRISE_CHAR_L && canvas[nextX+1][nextY+1] <= SUPRISE_CHAR_H){
tail_size += (int)canvas[nextX+1][nextY+1]-'0';
Make_Suprise();
}
else if(canvas[nextX+1][nextY+1] != SPACE_CHAR && next != body.back()){
return 0; //game over
}
body.push(next);
canvas[nextX+1][nextY+1] = SNAKE_CHAR;
if(tail_size){
--tail_size;
}
else{
body.pop();
canvas[tailX+1][tailY+1] = SPACE_CHAR;
}
if(nextX == headX){
next.first = nextX;
if(headY > nextY) next.second = nextY-1;
else next.second = nextY+1;
}
else{
if(headX > nextX) next.first = nextX-1;
else next.first = nextX+1;
next.second = nextY;
}
return 1;
}
pair<int, int> random(){return (pair<int, int>){rand()%(MAP_X+1), rand()%(MAP_Y+1)};}
char Snake::Make_Suprise(){
con:pair<int, int> where = random();
if(canvas[where.first][where.second] != SPACE_CHAR) goto con; //maybe bug
char p = SUPRISE_CHAR_L+rand()%(SUPRISE_CHAR_H-SUPRISE_CHAR_L+1);
canvas[where.first][where.second] = p;
return p;
}
#endif
/*
* Canvas.h
* Coco07
* 2020.8.27
*/
#ifndef CANVAS_H
#define CANVAS_H
#include <windows.h>
#include <ctime>
#include <stdio.h>
#define MAP_X 20
#define MAP_Y 40
#define SNAKE_CHAR '*'
#define WALL_CHAR '#'
#define SPACE_CHAR ' '
#define SUPRISE_CHAR_L '1'
#define SUPRISE_CHAR_H '5'
class Canvas{
public:
char page[MAP_X][MAP_Y];
bool draw();
void init();
char *operator[] (const int i) {return page[i];}
private:
char pageOUT[MAP_X][MAP_Y];
};
bool Set_Cursor(const int x, const int y);
void Canvas::init(){
srand(time(NULL));
for(int i = 0; i < MAP_X; ++i){
for(int j = 0; j < MAP_Y; ++j){
if(i == 0 || j == 0 || i == MAP_X-1 || j == MAP_Y-1) page[i][j] = WALL_CHAR;
else page[i][j] = SPACE_CHAR;
}
}
}
bool Canvas::draw(){
for(int i = 0; i < MAP_X; ++i){
for(int j = 0; j < MAP_Y; ++j){
if(pageOUT[i][j] != page[i][j]){
pageOUT[i][j] = page[i][j];
Set_Cursor(j, i);
putchar(pageOUT[i][j]);
}
}
}
}
COORD coord;
bool Set_Cursor(const int x, const int y){
coord.X = x; coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
#endif