SimpleĀ ASCII AntiSnake Game written in objective C++.

 

main.cpp

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include <iostream>
#include <conio.h>

#include "Includes.h"

using namespace std;

int main() {
  GameManager gameManager;
  
  gameManager.GameLoop();

  gameManager.gameOver();

  return 0;
}

 

Includes.h

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#pragma once

#include "GameManager.h"
#include "Level.h"
#include "HighScore.h"

 

Level.h

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#pragma once

#include <vector>
#include <string>
#include <ctime>
#include <random>

#include "Score.h"

using namespace std;

class Level
{
public:
  Level();
  ~Level();
  
  int getScore() { return _score.GetScore(); };

  void printLevel();
  bool playerInput(char key);
private:
  int _playerX;
  int _playerY;
  vector<string> _levelData;
  Score _score;

  mt19937 _randomEngine;

  void spawnApple();
  short checkCollision(char direction);
  void findPlayer();
  void loadLevel(string levelName);
};

 

Level.cpp

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include "Level.h"

#include <iostream>
#include <fstream>

Level::Level() : _playerX(0), _playerY(0)
{
  loadLevel("Level.txt");

  _randomEngine.seed(time(nullptr)); //Seeding random engine with time 

  findPlayer();
}


Level::~Level()
{
}

bool Level::playerInput(char key) {
  bool isGameOver = false;
  switch (key)
  {
  case 'W':
  case 'w':
    if (checkCollision('W') == 0 || checkCollision('W') == 2) {
      if (checkCollision('W') == 2) {
        _score.addPoint();
        spawnApple();
      }

      _levelData[_playerY][_playerX] = ' ';
      _levelData[_playerY - 1][_playerX] = '@';

      _playerY--;
    }
    else if (checkCollision('W') == 1) {
      isGameOver = true;
    }
    
    break;
  case 'S':
  case 's':
    if (checkCollision('S') == 0 || checkCollision('S') == 2) {
      if (checkCollision('S') == 2) {
        _score.addPoint();
        spawnApple();
      }

      _levelData[_playerY][_playerX] = ' ';
      _levelData[_playerY + 1][_playerX] = '@';

      _playerY++;
    }
    else if (checkCollision('S') == 1) {
      isGameOver = true;
    }
    break;
  case 'A':
  case 'a':
    if (checkCollision('A') == 0 || checkCollision('A') == 2) {
      if (checkCollision('A') == 2) {
        _score.addPoint();
        spawnApple();
      }

      _levelData[_playerY][_playerX] = ' ';
      _levelData[_playerY][_playerX - 1] = '@';

      _playerX--;
    }
    else if (checkCollision('A') == 1) {
      isGameOver = true;
    }
    break;
  case 'D':
  case 'd':
    if (checkCollision('D') == 0 || checkCollision('D') == 2) {
      if (checkCollision('D') == 2) {
        _score.addPoint();
        spawnApple();
      }

      _levelData[_playerY][_playerX] = ' ';
      _levelData[_playerY][_playerX + 1] = '@';

      _playerX++;
    }
    else if (checkCollision('D') == 1) {
      isGameOver = true;
    }
    break;
  }

  return isGameOver;
}

void Level::printLevel() {
  for (unsigned int i = 0; i < _levelData.size(); i++) {
    cout << _levelData[i] << endl;
  }

  _score.printScore();
}

void Level::spawnApple() {
  //Generating X & Y coordinates without border of the level
  uniform_int_distribution<int> distribution(1, _levelData.size() - 2); //Y, 
  uniform_int_distribution<int> distribution2(1, _levelData[0].size() - 2); //X

  RandAgain:
  unsigned int randomY = distribution(_randomEngine);
  unsigned int randomX = distribution2(_randomEngine);

  if (_levelData[randomY][randomX] != '@' && _levelData[randomY][randomX] != '#' && _levelData[randomY][randomX] != '*') {
    _levelData[randomY][randomX] = '*';

    RandAgain2:
    randomY = distribution(_randomEngine);
    randomX = distribution2(_randomEngine);

    if (_levelData[randomY][randomX] != '@' && _levelData[randomY][randomX] != '#' && _levelData[randomY][randomX] != '*') {
      _levelData[randomY][randomX] = '#';
    }
    else {
      goto RandAgain2;
    }
  }
  else {
    goto RandAgain; //Could be done better
            //Probably...
  }
}

