C12-纯C语言写的俄罗斯方块小游戏加彩色库使用


hello 大家好对于前面学习C语言已经过半,今天打算做一个小游戏,练习语法。

方块形状

放在一总的数组中,要使用的时候,从总的数组中取出来

遇到sizeof的时候可以调试 去除以一个数字 不用太过于思考。

自动下落

#include<coino.h>
#include<time.h>
clock_t //其实是 类型名字替换 long
clock_t clockStart=clock();
clock_t clockFinish=clock(); //开始与结束都再一个起跑线
while1{
char chInput=0;
if(_kbhit()!=0)
{
chInput=_getch();
}
clockFinish=clock();//刷新 结束时间
if(clockFinish-clockStart>500)
{
OnDown();
clockStart=clock();//刷新 Start点 要不然一直大于500ms
}
//下面用switch调节方块去向
}

一开始 start与finish是一起开始的
finish - start会大于 500
那么start没有更新,所以以后一直大于 500 一直下落
所以 函数里面要将函数更新

背景与方块组合问题

思考 如果 背景与方块一直分离
那么方块靠近墙的时候 会有空白的地方 那么编译器到底显示墙还是 方块空白的地方呢 (坐标重合)

所以 用Combine函数 将方块融入到背景中 把方块为1的点,把在这个坐标的背景点变为1;
以后ShowGame只要 ShowBG就可以了
融合以后 还要分离 那么跳回去分离就可以了 就是将方块为1的点 把背景坐标变为0;

组合的时候还可以判断 是否游戏结束,如果 变为1的时候 已经是1那么游戏就结束了。

下个方块显示问题

下个方块显示问题
1.初始第一个方块的时候 直接使用随机值(没有改变 g_nShape,g_nType)
2.再得到下一个方块的 并且显示出来 (改变了g_nShape,g_nType)
思考:下落的时候 才会更新下一个方块 所以将 CurBrick放在OnDown里面并且显示出预测的下一个方块

在OnDown里面
3.GetNew方块的时候 就把此时方块等于 上一次CurBrick方块
4.即时更新,CurBrick

Rotata 会影响g_nShape 所以取一个中间变量 g_nShape1,g_nType
更新状态思考,应该在CurBrick更新 g_nShape g_nType之前
所以第一次,CurBrick以后再显示 OnceBrick g_shape1是等于OnceBrick的
再CurBrick里面 更新g_nShape之前 就更新g_nShape1 等于上一次的g_nShape
增加一个中间层 就解决了 g_nShape 为一个 更新影响。

菜单

  • 对于void函数 返回主菜单用return就可以了

附录代码

如果要复制的时候,请把编译环境修改(预编译头,随机基地址。)
Tetris.cpp

#include "stdafx.h"
#include"View.h"
#include"Model.h"
#include<conio.h>
#include<stdlib.h>
#include"time.h"

void GameGo();
int _tmain(int argc, _TCHAR* argv[])
{
 GameGo();
 return 0;
}
void GameGo()
{
 do{
  int nValue = 0;
  MainMeau();
  scanf("%d", &nValue);
  switch (nValue)
  {
  case 1:
   GameIntr();
   break;
  case 2:
   SeletSpeed();
   break;
  case 3:
   exit(0);
   break;
  default:
   break;
  }
 } while (1);
}

Model.cpp


#include"Model.h"
#include"view.h"
#include"stdlib.h"
#include"time.h"
#include<stdio.h>
#include<conio.h>

char g_chBackGround[GAME_ROW][GAME_COL] = { 0 };
char g_chBrick[4][4] = { 0 };
char g_chCurBrick[4][4] = { 0 };

int g_nType = 0;//种类
int g_nShape = 0;//形状

int g_nRow = 0;//Brick的坐标
int g_nCol = 0;//

int g_nGrade = 0;

int g_nSpeed = 0;





