• delphi 控制台 贪吃蛇


    游戏的界面

    主要的功能实现

    1 键盘消息

    program Project1;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils,
      windows,
      uConsoleClass in 'uConsoleClass.pas',
      uSnake in 'uSnake.pas';
    
    // 参考
    /// http://blog.csdn.net/haiou327/article/details/5695237
    var
      MyMsg   : TMsg;
    begin
      while windows.GetMessage(MyMsg, 0, 0, 0) do
      begin
        DispatchMessage(MyMsg);
      end;
    end.

    2 定时器 

    这里用的是API 

    procedure TimerProc(window : Hwnd ; message,idEvent :UInt; dwTime: dword);stdcall;
    begin
      if Snake.StartSnake then
        Snake.MoveSnake();
    end;


    FTimer := SetTimer(0, 0, TIMERINTERVAL, @TimerProc);

     3 蛇控制单元

    unit uSnake;
    
    interface
    
    uses
      Windows, classes, uConsoleClass, ExtCtrls;
    
    const
      GAMEROW = 16;
      GAMECOL = 54;
    
      TIMERINTERVAL = 300;
    type
    
      TMoveDir   = (MD_Right, MD_Left, MD_Up, MD_Down);
      TPointType = (PT_Head, PT_Body, PT_Tail, PT_Food);
    
    
      TGamePoint = record
        Row        : byte;
        Col        : byte;
        PointType  : TPointType;
      end;
      PGamePoint = ^TGamePoint;
    
    
      TReadKeyThread = Class(TThread)
      private
        FMoveDir        : TMoveDir;
        FStartRead      : boolean;
        FPause          : boolean;
    
        procedure SetStartRead(const Value: boolean);
      public
    
        property Pause            : boolean read FPause write FPause;
        property StartRead        : boolean read FStartRead write SetStartRead;
        property MoveDir          : TMoveDir read FMoveDir write FMoveDir;
      protected
        procedure Execute; override;
      end;
    
      TSnake = class
      private
        //FGameMap        : array[0..GAMEROW - 1, 0..GAMECOL - 1] of byte;
        FFoodPoint      : PGamePoint;
    
        FSnakePointList : TList;
        FLastPoint      : PGamePoint;
        FMyConsole      : TConsoleControl;
    
        FStartSnake     : boolean;
        FReadKeyThread  : TReadKeyThread;
    
        FEatFoodCount   : integer;
    //    FScores         : integer;
    
        procedure InitGameMap();
        procedure FreeSnakeList();
        function CheckInSnake(Row, Col: integer): boolean;
    
        procedure PrintSnake();
    
    
    
        function GetSnakeBodyType(bodyType: TPointType): PGamePoint;
        procedure GetFood();
    
        procedure ShowScores(add: boolean = false);
    
        procedure Start();
        function CheckGameOver(): boolean;
        procedure GameOver();
        function EatFood(): boolean;
    
        function GetMoveDir(): TMoveDir;
    
        property Dir: TMoveDir read GetMoveDir;
        property StartSnake: boolean read FStartSnake write FStartSnake;
    
      public
        constructor Create();
        destructor Destroy;override;
    
        procedure StartGame();
        procedure MoveSnake();
        function ThreadPause(): boolean;
      end;
    
    
    implementation
    
    uses SysUtils;
    
    var
      Snake   : TSnake;
      FTimer  : Integer;
    
    procedure TimerProc(window : Hwnd ; message,idEvent :UInt; dwTime: dword);stdcall;
    begin
      if Snake.StartSnake then
        Snake.MoveSnake();
    end;
    
    { TSnake }
    
    function TSnake.CheckGameOver: boolean;
    var
      Head: PGamePoint;
      I: integer;
      P: PGamePoint;
    begin
      Result  := false;
      Head    := GetSnakeBodyType(PT_Head);
    //  FMyConsole.SetCursorTo(0, 16);
    //  FMyConsole.WriteText('Row: ' + inttostr(Head^.Row) + ' Col: ' + inttostr(Head^.Col));
    
      if Dir = MD_Up then
      begin
        if Head^.Row = 1 then
          Result := true;
      end;
    
      // 判断撞到上下的墙
      if (Head^.Row < 1) or (Head^.Row > GAMEROW - 3) then
        Result := true;
    
      // 判断撞到左右的墙
      if (Head^.Col < 3) or (Head^.Col > GAMECOL - 6) then
        Result := true;
    
      // 判断是否撞到自己
    
      for I := 2 to FSnakePointList.Count - 1 do
      begin
        P := FSnakePointList.Items[I];
        case Dir of
        MD_Right:
          begin
            if (Head^.Col + 1 = P^.Col) and (Head^.Row = P^.Row) then
              Result := true;
          end;
        MD_Left:
          begin
            if (Head^.Col - 1 = P^.Col) and (Head^.Row = P^.Row) then
              Result := true;
          end;
        MD_Up:
          begin
            if (Head^.Row - 1 = P^.Row) and (Head^.Col = P^.Col) then
              Result := true;
          end;
        MD_Down:
          begin
            if (Head^.Row + 1 = P^.Row) and (Head^.Col = P^.Col) then
              Result := true;
          end;
        end;
      end;
    end;
    
    function TSnake.CheckInSnake(Row, Col: integer): boolean;
    var
      P: PGamePoint;
      I: integer;
    begin
      Result := false;
      for I := 0 to FSnakePointList.Count - 1 do
      begin
        P := FSnakePointList.Items[I];
        if (P^.Row = Row) and (P^.Col= Col) then
        begin
          Result := true;
          break;
        end;
      end;
    end;
    
    constructor TSnake.Create();
    begin
      FReadKeyThread  := TReadKeyThread.Create(true);
      FSnakePointList := TList.Create();
      New(FFoodPoint);
      New(FLastPoint);
      FMyConsole:= TConsoleControl.Create;
      FMyConsole.SetWindowTitle('【贪吃蛇】 V1.0');
      InitGameMap();
    end;
    
    destructor TSnake.Destroy;
    begin
      Dispose(FFoodPoint);
      Dispose(FLastPoint);
      FreeAndNil(FSnakePointList);
      FMyConsole.Free;
      FReadKeyThread.Free();
      inherited;
    end;
    
    function TSnake.EatFood: boolean;
    var
      Head : PGamePoint;
    begin
      Result := false;
      Head := GetSnakeBodyType(PT_Head);
      if (Head^.Row = FFoodPoint^.Row) and (Head^.Col = FFoodPoint^.Col) then
      begin
        ShowScores(true);
        Result := true;
      end;
      ShowScores();
    end;
    
    procedure TSnake.FreeSnakeList;
    var
      P: PGamePoint;
      Index: integer;
    begin
      if FSnakePointList.Count > 0 then
      begin
        repeat
          Index := FSnakePointList.Count - 1;
          P     := FSnakePointList.Items[Index];
          FSnakePointList.Delete(Index);
          Dispose(P);
        until FSnakePointList.Count = 0;
      end;
    end;
    
    procedure TSnake.GameOver;
    var
      S: string;
    begin
      StartSnake               := false;
      FReadKeyThread.StartRead := false;
    //
      FMyConsole.SetCursorTo(0, 16);
      FMyConsole.WriteText('                                                      ');
      FMyConsole.SetCursorTo(0, 16);
      FMyConsole.WriteText('游戏结束重新开始吗? (y/n):');
      Readln(S);
      if LowerCase(S) = 'y' then
      begin
        //FMyConsole.SetCursorTo(0, 16);
        //FMyConsole.WriteText('游戏开始                      ');
        InitGameMap();
        Start();
      end;
    end;
    
    procedure TSnake.GetFood;
    begin
      Randomize;
      repeat
        FFoodPoint^.Row := Random(GAMEROW - 7) + 5;
        FFoodPoint^.Col := Random(GAMECOL - 10) + 5;
      until not CheckInSnake(FFoodPoint^.Row, FFoodPoint^.Col);
      FMyConsole.SetForegroundColor(true, false, true, false);
      FMyConsole.SetCursorTo(FFoodPoint^.Col, FFoodPoint^.Row);
      FMyConsole.WriteText('O');
    end;
    
    function TSnake.GetMoveDir: TMoveDir;
    begin
      Result := FReadKeyThread.MoveDir;
    end;
    
    function TSnake.GetSnakeBodyType(bodyType: TPointType): PGamePoint;
    var
      I: integer;
    begin
      Result := nil;
      for I := 0 to FSnakePointList.Count - 1 do
      begin
        Result := FSnakePointList.Items[I];
        if Result.PointType = bodyType then break;
      end;
    end;
    
    procedure TSnake.InitGameMap;
    var
    //  I, J: integer;
      P: PGamePoint;
    begin
      FMyConsole.ClearScreen;
    //  for I := 0 to GAMEROW - 1 do
    //  begin
    //    for J := 0 to GAMECOL - 1 do
    //    begin
    //      if (I = 0) or (I = GAMEROW - 1) then
    //        FGameMap[I][J] := 1
    //      else
    //        FGameMap[I][J] := 0;
    //
    //      if (J = 0) or (J = 1) or (J = GAMECOL - 1 ) or (J = GAMECOL - 2 ) then
    //        FGameMap[I][J] := 1
    //      else
    //        FGameMap[I][J] := 0;
    //    end;
    //  end;
    
      FreeSnakeList();
    
      // 头 先添加
      New(P);
      P^.Row := 2;
      P^.Col := 7;
      P^.PointType := PT_Head;
      FSnakePointList.Add(P);
    
      // 身体
      New(P);
      P^.Row := 2;
      P^.Col := 6;
      P^.PointType := PT_Body;
      FSnakePointList.Add(P);
      New(P);
      P^.Row := 2;
      P^.Col := 5;
      P^.PointType := PT_Body;
      FSnakePointList.Add(P);
      New(P);
      P^.Row := 2;
      P^.Col := 4;
      P^.PointType := PT_Body;
      FSnakePointList.Add(P);
      New(P);
      P^.Row := 2;
      P^.Col := 3;
      P^.PointType := PT_Tail;
      FSnakePointList.Add(P);
    
    //  // 蛇的初始位置
    //  for J := 1 to 5 do
    //    FGameMap[1][J] := 1;
    
      // 食物初始位置
    //  FFoodPoint^.Row := 10;
    //  FFoodPoint^.Col := 30;
    //  FFoodPoint^.PointType := PT_Food;
    
    //  FGameMap[10][30] := 1; 
      FMyConsole.SetCursorTo(0, 0);
      FMyConsole.SetForegroundColor(true, false, false, false);
      FMyConsole.WriteTextLine('┏━━━━━━━━━━━━━━━━━━━━━━━━┓');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┃                                                ┃');
      FMyConsole.WriteTextLine('┗━━━━━━━━━━━━━━━━━━━━━━━━┛');
    
      GetFood();
    end;
    
    procedure TSnake.MoveSnake;
    var
      Head  : PGamePoint;
      Tail  : PGamePoint;
      P1, P2: PGamePoint;
      I     : integer;
      NewBody: PGamePoint;
      eat: boolean;
    begin
    
      if ThreadPause then
      begin
        FMyConsole.SetCursorTo(0, 16);
        FMyConsole.WriteText('游戏已暂停请按空格键继续...                    ');
      end
      else
      begin
        if CheckGameOver() then
        begin
          GameOver();
        end
        else
        begin
          eat := EatFood();
    
          //保存最后一个要擦除的点
          Tail := GetSnakeBodyType(PT_Tail);
          FLastPoint^.Row := Tail^.Row;
          FLastPoint^.Col := Tail^.Col;
    
          if eat then
          begin
            New(NewBody);
            NewBody^.Row := Tail^.Row;
            NewBody^.Col := Tail^.Col;
            NewBody^.PointType := PT_Tail;
            FSnakePointList.add(NewBody);
    
            Tail^.PointType := PT_Body;
    
            GetFood();
          end;
    
          // 移动蛇的位置
          for I := FSnakePointList.Count - 1 downto 1 do
          begin
            P1 := FSnakePointList.Items[I];
            P2 := FSnakePointList.Items[I - 1];
    
            P1^.Row := P2^.Row;
            P1^.Col := P2^.Col;
          end;
    
          Head := GetSnakeBodyType(PT_Head);
          case Dir of
            MD_Right: Inc(Head^.Col);
            MD_Left : Dec(Head^.Col);
            MD_Up   : Dec(Head^.Row);
            MD_Down : Inc(Head^.Row);
          end;
    
          PrintSnake();
    
            // 清空蛇尾
          if FStartSnake and not eat then
          begin
            FMyConsole.SetCursorTo(FLastPoint^.Col, FLastPoint^.Row);
            FMyConsole.WriteText(' ');
          end;
        end;
      end;
    
    end;
    
    procedure TSnake.PrintSnake;
    var
      P: PGamePoint;
      I: integer;
    begin
      FMyConsole.SetForegroundColor(false, true, false, false);
      for I := 0 to FSnakePointList.Count - 1 do
      begin
        P := FSnakePointList.Items[I];
        FMyConsole.SetCursorTo(P^.Col, P^.Row);
        case P^.PointType of
          PT_Head: FMyConsole.WriteText('#');
          PT_Body: FMyConsole.WriteText('*');
          PT_Tail: FMyConsole.WriteText('*');
        end;
      end;
    
    //  FMyConsole.WriteTextLine('┏━━━━━━━━━━━━━━━━━━━━━━━━┓');
    //  FMyConsole.WriteTextLine('┃****#                                           ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                         O      ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┃                                                ┃');
    //  FMyConsole.WriteTextLine('┗━━━━━━━━━━━━━━━━━━━━━━━━┛');
      // 1448end;
    
    procedure TSnake.ShowScores(add: boolean = false);
    var
      S: string;
    begin
    //    FEatFoodCount   : integer;
    //    FScores         : integer;
      if add then
      begin
        Inc(FEatFoodCount);
      end;
      S := Format('完成食物个数: %d     得分数: %d    ', [FEatFoodCount, 10 * FEatFoodCount]);
      FMyConsole.SetCursorTo(0, 16);
      FMyConsole.WriteText(S);
    end;
    
    procedure TSnake.Start;
    begin
      FEatFoodCount   := 0;
      //FScores         := 0;
      StartSnake := true;
      FReadKeyThread.StartRead := true;
    end;
    
    procedure TSnake.StartGame;
    var
      S: string;
    begin
      PrintSnake();
    
      FMyConsole.SetCursorTo(0, 16);
      FMyConsole.WriteText('现在开始游戏吗? (y/n):');
      Readln(S);
      if LowerCase(S) = 'y' then
      begin
    //    FMyConsole.SetCursorTo(0, 16);
    //    FMyConsole.WriteText('开始游戏                          ');
        Start();
      end;
    end;
    
    function TSnake.ThreadPause: boolean;
    begin
      Result := FReadKeyThread.Pause;
    end;
    
    { TReadKeyThread }
    
    procedure TReadKeyThread.Execute;
    var
      arrInputRecs   : array[0..9] of TInputRecord;
      dwCur, dwCount : DWORD;
      hInput         : THandle;
    begin
      hInput   := GetStdHandle(STD_INPUT_HANDLE);
      while TRUE do
      begin
        ReadConsoleInput(hInput, arrInputRecs[0], 10, dwCount);
    
        for dwCur := 0 to 10 - 1 do
        begin
          if self.Terminated then break;
          case arrInputRecs[dwCur].EventType of
            KEY_EVENT:
              begin
                with arrInputRecs[dwCur].Event.KeyEvent do
                begin
                  if bKeyDown = true then
                  begin
                    case wVirtualKeyCode of
                      VK_Space:
                        begin
                          Pause := not Pause;
                        end;
                      VK_Left:
                        begin
                          if (MoveDir <> MD_Left) and (MoveDir <> MD_Right) then
                          begin
                            if not FPause then
                              MoveDir := MD_Left;
                          end;
                        end;
                      VK_Right:
                        begin
                          if (MoveDir <> MD_Right) and (MoveDir <> MD_Left) then
                          begin
                            if not  FPause then
                              MoveDir := MD_Right;
                          end;
                        end;
                      VK_Up:
                        begin
                          if (MoveDir <> MD_Up) and (MoveDir <> MD_Down) then
                          begin
                            if not  FPause then
                              MoveDir := MD_Up;
                          end;
                        end;
                      VK_Down:
                        begin
                          if (MoveDir <> MD_Up) and (MoveDir <> MD_Down) then
                          begin
                            if not  FPause then
                              MoveDir := MD_Down;
                          end;
                        end;
                    end;
                  end;
                end;
              end;
          end;
        end;
      end;
    end;
    
    procedure TReadKeyThread.SetStartRead(const Value: boolean);
    begin
      FStartRead := Value;
      if FStartRead then
      begin
        MoveDir := MD_Right;
        FPause  := false;
        Resume;
      end
      else
        Suspend;
    end;
    
    initialization
      Snake := TSnake.Create;
      Snake.StartGame();
      FTimer := SetTimer(0, 0, TIMERINTERVAL, @TimerProc);
      
    finalization
      KillTimer(0, FTimer);
      Snake.Free();
    
    end.

    4 控制台单元  这个单元是网上的

    unit uConsoleClass;
    
    interface
    
    uses Windows;
    
    type
      TConsoleControl = Class
      private
        FhStdIn            : THandle;  // Handle to the standard input
        FhStdOut           : THandle;  // Handle to the standard output
        FhStdErr           : THandle;  // Handle to the standard error (Output)
        FbConsoleAllocated : Boolean;  // Creation Flag
        FBgAttrib          : Cardinal; // Currently set BackGround Attribs.
        FFgAttrib          : Cardinal; // Currently set ForeGround Attribs.
    
      public
        (* Creates a new consolewindow, or connects the current window *)
        constructor Create;
        destructor Destroy;override;
    
        (* Cleanup of the class structures *)
        (* Color properties:
           The console window does not handle the colors like known form delphi
           components. Each color will be created from a red,green,blue and a
           intensity part. In fact the resulting colors are the same as the well
           known 16 base colors (clwhite .. clBlack).
           Black ist if all flags are false, white if all flag are true.
           The following two functions will change the color for followingwrites *)
        procedure SetForegroundColor(bRed,bGreen,bBlue,bIntensity : Boolean);
        procedure SetBackgroundColor(bRed,bGreen,bBlue,bIntensity : Boolean);
    
        (* Writing functions : simple wrapper around WriteConsole*)
        procedure WriteText (const s : string);
        procedure WriteTextLine( const s : string);
    
        (* Change the Windowtitle of the command window. If the program has been
           executed from a CMD-box the title change is only active while the
           programs execution time *)
        procedure SetWindowTitle (const sTitle : string);
    
        (* some Cursor manipulation functions *)
        procedure ShowCursor (iSize : Integer);
        procedure HideCursor;
        procedure GetCursorPos(var x, y : integer);
        procedure SetCursorTo(x, y : integer);
    
        (* screen operations:
           the screen ist the visible part of a cmd window. Behind the windowthere
           is a screenbuffer. The screenbuffer may be larger than the visible window *)
        procedure ClearScreen;
        function GetScreenLeft   : integer;
        function GetScreenTop    : Integer;
        function GetScreenHeight : integer;
        function GetScreenWidth  : integer;
    
        (* screenbuffer operations *)
        procedure ClearBuffer;
        function GetBufferHeight : integer;
        function GetBufferWidth  : integer;
    
        (* sample to read characters from then screenbuffer *)
        procedure GetCharAtPos(x, y : Integer; var rCharInfo : Char);
      end;
    
    implementation
    { TConsoleControl }
    
    procedure TConsoleControl.ClearBuffer;
    var
      SBInfo         : TConsoleScreenBufferInfo;
      ulWrittenChars : Cardinal;
      TopLeft        : TCoord;
    begin
      TopLeft.X := 0;
      TopLeft.Y := 0;
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      FillConsoleOutputCharacter(FhStdOut,' ', SBInfo.dwSize.X * SBInfo.dwSize.Y, TopLeft, ulWrittenChars);
      FillConsoleOutputAttribute(FhStdOut, FOREGROUND_RED or FOREGROUND_BLUE or FOREGROUND_GREEN,
                                  (SBInfo.srWindow.Right - SBInfo.srWindow.Left) *
                                  (SBInfo.srWindow.Bottom - SBInfo.srWindow.Top),
                                  TopLeft, ulWrittenChars);
    end;
    
    procedure TConsoleControl.ClearScreen;
    var
      SBInfo         : TConsoleScreenBufferInfo;
      ulWrittenChars : Cardinal;
      TopLeft        : TCoord;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      TopLeft.X := SBInfo.srWindow.Left;
      TopLeft.Y := SBInfo.srWindow.Top;
    
      FillConsoleOutputCharacter(FhStdOut,' ',
                                 (SBInfo.srWindow.Right - SBInfo.srWindow.Left)*
                                 (SBInfo.srWindow.Bottom - SBInfo.srWindow.Top),
                                 TopLeft,
                                 ulWrittenChars);
      FillConsoleOutputAttribute(FhStdOut,FOREGROUND_RED or FOREGROUND_BLUE or FOREGROUND_GREEN,
                                 (SBInfo.srWindow.Right - SBInfo.srWindow.Left)*
                                 (SBInfo.srWindow.Bottom - SBInfo.srWindow.Top),
                                 TopLeft,
                                 ulWrittenChars);
    end;
    
    constructor TConsoleControl.Create;
    begin
      inherited Create;
    // A process can be associated with only one console, so the AllocConsole
    // function fails if the calling process already has a console.
      FbConsoleAllocated := AllocConsole;
    // initializing the needed handles
      FhStdOut := GetStdHandle(STD_OUTPUT_HANDLE);
      FhStdErr := GetStdHandle(STD_ERROR_HANDLE);
      FhStdIn  := GetStdHandle(STD_INPUT_HANDLE);
    end;
    
    destructor TConsoleControl.Destroy;
    begin
      if FbConsoleAllocated then FreeConsole;
      inherited;
    end;
    
    function TConsoleControl.GetBufferHeight: integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.dwSize.Y;
    end;
    
    function TConsoleControl.GetBufferWidth: integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.dwSize.X;
    end;
    
    procedure TConsoleControl.GetCharAtPos(x, y: Integer; var rCharInfo : Char);
    var
      CharInfo : array [0..10] of Char;
      TopLeft  : TCoord;
      CharsRead : Cardinal;
    begin
      TopLeft.x := X;
      TopLeft.Y := Y;
      ReadConsoleOutputCharacter(FhStdOut,CharInfo,10,TopLeft,CharsRead);
      rCharInfo   := CharInfo[0];
    end;
    
    procedure TConsoleControl.GetCursorPos(var x, y: integer);
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      x := SBInfo.dwCursorPosition.X;
      y := SBInfo.dwCursorPosition.Y;
    end;
    
    function TConsoleControl.GetScreenHeight: integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.srWindow.Bottom -SBInfo.srWindow.Top;
    end;
    
    function TConsoleControl.GetScreenLeft: integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.srWindow.Left;
    end;
    
    function TConsoleControl.GetScreenTop: Integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.srWindow.Top;
    end;
    
    function TConsoleControl.GetScreenWidth: integer;
    var
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      Result := SBInfo.srWindow.Right - SBInfo.srWindow.Left;
    end;
    
    procedure TConsoleControl.HideCursor;
    var
      ConsoleCursorInfo : TConsoleCursorInfo;
    begin
      GetConsoleCursorInfo(FhStdOut,ConsoleCursorInfo);
      if ConsoleCursorInfo.bVisible then begin
        ConsoleCursorInfo.bVisible := False;
        SetConsoleCursorInfo(FhStdOut,ConsoleCursorInfo);
      end;
    end;
    
    procedure TConsoleControl.SetBackgroundColor(bRed, bGreen, bBlue,
      bIntensity: Boolean);
    begin
      FBgAttrib := 0;
      if bRed       then FBgAttrib := FBgAttrib or BACKGROUND_RED;
      if bGreen     then FBgAttrib := FBgAttrib or BACKGROUND_GREEN;
      if bBlue      then FBgAttrib := FBgAttrib or BACKGROUND_BLUE;
      if bIntensity then FBgAttrib := FBgAttrib or BACKGROUND_INTENSITY;
      SetConsoleTextAttribute(FhStdOut, FBgAttrib or FFgAttrib);
    end;
    
    procedure TConsoleControl.SetCursorTo(x, y: integer);
    var
      Coords : TCoord;
      SBInfo : TConsoleScreenBufferInfo;
    begin
      GetConsoleScreenBufferInfo(FhStdOut,SBInfo);
      if x < 0 then Exit;
      if y < 0 then Exit;
      if x > SbInfo.dwSize.X then Exit;
      if y > SbInfo.dwSize.Y then Exit;
      Coords.X := x;
      Coords.Y := y;
      SetConsoleCursorPosition(FhStdOut,Coords);
    end;
    
    procedure TConsoleControl.SetForegroundColor(bRed, bGreen, bBlue,
      bIntensity: Boolean);
    begin
      FFgAttrib := 0;
      if bRed       then FFgAttrib := FFgAttrib or FOREGROUND_RED;
      if bGreen     then FFgAttrib := FFgAttrib or FOREGROUND_GREEN;
      if bBlue      then FFgAttrib := FFgAttrib or FOREGROUND_BLUE;
      if bIntensity then FFgAttrib := FFgAttrib or FOREGROUND_INTENSITY;
      SetConsoleTextAttribute(FhStdOut,FBgAttrib or FFgAttrib);
    end;
    
    procedure TConsoleControl.SetWindowTitle(const sTitle: string);
    begin
      SetConsoleTitle(PChar(sTitle));
    end;
    
    procedure TConsoleControl.ShowCursor(iSize: Integer);
    var
      ConsoleCursorInfo : TConsoleCursorInfo;
    begin
      GetConsoleCursorInfo(FhStdOut,ConsoleCursorInfo);
      if (not ConsoleCursorInfo.bVisible) or (ConsoleCursorInfo.dwSize <> iSize) then
      begin
        ConsoleCursorInfo.bVisible := True;
        ConsoleCursorInfo.dwSize   := iSize;
        SetConsoleCursorInfo(FhStdOut,ConsoleCursorInfo);
      end;
    end;
    
    procedure TConsoleControl.WriteText(const s: string);
    var
      ulLength : Cardinal;
    begin
      WriteConsole(FhStdOut, PChar(s), Length(s), ulLength, NIL);
    end;
    
    procedure TConsoleControl.WriteTextLine(const s: string);
    begin
      WriteText(s +#13#10);
    end;
    
    end.

                                                                                                                                  

  • 相关阅读:
    遗传算法中适值函数的标定与大变异算法
    遗传算法中几种不同选择算子及Python实现
    BZOJ_4025_二分图_线段树按时间分治+并查集
    BZOJ_1818_[Cqoi2010]内部白点 _扫描线+树状数组
    BZOJ_3165_[Heoi2013]Segment_线段树
    UOJ_21_【UR #1】缩进优化_数学
    UOJ_14_【UER #1】DZY Loves Graph_并查集
    BZOJ_5359_[Lydsy1805月赛]寻宝游戏_DP
    BZOJ_2813_奇妙的Fibonacci_线性筛
    51nod_1236_序列求和 V3 _组合数学
  • 原文地址:https://www.cnblogs.com/qkhhxkj/p/2846380.html
Copyright © 2020-2023  润新知