This is a sample implementation of the tetris game in console. The tetris game was implemented both in C++ and C#. C++ version uses a predefined base class that provides access to character console buffer, keyboard control and main generic game cycle. C# version uses the same C++ base class, but this time compiled into managed DLL assembly.
Download C++ console tetris game source code
Download C# console tetris game source code
const float tetris::SPEED = 0.5; // default seconds per each down move const float tetris::HIGH_SPEED = 0.05; tetris::tetris() : BaseApp(24, 30) { srand (time(NULL)); pausing = true; figure=NULL; figureNext=NULL; moveTimer = 0; DrawScene(); // draw scene DrawWalls(); SpawnNewFigure(); } void tetris::SpawnNewFigure() { Figure::POINT pt; currentSpeed = SPEED; moveDownCounter = 0; // take next figure as current one if (figure) { delete figure; figure=NULL; } if (figureNext) figure = figureNext; // initialize current figure for the first time // place current figure at initial position on top pt.x = (X_SIZE-6)/2; pt.y = 2; if (!figure) figure = new Figure(pt,this); else figure->PlaceTo(pt); figure->Draw(); // prepare next figure for future cycle // create and show next figure on the right pt.x = X_SIZE-5; figureNext = new Figure(pt,this); figureNext->Draw(); pausing = false; } void tetris::KeyPressed(int btnCode) { try { if (btnCode == 224) btnCode = getch(); switch(btnCode) { case 119: case 72: currentSpeed=SPEED; break; // w, up arrow case 115: case 80: currentSpeed=HIGH_SPEED; break; // s, down arrow case 97: case 75: figure->MoveLeft(); break; // a, left arrow case 100: case 77: figure->MoveRight(); break; // d, right arrow case 32: figure->Rotate(); break; // space case 'p': pausing=!pausing; break; // pause } } catch(...) { pausing = true; SpawnNewFigure(); } } void tetris::UpdateF(float deltaTime) { try { if (figure && !pausing) { moveTimer += deltaTime; if (moveTimer>=currentSpeed) { moveTimer = 0; bool ok = figure->MoveDown(); if (ok) { moveDownCounter++; ok = figure->CanMoveDown(); } if (!ok) { pausing = true; if (moveDownCounter==0) // if we could not make even 1 move down - GAME OVER: restart a game { DrawScene(); // draw scene DrawWalls(); } SpawnNewFigure(); // if reached a floor, respawn a new figure from top } } } } catch(...) { pausing = true; SpawnNewFigure(); } } void tetris::DrawWalls() { for (int x = 0; x < X_SIZE; x++) { SetChar(x, 0, W); SetChar(x, Y_SIZE-1, W); } for (int y = 0; y < Y_SIZE; y++) { SetChar(0, y, W); SetChar(X_SIZE-1, y, W); } for (int x = X_SIZE-7; x < X_SIZE; x++) { SetChar(x, 5, W); } for (int y = 0; y < 5; y++) { SetChar(X_SIZE-7, y, W); } } void tetris::DrawScene() { for (int x = 0; x < X_SIZE; x++) { for (int y = 0; y < Y_SIZE; y++) { SetChar(x,y, E); } } }C# source code sample
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; using FigureLayout = System.Collections.Generic.List; namespace tetrisCSharp { class Tetris : BaseApp { public const char W = '#'; // wall character public const char F = '*'; // figure character public const char E = '.'; // empty character float moveTimer; bool pausing; int moveDownCounter; const float SPEED = 0.5f; // default speed: seconds per move const float HIGH_SPEED = 0.05f; // high speed float currentSpeed = SPEED; // current speed Figure figure; Figure figureNext; void DrawWalls() { Enumerable.Range(0, X_SIZE).ForEach(x => { SetChar(x, 0, W); SetChar(x, Y_SIZE - 1, W); }); // horizontal walls Enumerable.Range(0, Y_SIZE).ForEach(y => { SetChar(0, y, W); SetChar(X_SIZE - 1, y, W); }); // vertical walls // box, showing next figure Enumerable.Range(X_SIZE - 7, 7).ForEach(x => SetChar(x, 5, W)); Enumerable.Range(0, 5).ForEach(y => SetChar(X_SIZE - 7, y, W)); } void DrawScene() { // place empty char in all cells Enumerable.Range(0, X_SIZE).CrossJoinAndExecute(Enumerable.Range(0, Y_SIZE), (x, y) => SetChar(x, y, E)); } void SpawnNewFigure() { POINT pt; currentSpeed = SPEED; moveDownCounter = 0; // take next figure as current one if (figure != null) { figure = null; } if (figureNext != null) figure = figureNext; // initialize current figure for the first time // place current figure at initial position on top pt.x = (X_SIZE - 6) / 2; pt.y = 2; if (figure == null) figure = new Figure(pt, this); else figure.PlaceTo(pt); figure.Draw(); // prepare next figure for future cycle // create and show next figure on the right pt.x = X_SIZE - 5; figureNext = new Figure(pt, this); figureNext.Draw(); pausing = false; } internal Tetris() : base(24, 30) { pausing = true; moveTimer = 0; DrawScene(); // draw scene DrawWalls(); SpawnNewFigure(); } public override void KeyPressed(int btnCode) { try { switch (btnCode) { case 119: case 72: currentSpeed = SPEED; break; // w, up arrow case 115: case 80: currentSpeed = HIGH_SPEED; break; // s, down arrow case 97: case 75: figure.MoveLeft(); break; // a, left arrow case 100: case 77: figure.MoveRight(); break; // d, right arrow case 32: figure.Rotate(); break; // space case 'p': pausing = !pausing; break; // pause } } catch { pausing = true; SpawnNewFigure(); } } public override void UpdateF(float deltaTime) { try { if (figure!=null && !pausing) { moveTimer += deltaTime; if (moveTimer >= currentSpeed) { moveTimer = 0; bool ok = figure.MoveDown(); if (ok) { moveDownCounter++; ok = figure.CanMoveDown(); } if (!ok) { pausing = true; if (moveDownCounter == 0) // if we could not make even 1 move down - GAME OVER: restart a game { DrawScene(); // draw scene DrawWalls(); } SpawnNewFigure(); // if reached a floor, respawn a new figure from top } } } } catch { pausing = true; SpawnNewFigure(); } } } }
Комментариев нет :
Отправить комментарий