#c #optimization #compilation #compiler-optimization
#c #оптимизация #Сборник #компилятор-оптимизация
Вопрос:
Я пытаюсь создать игру minesweeper на c, которая была бы достаточно компактной, чтобы поместиться в qr-код, как некоторые другие люди сделали со snake. В нынешнем виде моя программа должна иметь размер около 2,98 КБ, а в настоящее время она составляет 58 КБ.
Прежде чем я перейду к попыткам сотворить какое-нибудь волшебство компилятора, я хотел бы знать, как можно усовершенствовать мой предварительный компилятор кода. Выполним ли мой подход, должен ли он быть совершенно другим, или подгонка программы minesweeper к такому небольшому размеру невозможна без использования assembly? Мой код можно увидеть здесь:
#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}, {1,1},
{0,-1}, {-1,0},
{-1,-1},{-1,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 amp;amp; 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, 0, WIDTH - 1, HEIGHT - 1 };
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("Minesweeper!");
SetConsoleWindowInfo(wHnd, TRUE, amp;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, knownGrid, 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 amp;amp; arrowPos[1] == y)
{
consoleBuffer[x][y].Attributes = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
}
}
}
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, amp;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, knownGrid, arrowPos);
break;
}
}
}
Комментарии:
1. Лучше подходит для этого вопроса при обзоре кода.
2. Это может поместиться как код на C, если вы используете запутанный c. Для этого доступны инструменты. Что касается скомпилированной, без оптимизации … нет.
Ответ №1:
Уменьшение с 58K до 3K — довольно большая просьба.
Несколько идей:
- Изучите библиотеки, которые связаны в процессе сборки, и сократите их до минимума; Исключите вызовы библиотечных функций, которые вы могли бы написать самостоятельно.
- Возможно использование более коротких типов. Вам нужно
int
? Можете ли вы использовать байт (char
) илиshort
вместо? - Подумайте, какие части
windows.h
иstdlib.h
вам действительно нужны.