Use C + + design gluttonous Snake Games __c++

Source: Internet
Author: User
Tags gety rand sleep
Description: All code can be compiled and executed on Visual Studio 2013. did not test compilation on other compilers. rules of the game

The gluttonous snake game requires the player to control the direction key (or Wsad key) to control the direction of the snake, so that the snake can eat the food on the panel's immediate position. After each successful eating of food, the small snake body length will increase a little, the score increases. When a snake hits a border or a snake's head collides with a snake, the snake hangs and the game ends.

Game Structure Design

The game should contain the initial welcome interface, game interface, game end interface.

Create a Cgame class to manage the game's progress. The class is placed in the Game.h file, where you can define Newgame (), PlayGame (), Setgame () and Exitgame () four functions to control each unit of the game, in order to make the whole program look more like a game, You can take a more beautiful interface to show each part of the game.

The Newgame () function sets the game welcome interface. You can simply print out some characters of the game name Snake and a hint "press any key to start ...". After clicking on any key, the game program will be transferred to Setgame () to continue execution. You can add some dynamic effects so that the prompt "Press any keyto start ..." keeps beating. The Setgame () includes the contents of the game settings. You can choose Easy,normal,hard three options. These three options will correspond to the different moving velocities of the snakes, which will be reflected in the PlayGame () function each time the loop executes. After the setup is complete, the game program will be transferred to PlayGame () to continue execution. The PlayGame () function body will be a dead loop, because the game can be considered as an infinite loop in which each step of the iteration is performed sequentially: to determine whether the user enters, then adjusts the game content according to user input (and continues the game by default if there is no input), Judge whether to conform to the rules (do not conform to jump out of the loop, into the Exitgame () to exit the game), to determine whether the need for additional points deduction. After you have completed these steps, the next iteration is performed. Of course, before playing the game, you have to perform the necessary initialization to display the general frame and the hint information. Eitgame () displays the game score and asks if the player will play again. Here spelled out a skull-head pattern, said game over.

The above is the main content of the game, these four functions set the basic structure of the game, the remainder will continue to consider the details of the issue. And then show the details of Game.h. set up a game object

Set up a series of classes to represent the game object, which should include how to handle the game object (function). Analysis of the game, you can know that the main game is small snakes and food.

All game objects, including snakes and food, are made up of a series of points on the console. So a lot of methods are needed to handle point objects. You can create Point.h to define CPoint objects to simplify the processing of other objects.

The contents of the Point.h file are as follows:

#pragma once
#include <iostream>
#include <windows.h>
using Std::cout;
Using Std::cin;

Class CPoint
{public
:
	CPoint () {}
	cpoint (int x, int y)
	{
		this->x = x;
		This->y = y;
	}
	void Plot (HANDLE hOut)
	{
		setoutputposition (x, y,hout);
		cout << "";
	}
	void Clear (HANDLE hOut)
	{
		setoutputposition (x, y, hOut);
		cout << "  ";
	}
	void Clear ()
	{
		HANDLE hOut = GetStdHandle (std_output_handle);
		cout << "";
	}
	static method, which is used to set the position of the output point in the console at
	static void setoutputposition (int x, int y, HANDLE hOut)
	{
		COORD position;
		Position. x = x;
		Position. y = y;
		SetConsoleCursorPosition (hOut, position);
	}
	BOOL operator = = (cpoint& point)
	{return
		(point.x==this->x) && (point.y==this->y);
	}
	//Change the position of the CPoint object
	void setposition (int x, int y)
	{
		this->x = x;
		This->y = y;
	}
	int GetX () {return x;};
	int GetY () {return y;};
Private:
	int x, y;
};

Snakes and food are represented by a series of dots on the console panel. So this determines the small snakes and the food of the class data members will be used to store the specific information of these point sets. You can create a file snake.h and food.h to save the established class.

Snakes are made up of a series of dots that can be stored with simple arrays, linked lists, and so on. Consider the way snakes move: Snake as a whole before further, you can consider for the snake head to move a lattice according to the direction of the input, and then all the remaining points are moved to the position before the previous point of the snake. Add a point to the front of the head according to the user input direction, and the snake tail removes a point. The former needs to deal with all the points that make up the snake, which only needs to deal with two dots of snake head and snake tail. Obviously, the latter is more efficient. Here, a second mobile scheme is adopted, and a two-terminal queue is used to store the point's data accordingly.

