// Snake // Distribué par http://www.developpez.com // Auteur original : Ozer Senturk // //--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" #include "Unit2.h" #include #include #pragma package(smart_init) #pragma resource "*.dfm" /******************************************************************************* ***************** Necessary Definitions and Declerations *************** *******************************************************************************/ TForm1 *Form1; //...Our form... #define SQUARESIZE 15 //...Size of a square... #define COLUMNS 20 //...Number of columns... #define ROWS 30 //...Number of rows... #define SPACESIZE 1 //...Space between squares... #define MAXSNAKE 100 //...Maximum length of the snake... struct Point{ //...2D point structure... int x; int y; }; typedef struct Point Point2D; Point2D Squares[ROWS][COLUMNS]; //...Positions of the squares... Point2D Snake[MAXSNAKE]; //...Snake's points... int SnakeIndex = -1; //...Index of the last snake... AnsiString CurrentDirection = "Down"; int GameOver = 0; //...Game is not over at the begining... time_t t; //...For srand... Point2D Breakfast; //...Square generated as a breakfast... int Eaten = 0; //...Number of eaten breakfasts... /******************************************************************************* ************** End Of Necessary Definitions and Declerations *********** *******************************************************************************/ //...Checks whether the given indices exists in the snake or not... int DoesExist(int XIndex, int YIndex){ for(int i = 0; i <= SnakeIndex ; i++) { if(Snake[i].x == XIndex && Snake[i].y == YIndex) return 1; } return 0; } //...Generates a square to be eaten... void GenerateBreakfast(void) { do { Breakfast.x = rand()%30; Breakfast.y = rand()%20; } while(DoesExist(Breakfast.x, Breakfast.y)); Form1->Canvas->Brush->Color = clBlack; Form1->Canvas->Pen->Color = clBlack; Form1->Canvas->Rectangle(Squares[Breakfast.x][Breakfast.y].x, Squares[Breakfast.x][Breakfast.y].y, Squares[Breakfast.x][Breakfast.y].x + SQUARESIZE, Squares[Breakfast.x][Breakfast.y].y + SQUARESIZE); } //...Shows game over screen... void ShowGameOver(void) { Form1->Label5->Visible = true; GameOver = 1; Form1->Timer1->Enabled = false; } //...Draws the snake... void DrawSnake(void) { Form1->Canvas->Brush->Color = clBlack; Form1->Canvas->Pen->Color = clBlack; for(int i = 0; i <= SnakeIndex; i++) { Form1->Canvas->Rectangle(Squares[Snake[i].x][Snake[i].y].x, Squares[Snake[i].x][Snake[i].y].y, Squares[Snake[i].x][Snake[i].y].x + SQUARESIZE, Squares[Snake[i].x][Snake[i].y].y + SQUARESIZE); } } //...Draws the yellow squares... void DrawScene(void) { int i,j; Form1->Canvas->Brush->Color = clYellow; Form1->Canvas->Pen->Color = clYellow; for(i = 0; i < ROWS; i++) { for(j = 0; j < COLUMNS; j++) { Form1->Canvas->Rectangle(Squares[i][j].x, Squares[i][j].y, Squares[i][j].x + SQUARESIZE, Squares[i][j].y + SQUARESIZE); } } } //...Moves the snake according to current direction... void MoveSnake() { int XIndex, YIndex; //...Where to set the head of the snake... //..The indices of the snakes end... int PrevX = Snake[SnakeIndex].x; int PrevY = Snake[SnakeIndex].y; for(int i = SnakeIndex; i > 0; i--) { Snake[i].x = Snake[i-1].x; Snake[i].y = Snake[i-1].y; } if(CurrentDirection == "Down") { XIndex = Snake[0].x + 1; YIndex = Snake[0].y; } else if(CurrentDirection == "Up") { XIndex = Snake[0].x - 1; YIndex = Snake[0].y; } else if(CurrentDirection == "Left") { XIndex = Snake[0].x; YIndex = Snake[0].y - 1; } else if(CurrentDirection == "Right") { XIndex = Snake[0].x; YIndex = Snake[0].y + 1; } if(XIndex < 0 || XIndex > 29 || YIndex < 0 || YIndex > 19) { ShowGameOver(); return; } if(DoesExist(XIndex, YIndex)) { ShowGameOver(); return; } Snake[0].x = XIndex; Snake[0].y = YIndex; //...Draw a yellow square to the end of the snake... Form1->Canvas->Brush->Color = clYellow; Form1->Canvas->Pen->Color = clYellow; Form1->Canvas->Rectangle(Squares[PrevX][PrevY].x, Squares[PrevX][PrevY].y, Squares[PrevX][PrevY].x + SQUARESIZE, Squares[PrevX][PrevY].y + SQUARESIZE); if(Snake[0].x == Breakfast.x && Snake[0].y == Breakfast.y) { //...You ate something... SnakeIndex++; Snake[SnakeIndex].x = PrevX; Snake[SnakeIndex].y = PrevY; //...Increase the score... Eaten++; Form1->Label2->Caption = IntToStr(StrToInt(Form1->Label2->Caption) + Form1->ComboBox1->ItemIndex + 1); GenerateBreakfast(); } } __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } void __fastcall TForm1::Button2Click(TObject *Sender) { Application->Terminate(); } void __fastcall TForm1::Button3Click(TObject *Sender) { Timer1->Enabled = false; Label4->Visible = true; Form2->Show(); } void __fastcall TForm1::FormCreate(TObject *Sender) { int i,j; //...Fill squares data... for(i = 0; i < ROWS; i++) { for(j = 0; j < COLUMNS; j++) { Squares[i][j].x = SPACESIZE + j * (SPACESIZE + SQUARESIZE); Squares[i][j].y = SPACESIZE + i * (SPACESIZE + SQUARESIZE); } } //...Fill snake data... Snake[0].x = 5; Snake[0].y = 10; Snake[1].x = 4; Snake[1].y = 10; Snake[2].x = 3; Snake[2].y = 10; Snake[3].x = 2; Snake[3].y = 10; Snake[4].x = 1; Snake[4].y = 10; Snake[5].x = 0; Snake[5].y = 10; SnakeIndex = 5; ComboBox1->ItemIndex = 0; srand((unsigned)time(&t)); //...Set the seed to a different one... GenerateBreakfast(); } void __fastcall TForm1::FormPaint(TObject *Sender) { DrawScene(); DrawSnake(); } void __fastcall TForm1::Timer1Timer(TObject *Sender) { if(GameOver) return; MoveSnake(); if(!GameOver) { DrawSnake(); Form1->Canvas->Brush->Color = clBlack; Form1->Canvas->Pen->Color = clBlack; Form1->Canvas->Rectangle(Squares[Breakfast.x][Breakfast.y].x, Squares[Breakfast.x][Breakfast.y].y, Squares[Breakfast.x][Breakfast.y].x + SQUARESIZE, Squares[Breakfast.x][Breakfast.y].y + SQUARESIZE); } } void __fastcall TForm1::ComboBox1Change(TObject *Sender) { switch(ComboBox1->ItemIndex) { case 0: Timer1->Interval = 1000; break; case 1: Timer1->Interval = 900; break; case 2: Timer1->Interval = 800; break; case 3: Timer1->Interval = 700; break; case 4: Timer1->Interval = 600; break; case 5: Timer1->Interval = 500; break; case 6: Timer1->Interval = 400; break; case 7: Timer1->Interval = 300; break; case 8: Timer1->Interval = 200; break; case 9: Timer1->Interval = 100; break; case 10: Timer1->Interval = 50; break; case 11: Timer1->Interval = 25; break; } Panel1->Enabled = false; Panel1->Enabled = true; } void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if(Label4->Visible && Key != 'p' && Key != 'P') return; switch(Key) { case VK_LEFT: if(CurrentDirection == "Right") { ShowGameOver(); return; } CurrentDirection = "Left"; Timer1->Enabled = false; Timer1Timer(this); Timer1->Enabled = true; break; case VK_RIGHT: if(CurrentDirection == "Left") { ShowGameOver(); return; } CurrentDirection = "Right"; Timer1->Enabled = false; Timer1Timer(this); Timer1->Enabled = true; break; case VK_DOWN: if(CurrentDirection == "Up") { ShowGameOver(); return; } CurrentDirection = "Down"; Timer1->Enabled = false; Timer1Timer(this); Timer1->Enabled = true; break; case VK_UP: if(CurrentDirection == "Down") { ShowGameOver(); return; } CurrentDirection = "Up"; Timer1->Enabled = false; Timer1Timer(this); Timer1->Enabled = true; break; case 'p': case 'P': Timer1->Enabled = ! Timer1->Enabled; Label4->Visible = ! Label4->Visible; break; } } void __fastcall TForm1::Button1Click(TObject *Sender) { //...Fill snake data... Snake[0].x = 5; Snake[0].y = 10; Snake[1].x = 4; Snake[1].y = 10; Snake[2].x = 3; Snake[2].y = 10; Snake[3].x = 2; Snake[3].y = 10; Snake[4].x = 1; Snake[4].y = 10; Snake[5].x = 0; Snake[5].y = 10; SnakeIndex = 5; Label2->Caption = "0"; Timer1->Enabled = true; Label5->Visible = false; GameOver = 0; ComboBox1Change(this); DrawScene(); CurrentDirection = "Down"; }