char g_chBrickPool[][4] = {
    //T
    1, 1, 1, 0,
    0, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    0, 1, 0, 0,
    1, 1, 0, 0,
    0, 1, 0, 0,
    0, 0, 0, 0,

    0, 1, 0, 0,
    1, 1, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 0, 0, 0,
    1, 1, 0, 0,
    1, 0, 0, 0,
    0, 0, 0, 0,

    //长条
    1, 1, 1, 1,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0,

    1, 1, 1, 1,
    0, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,


    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0,

    //L
    1, 0, 0, 0,
    1, 0, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,

    1, 1, 1, 0,
    1, 0, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 1, 0, 0,
    0, 1, 0, 0,
    0, 1, 0, 0,
    0, 0, 0, 0,

    0, 0, 1, 0,
    1, 1, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    //反向L
    0, 1, 0, 0,
    0, 1, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,


    1, 0, 0, 0,
    1, 1, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 1, 0, 0,
    1, 0, 0, 0,
    1, 0, 0, 0,
    0, 0, 0, 0,

    1, 1, 1, 0,
    0, 0, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
   
    //田
    1, 1, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,


    1, 1, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,


    1, 1, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
   
    1, 1, 0, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,
    //z
    1, 1, 0, 0,
    0, 1, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    0, 1, 0, 0,
    1, 1, 0, 0,
    1, 0, 0, 0,
    0, 0, 0, 0,

    1, 1, 0, 0,
    0, 1, 1, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    0, 1, 0, 0,
    1, 1, 0, 0,
    1, 0, 0, 0,
    0, 0, 0, 0,

    //反Z
    0, 1, 1, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 0, 0, 0,
    1, 1, 0, 0,
    0, 1, 0, 0,
    0, 0, 0, 0,

    0, 1, 1, 0,
    1, 1, 0, 0,
    0, 0, 0, 0,
    0, 0, 0, 0,

    1, 0, 0, 0,
    1, 1, 0, 0,
    0, 1, 0, 0,
    0, 0, 0, 0,
};
void CurBrick()
{
    srand((unsigned)time(NULL));

    g_nRow = 0;
    g_nCol = GAME_COL / 2 - 1;
    int nAddType = sizeof(g_chBrickPool) / sizeof(g_chBrickPool[0]) / 16;

    g_nShape1 = g_nShape;
    g_nType1 = g_nType;
    g_nType = rand() % nAddType;


    g_nShape = rand() % 4;
   



    for (size_t nRow = 0; nRow < 4; nRow++)
    {
        for (size_t nCol = 0; nCol < 4; nCol++)
        {
            g_chCurBrick[nRow][nCol] = g_chBrickPool[nRow + g_nShape * 4 + g_nType * 16][nCol];
        }
    }

}


void ShowOnceBrick()
{
    srand((unsigned)time(NULL));
    g_nRow = 0;
    g_nCol = GAME_COL / 2 - 1;
    int nAddType = sizeof(g_chBrickPool) / sizeof(g_chBrickPool[0]) / 16;
    int nType2= rand() % nAddType;
    g_nType1 = nType2;//赋值给旋转
    int nShape2= rand() % 4;
    g_nShape1 = nShape2;//赋值给旋转
    for (size_t nRow = 0; nRow < 4; nRow++)
    {
        for (size_t nCol = 0; nCol < 4; nCol++)
        {

            g_chBrick[nRow][nCol] = g_chBrickPool[nRow + nShape2 * 4 + nType2 * 16][nCol];

        }
    }
    ShowBrick();
}
void GetNewBrick()
{
    for (size_t nRow = 0; nRow < 4; nRow++)
    {
        for (size_t nCol = 0; nCol < 4; nCol++)
        {

            g_chBrick[nRow][nCol] = g_chCurBrick[nRow][nCol];

        }
    }


}


void InitBackGround()
{
    for (size_t nRow = 0; nRow <GAME_ROW; nRow++)
    {
        for (size_t nCol = 0; nCol < GAME_COL; nCol++)
        {
            if (nCol == 0 ||
                nRow == GAME_ROW - 1 ||
                nCol == GAME_COL - 1)
            {
                g_chBackGround[nRow][nCol] = 1;
            }
            else
            {
                g_chBackGround[nRow][nCol] = 0;
            }
        }

    }
}