short Level::checkCollision(char direction) {
  int playerNextX;
  int playerNextY;
  char tile;
  int collisionResult;

  switch (direction) {
  case 'W': //Up
    playerNextX = _playerX;
    playerNextY = (_playerY - 1);
    break;
  case 'S': //Down
    playerNextX = _playerX;
    playerNextY = (_playerY + 1);
    break;
  case 'A': //Left
    playerNextX = (_playerX - 1);
    playerNextY = _playerY;
    break;
  case 'D': //Right
    playerNextX = (_playerX + 1);
    playerNextY = _playerY;
    break;
  }

  tile = _levelData[playerNextY][playerNextX]; //Tile, which player wants to enter

  switch (tile) { //Checks what is next tile
  case '#': //Wall
    collisionResult = 1;
    break;
  case ' ': //Empty tile
    collisionResult = 0;
    break;
  case '*': //Apple
    collisionResult = 2;
    break;
  case '@': //Player
    collisionResult = 1;
    break;
  }

  return collisionResult;
}

void Level::loadLevel(string levelName) {
  ifstream file;
  file.open(levelName);

  if (!(file.fail())) {
    string line;

    while (getline(file, line)) {
      //Push the current line onto the levelData array
      _levelData.push_back(line);
    }
  }
  else {
    printf("Something is wrong in load level!\n");
  }
}

void Level::findPlayer() {
  char tile;

  for (unsigned int i = 0; i < _levelData.size(); i++) { //i - Y
    for (unsigned int j = 0; j < _levelData[i].size(); j++) { //j = X
      tile = _levelData[i][j];

      if (tile == '@') {
        _playerY = i;
        _playerX = j;
      }
    }
  }
}

 

GameManager.h

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#pragma once

#include "Level.h"
#include "Score.h"
#include "HighScore.h"

class GameManager
{
public:
  GameManager();
  ~GameManager();

  void GameLoop();
  void gameOver();
private:
  bool _isGameOver;
  char _previousChar;

  Level _level;
  HighScore _highScore;

  char playerInput();
  void clearScreen();	
};

 

GameManager.cpp

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include "GameManager.h"

#include <conio.h>
#include <Windows.h>
#include <iostream>

using namespace std;

GameManager::GameManager() : _isGameOver(false), _previousChar('D')
{
}


GameManager::~GameManager()
{
}

void GameManager::GameLoop() {
  _level.printLevel();

  while (!_isGameOver) {				
    clearScreen();

    _level.printLevel();

    Sleep((500 - _level.getScore() * 5));

    if (_level.playerInput(playerInput())) {
      _isGameOver = true;
    }
  }
}

char GameManager::playerInput() {
  char move = ' ';

  if (_kbhit()) {
    move = _getch();
    if (move == 0 || move == 0xE0) move = _getch();
    
    if (move == 'W' || move == 'w' || move == 'S' || move == 's' || move == 'A' || move == 'a' || move == 'D' || move == 'd') {
      _previousChar = move;
    }	

    if (move == 27) {
      _isGameOver = true;
    }
  }

  if (move = ' ') {
    move = _previousChar;
  }

  return move;
}

void GameManager::clearScreen() {
  system("CLS");
}

void GameManager::gameOver() {
  system("CLS");
  _highScore.addHighScore(_level.getScore());
  _getch();

  system("CLS");
  cout << "Score: " << _level.getScore() << endl;
  cout << "Thank you for playing" << endl;
  cout << "Press any key to end the program..." << endl;
  _getch();
}

 

