// use following command to run : // g++ -std=c++14 snake.cpp -lpthread #include <bits/stdc++.h> #include <thread> #include <unistd.h> #include <termios.h> using namespace std; enum direction { LEFT, RIGHT, UP, DOWN }; enum tileConf { EMPTY, BLOCKED, OCCUPIED, FOOD }; enum gameState { RUNNING, OVER }; //////////////////////////////////////////////////////////////////////////////////////////////////////////// class Tile { public: tileConf conf; Tile(tileConf); }; Tile::Tile(tileConf tc) { conf = tc; } //////////////////////////////////////////////////////////////////////////////////////////////////////////// class Screen { public: int WIDTH,HEIGHT; vector< vector<Tile> >matrix; Screen(); void print(int,int,int,int,int); }; Screen::Screen() { HEIGHT = 20; WIDTH = 50; Tile tile(EMPTY); matrix = vector< vector<Tile> >(HEIGHT,vector<Tile>(WIDTH,tile)); /* for(int i=0;i<WIDTH;i++) matrix[HEIGHT-1][i].conf = matrix[0][i].conf = BLOCKED; for(int i=0;i<HEIGHT;i++) matrix[i][WIDTH-1].conf = matrix[i][0].conf = BLOCKED; */ } void Screen::print(int score,int level,int snakex,int snakey,int snakeLength) { system("clear"); for(int i=0;i<WIDTH+2;i++) cout<<"@"; cout<<endl; for(int i=0;i<HEIGHT;i++) { cout<<"@"; for(int j=0;j<WIDTH;j++) { if(matrix[i][j].conf == OCCUPIED) cout<<'o'; if(matrix[i][j].conf == BLOCKED) cout<<'#'; if(matrix[i][j].conf == EMPTY) cout<<' '; if(matrix[i][j].conf == FOOD) cout<<'F'; } cout<<"@"<<endl; } for(int i=0;i<WIDTH+2;i++) cout<<"@"; cout<<endl; cout<<"SCORE : "<<score<<endl; cout<<"LEVEL : "<<level<<endl; cout<<"Snake_Length : "<<snakeLength<<endl; cout<<"Snake_head (X,Y) : "<<snakex<<","<<snakey<<endl; } //////////////////////////////////////////////////////////////////////////////////////////////////////////// class Food { public: pair<int,int>coordinates; Food(Screen&); }; Food::Food(Screen&screen) { int x,y; do{ x = rand()%screen.HEIGHT; y = rand()%screen.WIDTH; }while(screen.matrix[x][y].conf!=EMPTY); coordinates = make_pair(x,y); screen.matrix[x][y] = FOOD; cout<<x<<" "<<y<<endl; //exit(0); } //////////////////////////////////////////////////////////////////////////////////////////////////////////// class Snake { public: pair<int,int>head,tail; list< pair<int,int> >body; int currentLength; volatile direction headDirection; int speed; Snake(Screen&); Snake(); void moveHeadLeft(Screen&,int&); void moveHeadRight(Screen&,int&); void moveHeadDown(Screen&,int&); void moveHeadUp(Screen&,int&); void moveTail(Screen&); void move(Screen&,int&); void eat(Screen&,int&); bool bitesItself(); // bites itself bool hitsWall(Screen&); }; Snake::Snake() { } Snake::Snake(Screen&screen) { int startx = screen.HEIGHT/2; int starty = screen.WIDTH/2; int endx = startx; int endy = starty+2; head = make_pair(endx,endy); tail = make_pair(startx,starty); pair<int,int>intermediate = make_pair(startx,starty+1); body.push_back(head); body.push_back(intermediate); body.push_back(tail); currentLength = 3; headDirection = RIGHT; speed = 1; screen.matrix[head.first][head.second].conf = OCCUPIED; screen.matrix[intermediate.first][intermediate.second].conf = OCCUPIED; screen.matrix[tail.first][tail.second].conf = OCCUPIED; } void Snake::moveTail(Screen&screen) { screen.matrix[tail.first][tail.second]=EMPTY; body.pop_back(); tail = body.back(); } void Snake::moveHeadLeft(Screen&screen,int &score) { int newx = head.first; int newy = head.second-1; if(newy<0) newy+=screen.WIDTH; tileConf tc = screen.matrix[newx][newy].conf; if(tc==FOOD) eat(screen,score); else if(tc==BLOCKED || tc==OCCUPIED) exit(0); screen.matrix[newx][newy]=OCCUPIED; head = make_pair(newx,newy); body.push_front(head); } void Snake::moveHeadRight(Screen&screen,int &score) { int newx = head.first; int newy = head.second+1; if(newy>=screen.WIDTH) newy%=screen.WIDTH; tileConf tc = screen.matrix[newx][newy].conf; if(tc==FOOD) eat(screen,score); else if(tc==BLOCKED || tc==OCCUPIED) exit(0); screen.matrix[newx][newy]=OCCUPIED; head = make_pair(newx,newy); body.push_front(head); } void Snake::moveHeadDown(Screen&screen,int &score) { int newx = head.first+1; int newy = head.second; if(newx>=screen.HEIGHT) newx%=screen.HEIGHT; tileConf tc = screen.matrix[newx][newy].conf; if(tc==FOOD) eat(screen,score); else if(tc==BLOCKED || tc==OCCUPIED) exit(0); screen.matrix[newx][newy]=OCCUPIED; head = make_pair(newx,newy); body.push_front(head); } void Snake::moveHeadUp(Screen&screen,int &score) { int newx = head.first-1; int newy = head.second; if(newx<0) newx = newx + screen.HEIGHT; tileConf tc = screen.matrix[newx][newy].conf; if(tc==FOOD) eat(screen,score); else if(tc==BLOCKED || tc==OCCUPIED) exit(0); screen.matrix[newx][newy]=OCCUPIED; head = make_pair(newx,newy); body.push_front(head); } void Snake::move(Screen &screen,int &score) { if(headDirection == RIGHT) moveHeadRight(screen,score); else if(headDirection == LEFT) moveHeadLeft(screen,score); else if(headDirection == UP) moveHeadUp(screen,score); else if(headDirection == DOWN) moveHeadDown(screen,score); moveTail(screen); } void Snake::eat(Screen&screen,int &score) { pair<int,int>tail1,tail2; tail1 = body.back(); body.pop_back(); tail2 = body.back(); body.push_back(tail); direction tailDirection; int x1,y1,x2,y2; x1 = tail1.first; y1 = tail1.second; x2 = tail2.first; y2 = tail2.second; if(y1+1==y2) { body.push_back(make_pair(x1,y1-1)); tail = body.back(); screen.matrix[x1][y1-1].conf=OCCUPIED; } else if(y1==y2+1) { body.push_back(make_pair(x1,y1+1)); tail = body.back(); screen.matrix[x1][y1+1].conf=OCCUPIED; } else if(x1==x2+1) { body.push_back(make_pair(x1+1,y1)); tail = body.back(); screen.matrix[x1+1][y1].conf=OCCUPIED; } else if(x1+1==x2) { body.push_back(make_pair(x1-1,y1)); tail = body.back(); screen.matrix[x1-1][y1].conf=OCCUPIED; } currentLength++; score+=10; Food f(screen); } bool Snake::bitesItself() { return false; } bool Snake::hitsWall(Screen&s) { return false; } //////////////////////////////////////////////////////////////////////////////////////////////////////////// class Game { public: gameState state; int score; int level; Snake snake; Screen screen; Game(); void run(); void keepSnakeMoving(Snake&,Screen&); }; Game::Game() { state = RUNNING; score = 0; level = 1; screen = Screen(); snake = Snake(screen); } void Game::keepSnakeMoving(Snake &snake,Screen &screen) { Food f(screen); while(true) //for(int i=0;i<10;i++) { usleep(100000); //cout<<"here"<<endl; snake.move(screen,score); screen.print(score,level,snake.head.first,snake.head.second,snake.currentLength); } } char getch() { char buf = 0; struct termios old = {0}; if (tcgetattr(0, &old) < 0) perror("tcsetattr()"); old.c_lflag &= ~ICANON; old.c_lflag &= ~ECHO; old.c_cc[VMIN] = 1; old.c_cc[VTIME] = 0; if (tcsetattr(0, TCSANOW, &old) < 0) perror("tcsetattr ICANON"); if (read(0, &buf, 1) < 0) perror ("read()"); old.c_lflag |= ICANON; old.c_lflag |= ECHO; if (tcsetattr(0, TCSADRAIN, &old) < 0) perror ("tcsetattr ~ICANON"); return (buf); } void Game::run() { thread th(&Game::keepSnakeMoving,this,std::ref(snake),std::ref(screen)); while(true) { char ch = getch(); if((ch=='w' || ch=='8') && snake.headDirection!=DOWN) snake.headDirection = UP; else if((ch=='d' || ch=='6') && snake.headDirection!=LEFT) snake.headDirection = RIGHT; else if((ch=='s' || ch=='5') && snake.headDirection!=UP) snake.headDirection = DOWN; else if((ch=='a' || ch=='4') && snake.headDirection!=RIGHT) snake.headDirection = LEFT; } th.join(); } int main() { srand((unsigned)time(0)); Game g; g.run(); return 0; }
Thursday, 29 December 2016
Snake Game in C++
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment