Preparation for Console Tetris

By | June 14, 2017

There was time when console was everywhere and no graphic user interface for any operating system at all. Nowadays some computer users even does not know what is command prompt for Windows or terminal for Macintosh OSX.
Command line user interface (CLI) is preferred console interface. To display computer graphic in text console so called text-base user interface (TUI) is used. DOS tetris and command prompt editor were implemented using TUI.
Below you may find 2 simple example of TUI implementation, which draw, rotate and move red rectangular composed by symbols. The first application is for Windows command prompt and second one for Linux and OSX operating systems.

Windows Command Prompt

Command Prompt Horizontal Rect

Command Prompt Horizontal Rect

Source Code

using System;
namespace ConsoleRect
{
    class Program
    {
        static void Main(string[] args)
        {
            // disable ctrl/c
            Console.CancelKeyPress += new ConsoleCancelEventHandler(HandleCancelKeys);
            // clear console and reset console	
            Console.Clear();
            Console.ResetColor();
            // old console size	
            int windowHeightOld = Console.WindowHeight;
            int windowWidthOld = Console.WindowWidth;
            string tt="Use Up,Down,Left,Right Arrow Keys to move rectangular. Q to exit";
            Console.Write(tt);
            Console.ForegroundColor = ConsoleColor.Red;
            // new console size	
            Console.WindowHeight = windowHeightOld * 3 / 2;
            Console.WindowWidth = windowWidthOld * 3 / 2;
            int consoleWindowLeft = Console.WindowLeft;
            int consoleWindowTop = Console.WindowTop;
            int consoleWindowWidth = Console.WindowWidth;
            int consoleWindowHeight = Console.WindowHeight;

            int xStartH = consoleWindowLeft + consoleWindowWidth / 3;
            int xEndH = consoleWindowLeft + (consoleWindowWidth / 3) * 2;
            int yStartH = consoleWindowTop + consoleWindowHeight / 3;
            int yEndH = consoleWindowTop + (consoleWindowHeight / 3) * 2;
            int xStartV = consoleWindowLeft + (consoleWindowWidth / 5) * 2;
            int xEndV = xStartV + consoleWindowHeight / 3; // (consoleWindowWidth / 5) * 4;
            int yStartV = consoleWindowTop + consoleWindowHeight / 5;
            int yEndV = consoleWindowTop + (consoleWindowHeight / 5) * 4;

            Draw(xStartH, xEndH, yStartH, yEndH, Convert.ToChar(2));
            bool bHor = true;
            while (true)
            {
                ConsoleKeyInfo cki = Console.ReadKey(true);
                if (cki.Key == ConsoleKey.Q)
                {
                    // quit application and restore old console
                    Console.Clear();
                    Console.ResetColor();
                    Console.SetWindowSize(windowWidthOld, windowHeightOld);
                    Console.WriteLine("Thank you for using");
                    return;
                }
                if (cki.Key == ConsoleKey.UpArrow)
                {
                    // draw veritical rect
                    if (bHor)
                        Draw(xStartH, xEndH, yStartH, yEndH, ' ');
                    Draw(xStartV, xEndV, yStartV, yEndV, Convert.ToChar(2));
                    bHor = false;
                }
                if (cki.Key == ConsoleKey.DownArrow)
                {
                    // draw horizontal rect
                    if (!bHor)
                        Draw(xStartV, xEndV, yStartV, yEndV, ' ');
                    Draw(xStartH, xEndH, yStartH, yEndH, Convert.ToChar(2));
                    bHor = true;
                }
                if (cki.Key == ConsoleKey.LeftArrow)
                {
                    // move rect left
                    if (xStartH > 0)
                    {
                        if (!bHor)
                            Draw(xEndV - 1, xEndV, yStartV, yEndV, ' ');
                        else
                            Draw(xEndH - 1, xEndH, yStartH, yEndH, ' ');
                        xStartH--;
                        xEndH--;
                        xStartV--;
                        xEndV--;
                        if (!bHor)
                            Draw(xStartV, xStartV + 1, yStartV, yEndV, Convert.ToChar(2));
                        else
                            Draw(xStartH, xStartH + 1, yStartH, yEndH, Convert.ToChar(2));
                    }
                }
                if (cki.Key == ConsoleKey.RightArrow)
                {
                    // move rect right
                    if (xEndH < consoleWindowWidth)
                    {
                        if (!bHor)
                            Draw(xStartV, xStartV + 1, yStartV, yEndV, ' ');
                        else
                            Draw(xStartH, xStartH + 1, yStartH, yEndH, ' ');
                        xStartH++;
                        xEndH++;
                        xStartV++;
                        xEndV++;
                        if (!bHor)
                            Draw(xEndV - 1, xEndV, yStartV, yEndV, Convert.ToChar(2));
                        else
                            Draw(xEndH - 1, xEndH, yStartH, yEndH, Convert.ToChar(2));
                    }
                }
            }
        }
        static void Draw(int xStart, int xEnd, int yStart, int yEnd, char chr)
        {
            for (int x = xStart; x < xEnd; x++)
            {
                for (int y = yStart; y < yEnd; y++)
                {
                    Console.SetCursorPosition(x, y);
                    Console.Write(chr);
                }
            }
        }
        private static void HandleCancelKeys(object sender, 
                                  ConsoleCancelEventArgs consoleCancelEventArgs)
        {
            // handle and disable ctrl/c
            consoleCancelEventArgs.Cancel = true;
        }
    }
}

Linux/Mac OS X Terminal

Terminal Horizontal Rect

Terminal Horizontal Rect

Source Code

#include 
#include 
#include 
#include 
int xrectstart;
int yrectstart;
int rectwidth = 20;
int rectheight = 5;
bool isvertical = false;
void moveleft();
void moveright();
void vertical();
void horizontal();
void drawrect(int xstart, int ystart, int height, int width, bool clean);
int main(int argc, char * argv[])
{
   printf("\033[?25l");      // cursor off
   printf("\033[2J\033[1;1H" \
     "Use Up,Down,Left and Right Arrow Keys to move rectangular or Q to exit");
   int ch = 0;
   struct termios told;
   tcgetattr(STDIN_FILENO, &told);
   struct termios tnew = told;
   tnew.c_iflag |= IGNBRK;
   tnew.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF);
   tnew.c_lflag &= ~(ICANON | ECHO | ECHOK | ECHOE | ECHONL | ISIG | IEXTEN);
//   tnew.c_lflag &= ~(ICANON | ECHO | IGNBRK);
   tcsetattr(STDIN_FILENO, TCSANOW, &tnew);
   // get terminal windows size
   struct winsize size;
   ioctl(STDOUT_FILENO,TIOCGWINSZ,&size);
   yrectstart = size.ws_row/3;
   xrectstart = size.ws_col/3;
   drawrect(xrectstart, yrectstart, rectwidth, rectheight, false);
   while((ch & 0xdf) != 'Q')
   {
      ch = getchar();
      if (ch == '\033') { // if the first value is esc
         getchar(); // skip the [
         switch(getchar()) { // the real value
                case 'A':
               // arrow up
               vertical();
            break;
            case 'B':
               // arrow down
               horizontal();
            break;
            case 'C':
               // arrow right
               moveright();
            break;
            case 'D':
               // arrow left
               moveleft();
            break;
         }
      }
   }
   printf("\033[2J\033[1;1H"); // clear screen
   printf("\033[?25h");   // cursor on
//      printf("\033[1;37m");       // no color
   printf("\033[39mDefault");
   tcsetattr(STDIN_FILENO, TCSANOW, &told);
   return 0;
}

// Rotate Functions

void vertical()
{
   if(!isvertical)
   {
      isvertical = true;
      drawrect(xrectstart, yrectstart, rectwidth, rectheight, true);
      int tmp = rectwidth;
      rectwidth = rectheight;
      rectheight = tmp;
      drawrect(xrectstart, yrectstart, rectwidth, rectheight, false);
   }
}
void horizontal()
{
   if(isvertical)
   {
      isvertical = false;
      drawrect(xrectstart, yrectstart, rectwidth, rectheight, true);
      int tmp = rectwidth;
      rectwidth = rectheight;
      rectheight = tmp;
      drawrect(xrectstart, yrectstart, rectwidth, rectheight, false);;
   }
}

// Move Functions
Move Rect

// Draw function
Draw Function

Leave a Reply

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