int IsCanMove(int nRowGobe, int nColGobe)
{
    for (size_t nRow = 0; nRow < 4; nRow++)
    {
        for (size_t nCol = 0; nCol < 4; nCol++)
        {
            if (g_chBrick[nRow][nCol] == 1)
            {
                if (1==g_chBackGround[nRow + nRowGobe][nCol + nColGobe])
                {
                    return 0;
                }
            }

        }
    }
    return 1;
}
int IsCanRotate()
{
    char chCurBrick[4][4] = { 0 };
    int nShape = (g_nShape + 1) % 4;
    for (size_t nRow = 0; nRow < 4; nRow++)
    {
        for (size_t nCol = 0; nCol < 4; nCol++)
        {
       
                chCurBrick[nRow][nCol] = g_chBrickPool[nRow+4*nShape+16*g_nType][nCol];//错误 2 误认为 直接等于g_chBrick;
           
        }
    }
    for (size_t nRow2 = 0; nRow2 < 4; nRow2++)
    {
        for (size_t nCol2 = 0; nCol2 < 4; nCol2++)
        {
            if (chCurBrick[nRow2][nCol2] == 1)
            {
                if (g_chBackGround[nRow2+g_nRow][nCol2+g_nCol]==1)
                {
                    return 0;
                }
            }
        }
    }
    return 1;
}

void Elimination()
{
    for (size_t nRow = GAME_ROW-2; nRow>0; nRow--)
    {
        for (int nCol = 1; nCol < GAME_COL-1; nCol++)
        {
            if (g_chBackGround[nRow][nCol] == 0)
            {
                break;
            }
            else
            {
                if (nCol == GAME_COL - 2)
                {
                    for (size_t nDexRow = nRow; nDexRow >0; nDexRow--)
                    {
                        for (size_t nDexCol = 0; nDexCol < GAME_COL-1; nDexCol++)
                        {
                            g_chBackGround[nDexRow][nDexCol] = g_chBackGround[nDexRow - 1][nDexCol];
                        }
                    }
                    nRow++;
                    g_nGrade += 10;
                }
               
            }
        }
    }
   
}

void GameStart()
{
    system("cls");
    InitBackGround();
    ShowBackGround();
    CurBrick();  //得到下次随机方块
    ShowNextBrick();//显示方块
    ShowOnceBrick();//作为开始的随机方块  原来是放在CurBrick前面但是,CurBrick能改变g_nShape所以放在后面
    clock_t clockStart = clock();
    clock_t clockFinish = clock(); //clock_t 其实就是long 类型

    while (1)
    {
        char chInput = 0;
        if (_kbhit() != 0)
        {
            chInput = _getch();
        }
        clockFinish = clock();
        if (clockFinish - clockStart > g_nSpeed)
        {

            OnDown(); //思考,下落固定,消行,得到下预测方块,显示下一个预测方块
            clockStart = clock();
        }

        switch (chInput)
        {
        case'a':
            OnLeft();
            break;
        case'd':
            OnRight();
            break;
        case'w':
            OnUp();
            break;
        case's':
            OnDown();
            break;
        case '4':
            return;
            break;
        case '5':
            getchar();
            break;
        default:
            break;
        }
        chInput = 0;

    }
   
}
void SeletSpeed()
{
    system("cls");
    printf("1.简单\r\n");
    printf("2.一般\r\n");
    printf("3.困难\r\n");
    printf("4.特别困难\r\n");
    int nValue = 0;
    scanf("%d", &nValue);
    switch (nValue)
    {
    case 1:
        g_nSpeed = 500;
        break;
    case 2:
        g_nSpeed = 300;
        break;
    case 3:
        g_nSpeed = 150;
        break;
    case 4:
        g_nSpeed = 50;
        break;
    default:
        break;
    }
    GameStart();
}

Model.h

#pragma once

#define GAME_ROW 16
#define GAME_COL 14

extern char g_chBackGround[GAME_ROW][GAME_COL];
extern char g_chBrick[4][4];
extern char g_chBrickPool[][4];
extern char g_chCurBrick[4][4];
extern int g_nRow ;//Brick的坐标
extern int g_nCol ;
extern int g_nType;
extern int g_nShape;
extern int g_nGrade;
extern int g_nSpeed;


void InitBackGround();
void GetNewBrick();
int IsCanMove(int nRowGobe, int nColGobe);
int IsCanRotate();
void Elimination();
void CurBrick();
void ShowOnceBrick();
void GameStart();
void SeletSpeed();