For convenience, you can use the container class (a two-terminal queue) deque<t> defined in the C + + STL (Standard Template Library) to store the set of points, using Push_front () and Pop_back () to handle the snake's movement process.

The Snake.h is as follows:

#pragma once #include <iostream> #include "Point.h" #include <deque> #include "Point.h" #include "Food.h"
Using Std::cout;
Using Std::cin;

Using std::d eque; Class Csnake {Public:enum movedirection{up, left, down,right};//The snake has only four moving directions, so you can define an enumeration type of the direction of the Snake's Motion Csnake ()//Snake initially will be only two
		Point element, the initial moving direction is set to right {Snake.push_back (CPoint (18, 16));
		Snake.push_back (CPoint (16, 16));
	Direction = Movedirection::right; //The Snake moves forward one step at a time, that is, the update point set snake void Move () {switch (direction)//determines how it moves according to the direction in this case. When moving to improve efficiency will only need to deal with the end point element {case movedirection::D OWN:snake.push_front (CPoint snake.begin ()->getx (), Snake.begin (), ; GetY () + 1));
		Break Case Movedirection::left:snake.push_front (CPoint (Snake.begin ()->getx ()-2, Snake.begin ()->gety ()));
		Break Case Movedirection::right:snake.push_front (CPoint (Snake.begin ()->getx () + 2, Snake.begin ()->gety ()));
		Break Case Movedirection::up:snake.push_front (CPoint (Snake.begin ()->getx (), Snake.begin ()->gety ()-1)); Break
		} snake.pop_back (); BOOL Changedirection (movedirection direction) {if (direction + 2)% 4 = this->direction)//Player input Direction contrary to the current mobile direction of the snake will not change
		Change at this time the direction of the snake return false;
		else this->direction = direction;
	return true; //Draw the snake all over the place. For efficiency, the function should only invoke the void Paintsnake (HANDLE hOut) {for (cpoint& point:snake) {cpoint::setoutputposition, when the game is initialized ( Point. GetX (), point.
			GetY (), hOut); Point.
		Plot (HOut);	
			}//Check whether the snake head and the body parts coincide, used to determine whether the foul bool Hititself () {for (cpoint& point:snake) {if (point = = *snake.begin ())
					{if (&point = = & (*snake.begin ()))//will ignore the situation where the snake head coincides with the snake head.
				Continue
			else return true;
	return false;
	Check whether a point is coincident with the snake body to determine whether the randomly produced food is placed on the snake. 
		BOOL Hit (cpoint& point) {for (cpoint& pointinsnake:snake) {if (point = = Pointinsnake) return true;
	return false;
		Check whether the snake head wall, used to determine whether the foul bool Hitedge () {int x = Snake.begin ()->getx ();
		int y = Snake.begin ()->gety (); if ((x = = 0) | | | (Y = 2) | | (x = = 78) | |	(y = = 24))
		Compare the location of the default wall to return true;
	else return false;
	//often need to deal with the snake head and the tail of the snake, so the two functions are defined.
	cpoint& Head () {return *snake.begin ();
	} cpoint& Tail () {return * (Snake.end ()-1); BOOL Eat (cfood& food) {//Complex judgment statement, used to determine whether food is in the direction of the snake head moving in the forward int foodx = food. GetPosition ().
		GetX (); int foody = food. GetPosition ().
		GetY (); int HEADX = Head ().
		GetX (); int heady = head ().
		GetY (); BOOL Toeat = ((Foodx = = HEADX) && (foody = = (heady + 1)) && (direction = movedirection::D own)) | | ((Foodx = = HEADX) && (foody = = (heady-1)) && (direction = movedirection::up)) | | (((Foodx + 2) = = HEADX) && (foody = = heady) && (direction = = movedirection::left)) | |
		(((foodx-2) = = HEADX) && (foody = = heady) && (direction = = Movedirection::right)); if (toeat) {Snake.push_front (food).
			GetPosition ());
		return true;
	else return false;
	} private:deque<cpoint> Snake; MovedIrection direction; };

Food.h is much simpler by comparison. Use "$$" to display food on the console. The reason for not having "$" is that the snake consists of "", and "" is the position of two ordinary characters on one line on the console (helpless). The Food.h is as follows:

#pragma once
#include <iostream>
#include "Point.h"
using Std::cout;
Class Cfood
{public
:
	cfood ()
	{
		position. SetPosition (a);

	Cfood (int x, int y)
	{
		position. SetPosition (x, y);
	}

	void Placefood (int x, int y)
	{
		position. SetPosition (x, y);
		HANDLE HOut = GetStdHandle (std_output_handle);
		Setconsoletextattribute (HOut, Foreground_blue | Foreground_green | foreground_intensity);
		Cpoint::setoutputposition (x, y, hOut);
		cout << "$$";
	}

	cpoint& GetPosition ()
	{return
		position;
	}

	void Show ()
	{
		cout << ' (' << position. GetX () << ', ' << position. GetY () << ') ';
Private:
	cpoint position;

Here's what Game.h is all about. Due to the output of many patterns, Game.h slightly bloated:

#pragma once #include <iostream> #include "Snake.h" #include "Food.h" #include "Point.h" #include "conio.h" #include
<windows.h> #include <time.h> using Std::endl;
Class Csnake;
		Class Cgame {public:cgame () {length = 80;
		width = 24;
		Score = 0;
	Exit = FALSE;
	BOOL Exit () {return exit;};
		void Newgame () {//small_rect rc = {0, 0, 80-1, 25-1};//Reset window position and size system ("CLS");
		HANDLE HOut = GetStdHandle (Std_output_handle); Setconsoletextattribute (HOut, foreground_green|
		foreground_red);
		System ("color 81");
		COORD position = {17, 6};

		SetConsoleCursorPosition (hOut, position); Set output "SNAKE" Setconsoletextattribute (HOut, Foreground_green |
		
		foreground_intensity);
		cout << "";
		Setconsoletextattribute (HOut, Foreground_green);
		Cpoint::setoutputposition (7, HOut);
		cout << "";
		Cpoint::setoutputposition (8, HOut); Setconsoletextattribute (HOut, Foreground_red|
		foreground_intensity);
		cout << "";
		Cpoint::setoutputposition (9, HOut); Setconsoletextattribute (HOut, Foreground_blue | Foreground_green |
		foreground_intensity);
		cout << "";
		Cpoint::setoutputposition (HOut); Setconsoletextattribute (HOut, foreground_blue| foreground_red|
		foreground_intensity);
		cout << "";
		Cpoint::setoutputposition (A, hOut); Setconsoletextattribute (HOut, foreground_green| foreground_red|
		foreground_intensity);
		cout << "";
		Cpoint::setoutputposition (HOut); Setconsoletextattribute (HOut, foreground_blue|
		foreground_intensity);

		cout << "";
			while (true) {cpoint::setoutputposition (M, hOut);

			cout << "Press any key to start ...";
			Sleep (70);
			for (int i = 0; i < i++) cout << "\b \b";
			Sleep (70); if (_kbHit ()) break;
	} cin.get ();
		} void Setgame () {char chooselevel;
		System ("CLS");
		HANDLE HOut = GetStdHandle (Std_output_handle); Setconsoletextattribute (HOut, Foreground_green |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, Foreground_green |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, foreground_red |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, Foreground_blue | Foreground_green |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, Foreground_blue | foreground_red |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, FOREGround_green | foreground_red |
		foreground_intensity);
		cout << "" << Endl; Setconsoletextattribute (HOut, Foreground_blue |
		foreground_intensity);
		cout << "" << Endl;
		Cpoint::setoutputposition (9, HOut);
		cout << "chose difficulity:" << Endl;                                           cout << "1" Easy "<< Endl <<"
		2) Normal "<< Endl <<" 3) Hard "<< Endl;
			while (true) {chooselevel = _getch ();
				if (Chooselevel = = ' 1 ' | | | chooselevel = = ' 2 ' | | | | chooselevel = = ' 3 ') {level = chooselevel-' 0 ';
					Switch (level) {case 1:speed = 500;
				Break
					Case 2:speed = 250;
				Break
					Case 3:speed = 100;
				Break
			} break; }} void Paintedge () {HANDLE HOut = GEtstdhandle (Std_output_handle); Setconsoletextattribute (HOut, foreground_green|
		foreground_intensity); for (int x = 0; x <=, x = 2) {for (int y = 0; y < y++) {if (x = = 0) | | (y = = 0) | | (x = = 78) | |
				(y = = 24))
					{cpoint::setoutputposition (x, y, hOut);
				cout << "";
			for (int x = 2; x <=; x+=2) {cpoint::setoutputposition (x, 2, HOut);
		cout << "";
		} void Showstate () {HANDLE hOut = GetStdHandle (Std_output_handle); Setconsoletextattribute (HOut, background_green| foreground_red | background_intensity |
		foreground_intensity);
		Cpoint::setoutputposition (2, 1, hOut);
		cout << "difficulity:"; Switch (level) {case 1:cout << ' easy ';
		Break Case 2:cout << "Noraml";
		Break Case 3:cout << "Hard";
		Break } setconsoletextattribute (HOut, Foreground_green |
		foreground_intensity);
		cout << ""; Setconsoletextattribute (HOut, BACKGROUND_green | foreground_red | background_intensity |
		foreground_intensity);
		cout << "Press WASD to move your snake." Setconsoletextattribute (HOut, Foreground_green |
		foreground_intensity);
		cout << ""; Setconsoletextattribute (HOut, Background_green | foreground_red | background_intensity |
		foreground_intensity);

	cout << "Score:" << score<< "";
			} void Updatescore (bool eaten) {if (eaten) {HANDLE HOut = GetStdHandle (Std_output_handle); Setconsoletextattribute (HOut, Background_green | foreground_red | background_intensity |
			foreground_intensity);
			Score + 10;
			Cpoint::setoutputposition (1, HOut);
			cout << "Score:" << Score;

			int spaceused=0;
			for (int s = score S!= 0; s/=) spaceused++;
		for (int i = 0; i < 10-spaceused i++) cout << ";
		} bool Directionchanged () {char ch;
			if (_kbhit ()) {ch = _getch (); Switch (CH) {case ' W ': Case ' W ': return Snake. Changedirection (Snake.
			UP); Case ' A ': Case ' a ': return snake. Changedirection (Snake.
			left); Case "s": Case ' s ': return snake. Changedirection (Snake.
			Down); Case ' d ': Case ' d ': return snake. Changedirection (Snake.
			right);
	return false;
		} void Randomfood (cfood& food) {Srand (Static_cast<unsigned> (Time (NULL)));
		int x, y;
			while (true) {x = rand ()% (LENGTH/2) * 2;
			y = rand ()% (WIDTH/2) * 2; if ((x <= 2) | | (y <= 6) | | (x >= 70) | |
				(y >= 20))
			Continue if (!snake.
			Hit (CPoint (x, y))) break;
		else continue; } food.
	Placefood (x, y);
		} void PlayGame () {//Game interface Initialization phase system ("CLS");
		Paintedge ();
		Showstate (); Food.	Placefood (20,20);
		Set food initial position HANDLE HOut = GetStdHandle (Std_output_handle); Snake.
		Paintsnake (HOut); while (true) {snake. Tail ().
			Clear (HOut);
			Directionchanged (); BOOL eaten = snake.
			Eat (food);
			if (!eaten) Snake.move ();
			else Randomfood (food); UpdatescOre (eaten); Sets the current font to Black Bottom white setconsoletextattribute (HOut, foreground_intensity | foreground_red | Foreground_green |
			Foreground_blue); Snake. Head ().
			Plot (HOut); if (snake. Hitedge () | | Snake.
				Hititself ()) {sleep (1000); Setconsoletextattribute (HOut, foreground_red |
				foreground_red); Snake. Head ().
				Plot (HOut);
				Sleep (3000);
			Break
		Sleep (speed);
		} void Gameover () {int x = 28;
		int y = 3;
		System ("CLS");
		HANDLE HOut = GetStdHandle (Std_output_handle); Setconsoletextattribute (HOut, Foreground_green |
		foreground_intensity);
		Cpoint::setoutputposition (x, y, hOut);
		cout << "";
		Cpoint::setoutputposition (x, y+1, HOut);
		cout << "";
		Cpoint::setoutputposition (x, y+2, HOut);
		cout << "";
		Cpoint::setoutputposition (x, y+3, HOut);
		cout << "";
		Cpoint::setoutputposition (x, Y+4, HOut);
		cout << ""; Cpoint::setoutputposition (x, y+5, HOUT);
		cout << "";
		Cpoint::setoutputposition (x, Y+6, HOut);
		cout << "";
		Cpoint::setoutputposition (x, Y+7, HOut);
		cout << "";
		Cpoint::setoutputposition (x, Y+8, HOut);
		cout << "";
		Cpoint::setoutputposition (x, y+9, HOut);
		cout << "";
		Cpoint::setoutputposition (x, y+10, HOut);
		cout << "";
		Cpoint::setoutputposition (x+7, y +, hOut);
		cout << "GAME over";
		Cpoint::setoutputposition (x + 7, y +, hOut);
		cout << "Score:" << Score;
		Cpoint::setoutputposition (x + 4, y + hOut); cout << "Play Again?"
		(y/n) ";
		Char ch;
			while (true) {ch = _getch ();
				if (ch = = ' n ' | | | ch = = ' n ') {exit = true;
			Break
		else if (ch = = ' Y ' | | | ch = = ' Y ') break;
	} cpoint::setoutputposition (x-1, y +, hOut);
	} Private:bool exit;
	int level;
	int speed;
	BOOL Gameover;
	Csnake Snake;
	Cfood food; Int length;	Game area total length int width;
Game Area total width int score; };

The design part of the game has been completed. Finally, create a Source.cpp file to run the game. The game can be understood as an endless loop. The cycle is an initialization phase, a loop in which the game is performed, after which the player has played once, and whether the loop needs to be executed again depending on whether the player chooses to play back the game. Therefore, the body of the Source.cpp will be a do-while loop.

The contents of the Source.cpp file are as follows:

#include "Game.h"
#include <windows.h>
#include <iostream>
#include <conio.h>
# Include <cstdlib>

using Std::cout;
Using Std::cin;
Using Std::endl;

int main ()
{
	setconsoletitle (L "gluttonous snake");//For setting the console window name
	cgame* Game = new Cgame ();
	Game->newgame ();
	Do
	{
		delete Game;
		Game = new Cgame ();
		Game->setgame ();
		Game->playgame ();
		Game->gameover ();
	} while (! Game->exit ());
	Sleep ();
	return 0;
}

Actual operation Result:


To set the interface:


Game interface, above is the status and hint:


When a snake hits a wall or bumps into a snake, it is displayed in red and then enters the game over interface:


Game over interface:


The game is simple, but it does illustrate the structure of the general game. The game is actually an endless cycle.

Feelings:

1. Write code must be serious. I'm just beginning to write a y as x, because there are such functions, so there is no grammatical problem, but it is obvious that there are some strange bugs in the game. It took me hours to find this simple spelling problem.

2. procedural efficiency issues . I'm just starting to have a different set of snake-moving methods than what I said above. I defined two functions in the Csnake class to completely erase the actual snakes on the console and to show all the points that make up the snake in turn. Then in each iteration of the loop of Cgame::P laygame (), the snake's picture is completely erased from the last iteration, and then filled with the image of the snake after it was moved. But later, when the game was found, when the snake body is longer, each move one step, due to the output of the cursor causes, the snake is constantly flashing, when the choice of hard difficulty mode, flashing is very obvious, affecting the overall experience. To solve this problem, I use the method of dealing with the snake head and the tail of the snake every time I move to improve my efficiency. As a result, the snake can hardly feel the presence of the cursor when it moves, and the snake moves very stably.



Monday, December 9, 2013


Welcome to reprint, please specify the source: Click to open the link

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.