首页 > 解决方案 > c程序的窗口大小调整影响元素位置

问题描述

我想在 c 中创建一个扫雷生成器,每当我运行程序时,要么窗口出现奇怪的形状,从而改变元素的位置以使其看起来不正确,或者我用来生成图块的函数生成不正确。我将如何解决这两个问题?我的代码在这里:

#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */


#define WIDTH 70
#define HEIGHT 35
#define BOMBS 20

HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */

void SetGrid(int grid[WIDTH][HEIGHT])
{
  int bomb[2] = {abs(rand() % WIDTH),
                 abs(rand() % HEIGHT)};

  for (int i = 0; i < BOMBS; i++)
  {
     while (grid[bomb[0]][bomb[1]] < -1)
     {
        bomb[0] = abs(rand() % WIDTH);
        bomb[1] = abs(rand() % HEIGHT);
     }

     grid[bomb[0]][bomb[1]] = -9;

     grid[bomb[0]+1][bomb[1]+1]++;
     grid[bomb[0]-1][bomb[1]-1]++;
     grid[bomb[0]-1][bomb[1]+1]++;
     grid[bomb[0]+1][bomb[1]-1]++;
     grid[bomb[0]-1][bomb[1]]++;
     grid[bomb[0]+1][bomb[1]]++;
     grid[bomb[0]][bomb[1]-1]++;
     grid[bomb[0]][bomb[1]+1]++;
  }

}

int main(void)
{

  srand(time(0));

  SMALL_RECT windowSize = {0, 0, WIDTH - 1, HEIGHT - 1};

  COORD bufferSize = {WIDTH, HEIGHT};

  COORD characterBufferSize = {WIDTH, HEIGHT};
  COORD characterPosition = {0, 0};
  SMALL_RECT consoleWriteArea = {0, 0, WIDTH - 1, HEIGHT - 1};

  CHAR_INFO consoleBuffer[WIDTH][HEIGHT];

  wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
  rHnd = GetStdHandle(STD_INPUT_HANDLE);

  SetConsoleTitle("Our shiny new title!");

  SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
  SetConsoleScreenBufferSize(wHnd, bufferSize);

  int startGrid[WIDTH][HEIGHT] = {0};
  SetGrid(startGrid);

  for (int x = 0; x < WIDTH; ++x)
  {
    for (int y = 0; y < HEIGHT; ++y)
    {

      if(startGrid[x][y] > 0)
      {
         consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
         consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
      }
      else
      {
         consoleBuffer[x][y].Char.AsciiChar = (unsigned char)219;
         consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
      }

    }

  }

  WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
  getchar();
}

标签: cwinapiwindows-console

解决方案


您需要处理几个边界问题。

  1. 四个角默认为-4
  2. 除了四个角,边框是-6(虽然你没用过)
  3. 重要:边界处的增加考虑是否超出边界。

这是代码:

#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */

#define WIDTH 30
#define HEIGHT 30
#define BOMBS 10

HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
int check(int a)
{
    if (a == 0 || a == WIDTH - 1 || a == HEIGHT - 1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}

void SetGrid(int grid[WIDTH][HEIGHT])
{
    int bomb[2] = { abs(rand() % WIDTH),
                   abs(rand() % HEIGHT) };
    char t[100];
    for (int i = 0; i < BOMBS; i++)
    {
        while (grid[bomb[0]][bomb[1]] < -1)
        {
            bomb[0] = abs(rand() % WIDTH);
            bomb[1] = abs(rand() % HEIGHT);
        }

        grid[bomb[0]][bomb[1]] = -9;
        if (check(bomb[0]) || check(bomb[1])) grid[bomb[0]][bomb[1]] = -6;
        if (check(bomb[0]) && check(bomb[1])) grid[bomb[0]][bomb[1]] = -4;
        if (bomb[0] + 1 <= WIDTH - 1 && bomb[1] + 1 <= HEIGHT - 1)
        {
            grid[bomb[0] + 1][bomb[1] + 1]++;
        }
        if (bomb[0] + 1 <= WIDTH - 1)
        {
            grid[bomb[0] + 1][bomb[1]]++;
        }
        if (bomb[1] + 1 <= HEIGHT - 1)
        {
            grid[bomb[0]][bomb[1] + 1]++;

        }
        if (bomb[0] - 1 >= 0 && bomb[1] + 1 <= HEIGHT - 1)
        {
            grid[bomb[0] - 1][bomb[1] + 1]++;
        }
        if (bomb[1] - 1 >= 0)
        {
            grid[bomb[0]][bomb[1] - 1]++;

        }
        if (bomb[1] - 1 >= 0 && bomb[0] + 1 <= WIDTH - 1)
        {
            grid[bomb[0] + 1][bomb[1] - 1]++;

        }
        if (bomb[0] - 1 >= 0 && bomb[1] - 1 >= 0)
        {
            grid[bomb[0] - 1][bomb[1] - 1]++;
        }
        if (bomb[0] - 1 >= 0)
        {
            grid[bomb[0] - 1][bomb[1]]++;
        }
    }
}

int main(void)
{

    srand(time(0));

    SMALL_RECT windowSize = { 0, 0, WIDTH - 1, HEIGHT - 1 };

    COORD bufferSize = { WIDTH, HEIGHT };

    COORD characterBufferSize = { WIDTH, HEIGHT };
    COORD characterPosition = { 0, 0 };
    SMALL_RECT consoleWriteArea = { 0, 0, WIDTH - 1, HEIGHT - 1 };

    CHAR_INFO consoleBuffer[WIDTH][HEIGHT];

    wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
    rHnd = GetStdHandle(STD_INPUT_HANDLE);

    SetConsoleTitle("Our shiny new title!");

    SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
    SetConsoleScreenBufferSize(wHnd, bufferSize);

    int startGrid[WIDTH][HEIGHT] = { 0 };
    SetGrid(startGrid);

    for (int x = 0; x < WIDTH; ++x)
    {
        for (int y = 0; y < HEIGHT; ++y)
        {

            if (startGrid[x][y] > 0)
            {
                consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
                consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
            }
            else
            {
                consoleBuffer[x][y].Char.AsciiChar = (unsigned char)111;
                consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
            }

        }

    }
    WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
    printf("\n\n");

    getchar();
}

推荐阅读