在不优化编译器的情况下减小C程序的大小

问题描述

我正试图用c编写一个扫雷游戏,该游戏足够紧凑以适合qr代码,就像其他人用蛇所做的一样。就目前而言,我的程序大约需要2.98 KB,目前为58KB。

在继续尝试实现一些编译器魔术之前,我想知道如何优化我的代码预编译器。我的方法可行吗,是否必须完全不同,或者是否在不使用汇编的情况下将扫雷程序安装到如此小的尺寸中是不可能的?我的代码可以在这里看到:

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

#define WIDTH 100
#define HEIGHT 100
#define BOMBS 799

#define KEY_UP 72
#define KEY_DOWN 80
#define KEY_LEFT 75
#define KEY_RIGHT 77

HANDLE wHnd;
HANDLE rHnd;

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

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

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

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

void ExpandGrid(int fullGrid[WIDTH][HEIGHT],int kNownGrid[WIDTH][HEIGHT],int blankPos[2])
{
    int neighbors[8][2] = {{0,1},{1,0},{0,-1},{-1,-1}};
    int curTile[2];

    kNownGrid[blankPos[0]][blankPos[1]] = 1;
    if(fullGrid[blankPos[0]][blankPos[1]] != 0) return;

    for(int blck = 0; blck < 8; ++blck)
    {
        curTile[0] = abs(blankPos[0]+neighbors[blck][0]);
        curTile[1] = abs(blankPos[1]+neighbors[blck][1]);
        if(curTile[0] > WIDTH-1 || curTile[1] > HEIGHT-1) continue;

        if(fullGrid[curTile[0]][curTile[1]] == 0 && kNownGrid[curTile[0]][curTile[1]] == 0)
        {
            kNownGrid[curTile[0]][curTile[1]] = 1;
            ExpandGrid(fullGrid,kNownGrid,curTile);
        }
        else if(fullGrid[curTile[0]][curTile[1]] > 0) kNownGrid[curTile[0]][curTile[1]] = 1;
    }
}

int main(void)
{

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

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

    CHAR_INFO consoleBuffer[WIDTH][HEIGHT];

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

    SetConsoleTitle("minesweeper!");

    SetConsoleWindowInfo(wHnd,TRUE,&windowSize);

    srand((unsigned int)time(NULL));

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

    int startCoord[2] = {0,0};
    int arrowPos[2] = {0,0};

    ExpandGrid(startGrid,startCoord);

    while(1)
    {
        if (arrowPos[0] > WIDTH-1) arrowPos[0] = WIDTH-1;
        if (arrowPos[0] < 0) arrowPos[0] = 0;
        if (arrowPos[1] > HEIGHT-1) arrowPos[1] = HEIGHT-1;
        if (arrowPos[1] < 0) arrowPos[1] = 0;

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

                if (kNownGrid[x][y] == 1)
                {
                    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 = 'o';
                        consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
                    }
                }
                else
                {
                    consoleBuffer[x][y].Char.AsciiChar = 00;
                    consoleBuffer[x][y].Attributes = FOREGROUND_BLUE | FOREGROUND_INTENSITY;
                }

                if(arrowPos[0] == x && arrowPos[1] == y)
                {
                    consoleBuffer[x][y].Attributes = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
                }
            }
        }

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

        switch(getch())
        {
            case KEY_UP:
                arrowPos[0]--;
                break;
            case KEY_DOWN:
                arrowPos[0]++;
                break;
            case KEY_LEFT:
                arrowPos[1]--;
                break;
            case KEY_RIGHT:
                arrowPos[1]++;
                break;
            case '\r':
                ExpandGrid(startGrid,arrowPos);
                break;
        }
    }
}

解决方法

从58K减少到3K是一个很大的问题。

一些想法:

  • 检查在构建过程中链接到的库,并将其减少到最低限度;消除对您可能可以编写的库函数的调用。
  • 可能使用较短的类型。您需要int吗?您可以改用字节(char还是short吗?
  • 考虑您确实需要windows.hstdlib.h的哪些部分。