//=========================================================================== // SNAKE w/ arrow keys //=========================================================================== // revised 2005 // Arrow Keys have been added to direct the snake. // // To enable the ArrowKeys: // // 1) Set Form1->KeyPreview to true; // 2) Create the Form1->OnKeyDown handler... // 3) In that handler include instructions for the VK_LEFT and other keys // // For the arrow keys to be recognized, you must return FOCUS away from // the buttons when they are pressed. To do this, include an // EditLength->SetFocus(); call at the end of each Button event handler. //=========================================================================== #include #pragma hdrstopFlag #include "Unit1.h" #include #include "math.h" // Needed to make randomize() work #include "time.h" // Needed to make randomize() work //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } // ========================================================================== // VARIABLES // ========================================================================== bool ateFood = false; // the world int world[25][25]; // these take care of the toroidal world int east, south, relativeE, relativeS, wrappedE, wrappedS; // the positions of each segment in the snake int snakeE[650], snakeS[650]; int snakeHeadE, snakeHeadS; int snakeTailE, snakeTailS; int snakeLength; int segment; int direction, lastDirection, reverseDirection; int span; int maxSize = 25; int iterations = 0; // ========================================================================== // FUNCTIONS // ========================================================================== //------------------------------------------------------------------- Render void render(void) { for (east=0; eastCanvas->Pen->Color=clRed; Form1->Canvas->Brush->Color=clRed; Form1->Canvas->Rectangle (east*20,south*20,east*20+20,south*20+20); break; case 1: Form1->Canvas->Pen->Color=clLime; Form1->Canvas->Brush->Color=clLime; Form1->Canvas->Rectangle (east*20,south*20,east*20+20,south*20+20); break; case 2: Form1->Canvas->Pen->Color=clBlue; Form1->Canvas->Brush->Color=clBlue; Form1->Canvas->Rectangle (east*20,south*20,east*20+20,south*20+20); break; case 3: Form1->Canvas->Pen->Color=clFuchsia; Form1->Canvas->Brush->Color=clFuchsia; Form1->Canvas->Rectangle (east*20,south*20,east*20+20,south*20+20); break; } } } } //---------------------------------------------------------------- Game Over void gameOver (void) { Form1->Timer1->Enabled = false; Form1->Color = clBlack; render(); Application->ProcessMessages(); } //----------------------------------------------------------------- Clear All void clearAll (void) { for (east=0; eastTimer1->Enabled = true; } //---------------------------------------------------------------------- STEP void step (void) { // cannot fold back on yourself reverseDirection = direction + 2; if (reverseDirection > 3) reverseDirection = reverseDirection - 4; if (lastDirection == reverseDirection) direction = lastDirection; // figure out where new head will be switch (direction) { case 0: // up snakeHeadS--; if (snakeHeadS < 0) snakeHeadS = 24; break; case 1: // right snakeHeadE++; if (snakeHeadE > 24) snakeHeadE = 0; break; case 2: // down snakeHeadS++; if (snakeHeadS > 24) snakeHeadS = 0; break; case 3: // left snakeHeadE--; if (snakeHeadE <0) snakeHeadE = 24; break; } // if you eat poison or eat yourself then the game is over if (world[snakeHeadE][snakeHeadS] == 3) gameOver(); if (world[snakeHeadE][snakeHeadS] == 1) gameOver(); // if there is food there remember to add to length if (world[snakeHeadE][snakeHeadS] == 2) ateFood = true; world[snakeHeadE][snakeHeadS] = true; // move each segment's E and S position down the shake length for (segment = snakeLength + 1; segment > 0; segment --) { snakeE[segment] = snakeE[segment - 1]; snakeS[segment] = snakeS[segment - 1]; } // and the snake head at the front snakeE[segment] = snakeHeadE; snakeS[segment] = snakeHeadS; // remove the snake's last tail position if it hasn't eaten if (!ateFood) { snakeTailE = snakeE[snakeLength ]; snakeTailS = snakeS[snakeLength ]; } if (ateFood) { snakeLength++; ateFood = false; } lastDirection = direction; // snake cannot double back on self world[snakeTailE][snakeTailS] = false; render(); // show some statistics Form1->EditLength->Text = snakeLength; } // ========================================================================== // EVENT HANDLERS // ========================================================================== //----------------------------------------------------------------- Form Show void __fastcall TForm1::FormShow(TObject *Sender) { randomize(); } //-------------------------------------------------------------- Begin Button void __fastcall TForm1::ButtonBeginClick(TObject *Sender) { clearAll(); makeRandomFood(); makeRandomPoison(); makeRandomSnake(); render(); EditLength->SetFocus(); // Returns the Edit to focus } //--------------------------------------------------------------- Step Button void __fastcall TForm1::ButtonStepClick(TObject *Sender) { step(); EditLength->SetFocus(); // Returns the Edit to focus } //-------------------------------------------------------------- Pause Button void __fastcall TForm1::ButtonPauseClick(TObject *Sender) { Timer1->Enabled = !Timer1->Enabled; if (Timer1->Enabled == true) { ButtonPause->Caption = "Pause"; PanelPause->Color = clRed; } else { ButtonPause->Caption = "Resume"; PanelPause->Color = clLime; } EditLength->SetFocus(); // Returns the Edit to focus } //----------------------------------------------------------------- On Timer void __fastcall TForm1::Timer1Timer(TObject *Sender) { step(); Application->ProcessMessages(); } //------------------------------------------------------------- Form Key Down void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift) { if (Key == VK_LEFT) direction = 3; if (Key == VK_RIGHT) direction = 1; if (Key == VK_UP) direction = 0; if (Key == VK_DOWN) direction = 2; } // ========================================================================== // THAT'S ALL FOLKS // ==========================================================================