View.cpp

#include"View.h"
#include"Model.h"
#include"setdisplay.h"

void ShowGame();
int g_nShape1=0;
int g_nType1=0;


void ShowBrick()
{
 for (size_t nRow = 0; nRow < 4; nRow++)
 {
  for (size_t nCol = 0; nCol < 4; nCol++)
  {
   if (g_chBrick[nRow][nCol] == 1)
   {
    WriteChar(nRow+g_nRow,nCol+g_nCol , "■", 
     SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
   }
   else
   {
    WriteChar(nRow+g_nRow,nCol+g_nCol, "□",
     SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
   }

  }

 }
}


void ShowBackGround()
{
 for (size_t nRow = 0; nRow < GAME_ROW; nRow++)
 {
  for (size_t nCol = 0; nCol < GAME_COL; nCol++)
  {
   if (g_chBackGround[nRow][nCol] == 1)
   {
    WriteChar(nRow, nCol, "■",\
     SetConsoleColor(COLOR_YELLOW,COLOR_BLACK));
    
   }
   else
   {
    WriteChar(nRow, nCol, "□",\
     SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
   }

  }
 }
}

void Rotate()
{
 g_nShape1 = (g_nShape1 + 1) % 4;

 for (size_t nRow = 0; nRow < 4; nRow++)
 {
  for (size_t nCol = 0; nCol < 4; nCol++)
  {
   g_chBrick[nRow][nCol] = g_chBrickPool[nRow + g_nShape1 * 4 + g_nType1 * 16][nCol];

  }
 }
}


void OnLeft()
{
 if (IsCanMove(g_nRow, g_nCol-1))
 {
  g_nCol--;
  ShowGame();
	
 }
}
void OnRight()
{
 if (IsCanMove(g_nRow, g_nCol + 1))
 {
  g_nCol++;
  ShowGame();
  
 }
}
void OnDown()
{
 if (IsCanMove(g_nRow + 1, g_nCol))
 {
  g_nRow++;
  ShowGame();
 }
 else
 {
  CombineBG(); //固定方块
  Elimination();//判断消行
  ShowBackGround();//显示背景 不用ShowGame()
  GetNewBrick();//将此时的方块等于上一次预测的方块
  CurBrick();//进行下一次预测
  ShowNextBrick();//显示出来

 }
}
void OnUp()
{
 if (IsCanRotate())
 {
  Rotate();
  ShowGame();
 }

}
void CombineBG()
{
 for (size_t nRow = 0; nRow < 4; nRow++)
 {
  for (size_t nCol = 0; nCol < 4; nCol++)
  {
   if (g_chBrick[nRow][nCol]==1)
   {
    if (g_chBackGround[nRow + g_nRow][nCol + g_nCol] == 1) //如果融合背景的时候 就有方块了 那么证明 重合了 游戏就结束了
    {
     WriteChar(GAME_ROW, 0, "GAME OVER",
      SetConsoleColor(COLOR_RED, COLOR_BLACK));
     exit(0);
    }
    g_chBackGround[nRow+g_nRow][nCol+g_nCol] =1;//所犯的错误 == 1 那就不会产生任何作用。
   }
  }

 }
}
void SeparateBG()
{
 for (size_t nRow = 0; nRow < 4; nRow++)
 {
  for (size_t nCol = 0; nCol < 4; nCol++)
  {
   if (g_chBrick[nRow][nCol] == 1)
   {
    g_chBackGround[nRow+g_nRow][nCol+g_nCol] =0; //所犯的错误,== 0
   }
  }

 }
	
}
void ShowGame()
{
 ShowGrade();
 CombineBG();//已经将方块和背景合在一起了
 ShowBackGround();//直接显示
 SeparateBG();//再分离

}
void GameOver()
{
 /*int nFlag = 0;
 for (size_t nRow = 0; nRow <=1; nRow++)
 {
  for (size_t nCol = 1; nCol < GAME_COL - 1; nCol++)
  {
   if (g_chBackGround[nRow][nCol] == 1)
   {
    nFlag++;
   }
  }
 }
 if (nFlag >= 2)
 {
  WriteChar(GAME_ROW + 1, 0, "GAME OVER", 
           SetConsoleColor(COLOR_RED, COLOR_BLACK));
  exit(0);
 }*/
}

void ShowGrade()
{
 WriteChar(GAME_ROW / 2, GAME_COL + 2, "历史最高分:1640", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(GAME_ROW / 2 - 1, GAME_COL + 2, "YOUR GRADE:", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 printf("%d", g_nGrade);
 WriteChar(GAME_ROW / 2+1, GAME_COL + 2, "按4返回菜单", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(GAME_ROW / 2+2, GAME_COL + 2, "按5暂停游戏菜单,暂停后按Enter开始", SetConsoleColor(COLOR_RED, COLOR_BLACK));
	
}

void ShowNextBrick()
{
 for (size_t nRow = 0; nRow < 4; nRow++)
 {
  for (size_t nCol = 0; nCol < 4; nCol++)
  {
   if (g_chCurBrick[nRow][nCol] == 1)
   {
    WriteChar(nRow+2, GAME_COL+nCol+2, "■", SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
   }
   else
   {
    WriteChar(nRow+2, GAME_COL+nCol+2, "□", SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));

   }
  }

 }
	
}
void MainMeau()
{
 system("cls");
 WriteChar(0, 0, "************************************", SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
 WriteChar(1, 3, "欢迎来到俄罗斯方块游戏时间", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(2, 3, "请输入你想操作的数字", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(3, 3, "1.游戏介绍", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(4, 3, "2.开始游戏", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(5, 3, "3.退出界面", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(6, 3, "4.返回菜单", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 WriteChar(7, 0, "************************************", SetConsoleColor(COLOR_YELLOW, COLOR_BLACK));
}
void GameIntr()
{
 system("cls");
 WriteChar(0, 0, "《俄罗斯方块》(Tetris, 俄文:Тетрис)是一款由俄罗斯人阿列克谢·帕基特诺夫于1984年6月发明的休闲游戏。", SetConsoleColor(COLOR_WHITE, COLOR_BLACK));
 WriteChar(1, 0, "该游戏曾经被多家公司代理过。经过多轮诉讼后,该游戏的代理权最终被任天堂获得。任天堂对于俄罗斯方块来说意义重大,", SetConsoleColor(COLOR_WHITE, COLOR_BLACK));
 WriteChar(2, 0, "因为将它与GB搭配在一起后,获得了巨大的成功。", SetConsoleColor(COLOR_WHITE, COLOR_BLACK));
 WriteChar(3, 0, "《俄罗斯方块》的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。", SetConsoleColor(COLOR_WHITE, COLOR_BLACK));
 WriteChar(4, 0, "按4返回菜单", SetConsoleColor(COLOR_RED, COLOR_BLACK));
 int nCount;
 scanf("%d", &nCount);
 if (nCount == 4)
 {
  return;
 }
}

View.h

#pragma once

void ShowBackGround();
void ShowBrick();
void CombineBG();
void SeparateBG();
void ShowGame();
void GameOver();
void ShowGrade();
void ShowNextBrick();


void OnLeft();
void OnRight();
void OnDown();
void OnUp();
void MainMeau();
void GameIntr();

extern int g_nType1;
extern int g_nShape1;

彩色库代码(我从Linux改到window下的彩色库)
setdisplay.h

#pragma once
#include <windows.h>
#include <stdio.h>

/********控制台输出控制彩色内容*********/

/*************************************
这个彩色控制台的一个小问题:
    会比设置的高度多一行(最后一行),
    这一行可以输出内容,
    但不要输出内容到最后一列,
    否则界面会被挤下来一行,第一行会消失,
    意味着在设置满屏背景的情况下,
    要不最后一行全黑,
    要不右下角留一个窄黑块,
    测试&例子代码中第8个测试可以展示问题
**************************************/


/*********** 宽度的基本单位(整数) ***********/
// 设置为2意味着1列为2个英文宽度或1个汉字宽度      
#define WIDTH_UNIT 2  // 可根据需求修改



/*************************************
颜色属性
**************************************/
#define COLOR_BLACK             0x00    // 黑色
#define COLOR_BLUE              0x01    // 蓝色
#define COLOR_GREEN             0x02    // 绿色
#define COLOR_LIGHTBLUE         0x03    // 湖蓝色
#define COLOR_RED               0x04    // 红色
#define COLOR_PURPLE            0x05    // 紫色
#define COLOR_YELLOW            0x06    // 黄色
#define COLOR_WHITE             0x07    // 白色
#define COLOR_GRAY              0x08    // 灰色
#define COLOR_THIN_BLUE         0x09    // 淡蓝色
#define COLOR_THIN_GREEN        0x0A    // 淡绿色
#define COLOR_THIN_LIGHT_GREEN  0x0B    // 淡浅绿色
#define COLOR_THIN_RED          0x0C    // 淡红色
#define COLOR_THIN_PURPLE       0x0D    // 淡紫色
#define COLOR_THIN_YELLOW       0x0E    // 淡黄色
#define COLOR_LIGHT_WHITE       0x0F    // 亮白色


/*******************************
功能:设置前背景色

f 前景色
b 背景色

原理:
  1字节数据
  低4字节为前景,高4字节为背景
********************************/
#define SetConsoleColor( f , b ) ( ( f ) + ( ( b ) << 0x04 ) )


/***********************************
测试函数 & 例子
************************************/
void TestWindowSizeAndColor();


/*************************************
函数功能:打印字符到控制台制定位置
nHigh: 高度X行,行数
nWide: 宽度Y列,列数
pszChar: 打印的字符串(一个字符也要用字符串的形式)
wArr: 打印字符的属性:颜色
      可通过SetConsoleColor宏设置背景色

注意: 数据显示到界面上后会一直存在
      宽度 1 列为 1 个汉字 或 两个英文,
      可通过 宽度宏 WIDTH_UNIT 来控制
**************************************/
void WriteChar(int nHigh , int nWide , char* pszChar , WORD wArr);


/*************************************
函数功能: 设置窗口信息
*pszWindewTitle: 窗口名称
nHigh: 高度X行,行数
nWide: 宽度Y列,列数
成功返回值: TRUE

注意:数值设置太大会出错,尤其是高度
      宽度 1 列为 1 个汉字 或 两个英文,
      可通过 宽度宏 WIDTH_UNIT 来控制
*************************************/
BOOL SetWindowSize(char *pszWindowTitle , int nHigth, int nWide);


setdisplay.cpp

#include "setdisplay.h"


/*********************************
测试函数 & 例子
**********************************/
void TestWindowSizeAndColor()
{
  // 1. 设置控制台标题和窗口大小
  SetWindowSize("控制台颜色测试用例" , // 标题
                30, // 高度 30 行 // 在1920*1080的显示器中最大值为60
                30  // 宽度 30 列 // 1 列 = 1 个汉字 或 2 个英文 
                );

  // 2. 在第一行输出一段带背景的文字
  WriteChar(0 ,  // 第 1 行
            0 ,  // 第 1 列
            "这是一段带背景的文字0123456789ABCDEF" ,
            SetConsoleColor( COLOR_BLACK , // 黑色前景
                             COLOR_WHITE)  // 白色背景
            );


  // 3. 在第三行输出一行淡浅绿色
  char szBuff[ MAXBYTE ] = { 0 };
  // 设置一个内容为60个空格的字符串
  sprintf_s(szBuff , MAXBYTE , "%60c" , ' ');
  WriteChar(2 ,  // 第 3 行
            0 ,  // 第 1 列
            szBuff ,   // 60个空格
            SetConsoleColor( COLOR_BLACK , // 黑色前景
                             COLOR_THIN_LIGHT_GREEN )  // 淡浅绿色
            );
            

  // 4. 在第五行输出一段浅绿色换行文字
  WriteChar(4 ,  // 第 5 行
            0 ,  // 第 1 列
            "这是一段换行的白文字\n0123456789ABCDEF<--这些文字被输出到了第六行,并且支持自动换行,多余的内容会自动到下一行" ,
            COLOR_THIN_GREEN
            );


  // 5. 在屏幕中间打印16种颜色
  // 主要方法通过给空格设置背景色
  for(int i = 0; i < 0x04; ++i)
  {
    for(int j = 0; j < 0x04; ++j)
    {
      WriteChar(i + 12 , // 从第13行开始
                j + 12 , // 从第13列开始
                "  " , // 两个空格
                SetConsoleColor( COLOR_BLACK , // 黑色前景 
                                 (WORD)(i * 4 + j) )    // 背景色
                );
    }
  }


  // 6. 在倒数第三行输出一段带背景的符号
  WriteChar(27 ,  // 第 28 行
            0 ,   // 第 1 列
            "符号:§№☆★○●◎◇◆□■△▲※→←↑↓〓#@&\^_ ̄  " ,
            SetConsoleColor( COLOR_THIN_BLUE ,   // 浅蓝前景
                             COLOR_LIGHT_WHITE)  // 亮白色背景
            );


  // 7. 在最后一行输出一行亮白色
  WriteChar(29 ,  // 第 30 行
            0 ,  // 第 1 列
            szBuff,
            SetConsoleColor( COLOR_BLACK , // 黑色前景
                             COLOR_LIGHT_WHITE )  // 亮白色背景
            );


  // 8. 问题展现
  // 在最后多出的一行输出内容
  WriteChar(30 ,  // 第 31 行
            0 ,   // 第 1 列
            "无法避免的Bug描述:设置30行,但这是第31行,再多加个空格来试试 " ,
            SetConsoleColor( COLOR_THIN_BLUE ,   // 浅蓝前景
                             COLOR_LIGHT_WHITE)  // 亮白色背景
            );
}


/*************************************
函数功能:打印字符到控制台制定位置
nHigh: 高度X行,行数
nWide: 宽度Y列,列数
pszChar: 打印的字符串(一个字符也要用字符串的形式)
wArr: 打印字符的属性:颜色
      可通过SetConsoleColor宏设置背景色

注意: 数据显示到界面上后会一直存在
      宽度 1 列为 1 个汉字 或 两个英文,
      可通过 宽度宏 WIDTH_UNIT 来控制
*************************************/
void WriteChar(int nHigh , int nWide , char* pszChar , WORD wArr)
{
	CONSOLE_CURSOR_INFO cii;
	cii.dwSize = 1;
	cii.bVisible = FALSE;
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE) , &cii);
	COORD loc;
	loc.X = nWide * (WIDTH_UNIT);
	loc.Y = nHigh;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE) , wArr);
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE) , loc);
	printf(pszChar);
}


/*************************************
函数功能: 设置窗口信息
*pszWindewTitle: 窗口名称
nHigh: 高度X行,行数
nWide: 宽度Y列,列数
成功返回值: TRUE

注意:数值设置太大会出错,尤其是高度
      宽度 1 列为 1 个汉字 或 两个英文,
      可通过 宽度宏 WIDTH_UNIT 来控制
*************************************/
BOOL SetWindowSize(char *pszWindowTitle , int nHight, int nWide)
{
	// Title
  nWide *= (WIDTH_UNIT);
  // nHight -= 1;
  nWide -= 1;
	SetConsoleTitleA(pszWindowTitle);
	HANDLE hStdin , hStdOut;
	hStdin = GetStdHandle(STD_INPUT_HANDLE);
	hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
	// get max console window size
	COORD pos = GetLargestConsoleWindowSize(hStdOut);
	COORD BufferSize = { pos.X , pos.Y };
	// set console buffer size
	if(!SetConsoleScreenBufferSize(hStdOut , BufferSize)){
		// set console buffer size FALSE
		printf("buffer err(%d,%d)%d\n" , BufferSize.X , BufferSize.Y , GetLastError());
		return FALSE;
	}
	SMALL_RECT srctWindow = { 0 , 0 , nWide , nHight };
	if(!SetConsoleWindowInfo(hStdOut , TRUE , &srctWindow)){
		// set console window size FALSE
		printf("size err %d\n" , GetLastError());
		return FALSE;
	}
	COORD Buffer = { nWide + 1 , nHight + 1 };
	// set console buffer size
	if(!SetConsoleScreenBufferSize(hStdOut , Buffer)){
		// set console buffer size FALSE
		printf("buffer err(%d, %d)%d\n" , BufferSize.X , BufferSize.Y , GetLastError());
		return FALSE;
	}
	return TRUE;
}

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值