Score.h

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#pragma once
class Score
{
public:
  Score();
  ~Score();

  void SetScore(unsigned int score) { _score = score; };
  void addPoint() { _score++; };


  unsigned int GetScore() { return _score; };

  void printScore();

private:
  unsigned int _score;
};

 

Score.cpp

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include "Score.h"

#include <iostream>

using namespace std;

Score::Score() : _score(0)
{
}


Score::~Score()
{
}

void Score::printScore() {
  cout << "Score: " << _score << endl;
}

 

HighScore.h

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#pragma once

#include <vector>
#include <string>
#include <fstream>
#include <iostream>

using namespace std;

class HighScore
{
public:
  HighScore();
  ~HighScore();
  
  void printHighScores();
  void addHighScore(unsigned int score);
  
private:
  unsigned int _highScore;
  vector<string> _highscoresNames;
  vector<int> _highscores;

  void loadHighScoresNames();
  void loadHighScores();
  int checkIfPlayerBeatScore();
};

 

HighScore.cpp

/*
Copyright (c) 2016 TheFlyingKeyboard
For more games and programs visit http://theflyingkeyboard.net/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/


#include "HighScore.h"



HighScore::HighScore() : _highScore(0)
{
  loadHighScoresNames();
  loadHighScores();
}


HighScore::~HighScore()
{
}

void HighScore::printHighScores() {
  for (int i = 0; i < _highscoresNames.size(); i++) {
    cout << i + 1 << ". " << _highscoresNames[i] << endl;
    cout << _highscores[i] << endl;
  }
}

void HighScore::addHighScore(unsigned int score) {
  _highScore = score;

  if (checkIfPlayerBeatScore() != 10) {
    ofstream highScores("Highscores.dat");
    ofstream highScoresNames("HighscoresNames.dat");

    string playerName;
    cout << "Enter your name: " << endl;
    cin >> playerName;

    for (int i = 0; i < _highscores.size(); i++) {
      if (checkIfPlayerBeatScore() == i) {
        highScores << _highScore << endl;
        highScoresNames << playerName << endl;
      }
      else {
        highScores << _highscores[i] << endl;
        highScoresNames << _highscoresNames[i] << endl;
      }
    }

    _highscores.clear();
    _highscoresNames.clear();

    loadHighScoresNames();
    loadHighScores();
  }
  printHighScores();
}

void HighScore::loadHighScoresNames() {
  ifstream file;
  file.open("HighscoresNames.dat");

  if (!(file.fail())) {
    string line;

    while (getline(file, line)) {
      //Push the current line onto the levelData array
      _highscoresNames.push_back(line);
    }
  }
  else {
    printf("Something is wrong in load highscoreNames!\n");
  }
}

void HighScore::loadHighScores() {
  ifstream file;
  file.open("Highscores.dat");

  if (!(file.fail())) {
    string line;

    while (getline(file, line)) {
      //Push the current line onto the levelData array
      _highscores.push_back(stoi(line));
    }
  }
  else {
    printf("Something is wrong in load highscore!\n");
  }
}

int HighScore::checkIfPlayerBeatScore() {
  int isNewHighscore = 10; //No highScore

  for (unsigned i = 0; i < _highscores.size(); i++) {
    if (_highScore > _highscores[i]) {
      isNewHighscore = i; //New position
      break;
    }
  }

  return isNewHighscore;
}

 

Level.txt

###################################
#                                 #
#      @                *         #
#                                 #
#                                 #
#              *                  #
#     *                           #
#                     *           #
#                                 #
#                                 #
#                                 #
###################################

 

HighScores.dat

80
70
62
60
50
47
40
30
22
18

 

HighScoresNames.dat

Jack
Steve
Johnny
Eve
Lincoln
Matt
Charlie
Dan
TheFlyingKeyboard
Lisa

 

C++ ASCII AntiSnake Game
Tagged on:             

Leave a Reply

Your email address will not be published. Required fields are marked *