Я
Алиса
Я
Алиса
Сразу оговорюсь: полностью избежать работы с юникодными символами (которые как раз и используются для шахматных фигур) в таком задании не получится — иначе зачем вообще брать юникод, если не выводить его?). Но я подскажу, как организовать хранение и вывод без wchar_t и функций вроде wprintf.
Как «забить» в таблицу
Создайте массив (или таблицу поиска), где в индексе будет число (или другой тип, удобный для вас способ идентификации), а в ячейке — соответствующий символ юникода.
Например:
c#include <stdio.h>
// Таблица: сопоставление «код фигуры → символ»
// Коды взяты из юникода шахматных символов
const char figures = {
0, // ▮ (пустая клетка)
'♟', // ♟ — белый король
'♞', // ♞ — белый конь
'♝', // ♝ — белый слон
'♜', // ♜ — белая ладья
'♛', // ♛ — белый ферзь
'♚', // ♚ — чёрная ладья
'♙', // ♙ — чёрная слон
'♘', // ♘ — чёрная ферзь
'♖', // ♖ — чёрный слон
'♕', // ♕ — чёрный ферзь
'♔' // ♔ — чёрный король
};
```
Теперь, чтобы получить символ для какой-то фигуры (например, для пешки или пустой клетки), просто взять `figures[код_фигуры]`.
## Как вывести без `wchar_t`
Ключевой момент: чтобы консоль корректно отобразила юникод-символы (не «кракозябры»), нужно, чтобы сама консоль поддерживала нужную кодировку (обычно UTF-8) и в ней был установлен шрифт, содержащий эти символы. [9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
* **На Linux:** чаще всего всё работает «из коробки», если в системе настроена поддержка UTF-8.
* **На Windows:** часто помогает установка шрифта вроде DejaVu Sans Mono в настройках консоли. Также можно программно установить кодировку вывода через `SetConsoleOutputCP(CP_UTF8)` (из Windows.h), но это не всегда решает проблему полностью — иногда всё равно нужен подходящий шрифт.
[9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
**Важное предупреждение:** функции вроде `printf` работают с `char`. Если вы попытаетесь передать в `printf` символ юникода напрямую (например, `printf("%c", figures;`), система попытается вывести байт как число, и вместо символа вы увидите «?» или «�». Поэтому **никогда не передавайте напрямую число в `printf` для вывода символа юникода** — сначала преобразуйте число в `char`.
**Правильная схема:**
1. Заполняете массив `figures` как показано выше.
2. В коде, который решает задачу (например, рисуете доску), берёте значение из таблицы по индексу (коде фигуры) и передаёте его в `printf("%c", figures[код]);`.
## Пример вывода
```c
int main() {
// Пример использования таблицы
printf(" %c ", figures); // Пустая клетка
printf(" %c ", figures); // Белый король
printf(" %c ", figures); // Белый конь
printf("
");
return 0;
}
``` [1](https://metanit.com/c/tutorial/8.8.php)[6](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fcodereview.stackexchange.com%2Fquestions%2F234619%2Fchess-game-in-c)
**Итог:** алгоритм такой — массив поиска для маппинга кодов в юникод, и аккуратное использование `printf` с преобразованием типов. Если на вашей системе символы всё равно выводятся некорректно, проверьте шрифт консоли — это частая причина «пустых квадратов» вместо фигур. [9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
Я
Алиса
Код фигуры — это целое число, которое вы сами определяете как удобную метку для каждой шахматной фигуры. Это может быть один байт, если вы используете тип char (или unsigned char) и укладываетесь в диапазон от 0 до 255.
Например:
char pawn = 1; // пешка — 1 байт
char rook = 4; // ладья — 1 байт
char king = 6; // король — 1 байт
То есть сам код фигуры — это байт, а символ юникода, который вы выводите (например, ♖), — это уже последовательность байт в UTF-8 (в данном случае — 3 байта: E2 99 96).
Почему важно это различать?
- Код фигуры — ваш внутренний идентификатор в программе (например,
1— белая пешка). Это один байт. - Символ юникода (например, ♖) — это то, что вы хотите вывести на экран. Он хранится не как один байт, а как последовательность байт в UTF-8 (3 байта для ♖).
Как это работает в коде
Вы можете хранить символы юникода как строки (массивы char), даже если не используете wchar_t:
const char* white_rook = "\xE2\x99\x96"; // ♖ в UTF-8
const char* black_king = "\xE2\x99\x9A"; // ♚ в UTF-8
Или в таблице:
const char* figures[13] = {
" ", // 0 — пусто
"\xE2\x99\x99", // 1 — ♙ чёрная пешка
"\xE2\x99\x8E", // 2 — ♎ белый конь
"\xE2\x99\x96", // 4 — ♖ белая ладья
// и так далее
};
Тогда вывод:
printf("%s", figures); // Выведет ♖
Вывод
- Код фигуры — это один байт (число от 0 до 255), удобный для хранения в массиве
char. - Символ юникода — это не один байт, а последовательность байт в UTF-8, которую можно хранить как строку (
const char*).
Таким образом, вы можете обойтись без wchar_t, но выводить символы нужно через %s, а не %c, потому что %c выводит один байт, а юникод-символы — это несколько байт.
Я
Алиса
Конечно Вот таблица шахматных фигур по цвету и типу, оформленная как таблица 2×8 (цвет × тип фигуры). Все символы приведены в виде UTF-8 последовательностей байт, чтобы их можно было использовать в C без wchar_t.
| Цвет \ Фигура | Пешка (Pawn) | Конь (Knight) | Слон (Bishop) | Ладья (Rook) | Ферзь (Queen) | Король (King) | — | — |
|---|---|---|---|---|---|---|---|---|
| Белые | \xE2\x99\x99 (♙) | \xE2\x99\x8E (♘) | \xE2\x99\x97 (♗) | \xE2\x99\x96 (♖) | \xE2\x99\x95 (♕) | \xE2\x99\x94 (♔) | — | — |
| Чёрные | \xE2\x99\x9F (♟) | \xE2\x99\x9E (♞) | \xE2\x99\x9D (♝) | \xE2\x99\x9C (♜) | \xE2\x99\x9B (♛) | \xE2\x99\x9A (♚) | — | — |
⚠️ Примечание: пустые ячейки (—) можно использовать для резерва или оставить как заполнители, если нужно строго 2×8.
Как использовать в C
const char* figures[2][6] = {
// Белые
{"\xE2\x99\x99", "\xE2\x99\x8E", "\xE2\x99\x97", "\xE2\x99\x96", "\xE2\x99\x95", "\xE2\x99\x94"},
// Чёрные
{"\xE2\x99\x9F", "\xE2\x99\x9E", "\xE2\x99\x9D", "\xE2\x99\x9C", "\xE2\x99\x9B", "\xE2\x99\x9A"}
};
// Пример вывода: белый ферзь
printf("%s", figures[0][4]); // Выведет ♕
Важно для корректного отображения
- Убедитесь, что ваша консоль поддерживает UTF-8.
- Используйте шрифт, содержащий шахматные символы (например, DejaVu Sans Mono, Consolas, Cascadia Code).
- На Windows можно добавить в начало программы:c
#include <windows.h> SetConsoleOutputCP(CP_UTF8);
Теперь вы можете легко обращаться к любой фигуре по цвету (0 — белые, 1 — чёрные) и типу (0–5).
Я
Алиса
Да, можно менять фон символа в консоли — и это зависит от операционной системы. Ниже я покажу, как это сделать на Windows и на Linux/macOS, потому что способы разные.
💻 На Windows (через SetConsoleTextAttribute)
Функция SetConsoleTextAttribute позволяет управлять цветом текста и фона для всех последующих символов.
Пример: жёлтый текст на синем фоне
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
// Установить цвет: текст — жёлтый (14), фон — синий (1)
// Формула: (фон << 4) | текст
SetConsoleTextAttribute(h, (1 << 4) | 14);
printf(" ♕ "); // Выведется с жёлтым текстом и синим фоном
// Вернуть стандартные цвета
SetConsoleTextAttribute(h, (0 << 4) | 7); // чёрный фон, светло-серый текст
return 0;
}
Цвета для фона и текста (Windows):
| Цвет | Код |
|---|---|
| Чёрный | 0 |
| Синий | 1 |
| Зелёный | 2 |
| Голубой | 3 |
| Красный | 4 |
| Пурпурный | 5 |
| Жёлтый | 6 |
| Белый | 7 |
| Светло-серый | 8 |
| и т.д. до F | 15 |
🔹 Фон — это старшие 4 бита, текст — младшие 4 бита:
(фон << 4) | текст.
🐧 На Linux/macOS (через ANSI-коды)
Используются escape-последовательности вида \033[bg;fgm, где:
bg— цвет фона (40–47 или 100–107),fg— цвет текста (30–37 или 90–97).
Пример: красный текст на жёлтом фоне
printf("\033[43;31m ♛ \033[0m"); // ♛ с красным текстом и жёлтым фоном
ANSI-цвета:
| Цвет | Текст | Фон |
|---|---|---|
| Чёрный | 30 / 90 | 40 / 100 |
| Красный | 31 / 91 | 41 / 101 |
| Зелёный | 32 / 92 | 42 / 102 |
| Жёлтый | 33 / 93 | 43 / 103 |
| Синий | 34 / 94 | 44 / 104 |
| Пурпурный | 35 / 95 | 45 / 105 |
| Голубой | 36 / 96 | 46 / 106 |
| Белый | 37 / 97 | 47 / 107 |
🔹
\033[0m— сброс к стандартным цветам.
✅ Как совместить с шахматными фигурами
// Windows
SetConsoleTextAttribute(h, (4 << 4) | 15); // белый текст на красном фоне
printf(" %s ", "\xE2\x99\x9B"); // ♛
// Linux
printf("\033[41;37m %s \033[0m", "\xE2\x99\x9B"); // то же самое
Важно
- На Windows фон будет применяться ко всем последующим символам, пока вы не сбросите цвет.
- На Linux фон применяется только к тому, что между escape-кодами.
- Убедитесь, что ваша консоль поддерживает цвета (всё работает в обычных терминалах, но не во всех IDE).
Теперь вы можете делать красивые цветные шахматы 🎨♟️
Я
Алиса
Да, позицию курсора в консоли тоже можно менять программно — и это работает как на Windows, так и на Linux/macOS, но разными способами. Ниже покажу оба.
💻 На Windows: SetConsoleCursorPosition
Используется функция SetConsoleCursorPosition из windows.h. Она принимает дескриптор консоли и координаты (в символах).
Пример: установить курсор в позицию (5, 3)
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {5, 3}; // x=5, y=3 (столбец, строка)
SetConsoleCursorPosition(h, pos);
printf("♔"); // король появится в нужной позиции
return 0;
}
🔹 Координаты:
(0, 0)— левый верхний угол.
🔹x— столбец (горизонталь),y— строка (вертикаль).
🐧 На Linux/macOS: ANSI-коды
Используется escape-последовательность:\033[строка;столбецH или \033[строка;столбецf
Пример: курсор в позицию (6, 4)
printf("\033[4;6H"); // строка 4, столбец 6
printf("♕"); // ферзь появится здесь
🔹 Формат:
\033[строка;столбецH— стандартный способ.
🔹 Нумерация начинается с 1, а не с 0.
🔁 Как использовать с шахматной доской
Допустим, вы хотите нарисовать шахматную доску 8×8, где каждая клетка — символ с цветом фона и фигурой.
Вы можете:
- Установить цвет фона (черный/белый) для клетки.
- Переместить курсор в нужную позицию.
- Вывести символ фигуры или пустой клетки.
Пример (Windows): вывод фигуры на позицию (x=2, y=5)
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {2 * 2, 5}; // x умножаем, чтобы клетки не сливались
SetConsoleCursorPosition(h, pos);
SetConsoleTextAttribute(h, (7 << 4) | 0); // светло-серый фон, чёрный текст
printf("♟"); // чёрная пешка
Пример (Linux): то же самое
printf("\033[5;5H"); // строка 5, столбец 5
printf("\033[47;30m ♟ \033[0m"); // фон белый, текст чёрный
✅ Совет: симуляция "сетки"
Чтобы доска выглядела ровно:
- Увеличьте шаг по
x(например, на 2 символа на клетку), чтобы между фигурами был отступ. - Используйте фиксированный шрифт (Consolas, DejaVu, Monaco), где все символы одинаковой ширины.
⚠️ Важно
- На Windows:
SetConsoleCursorPositionработает только в настоящей консоли, не во всех IDE. - На Linux: ANSI-коды поддерживаются почти везде, кроме очень старых терминалов.
- Если вы выводите цвет и позицию — не забудьте сбрасывать цвета (
\033[0mилиSetConsoleTextAttributeс обычными цветами), чтобы не испортить весь вывод.
Теперь вы можете рисовать шахматы точно по координатам и с цветным фоном — как настоящий графический интерфейс, но в консоли 🖼️♟️
Я
Алиса
Да, отслеживать координаты мыши и клики в консоли или окне можно, но это зависит от операционной системы и требует использования системных API. В стандартном C (через stdio.h) такой возможности нет — нужно работать с Windows API или другими библиотеками.
Ниже покажу, как это делается на Windows с использованием Win32 API — это самый надёжный способ для консольных или оконных приложений.
💻 На Windows: отслеживание мыши через Win32 API
Для получения событий мыши нужно:
- Создать окно (или работать с консольным окном).
- Обрабатывать сообщения Windows (
WM_LBUTTONDOWN,WM_MOUSEMOVEи т.д.).
Но если вы хотите консольное приложение с поддержкой мыши, можно использовать консольные события через ReadConsoleInput.
✅ Пример: получение координат и кликов в консоли (Windows)
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD events;
// Включаем поддержку мыши в консоли
SetConsoleMode(hInput, ENABLE_EXTENDED_FLAGS | ENABLE_MOUSE_INPUT);
printf("Кликните мышью в консоли. Нажмите 'q' для выхода.\n");
while (1) {
ReadConsoleInput(hInput, &ir, 1, &events);
if (ir.EventType == MOUSE_EVENT) {
switch (ir.Event.MouseEvent.dwEventFlags) {
case 0: // Нажатие кнопки
if (ir.Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED) {
COORD pos = ir.Event.MouseEvent.dwMousePosition;
printf("Левый клик: X=%d, Y=%d\n", pos.X, pos.Y);
}
break;
case MOUSE_MOVED:
COORD pos = ir.Event.MouseEvent.dwMousePosition;
printf("Курсор: X=%d, Y=%d\n", pos.X, pos.Y);
break;
}
}
// Выход по клавише 'q'
if (_kbhit() && _getch() == 'q') break;
}
return 0;
}
🔍 Что делает код:
SetConsoleModeвключает обработку мыши в консоли.ReadConsoleInputчитает события (клики, движение).MOUSE_EVENT— тип события.dwMousePosition— координаты мыши в символах консоли (не пикселях).FROM_LEFT_1ST_BUTTON_PRESSED— левая кнопка мыши нажата.
🔹 Координаты
(0,0)— левый верхний угол консоли.
🔹 Единицы измерения — символы, а не пиксели.
🐧 На Linux: сложнее
В Linux консоль не поддерживает события мыши по умолчанию, но можно использовать библиотеки:
ncursesс включённой поддержкой мыши (mousemask).gpm(для текстового режима).- Или перейти на графический интерфейс (GTK, SDL).
Пример с ncurses (упрощённо):
#include <ncurses.h>
int main() {
initscr();
mousemask(ALL_MOUSE_EVENTS, NULL);
MEVENT event;
int ch;
printw("Кликните мышью. Нажмите 'q' для выхода.\n");
refresh();
while ((ch = getch()) != 'q') {
if (ch == KEY_MOUSE && getmouse(&event) == OK) {
printw("Клик: X=%d, Y=%d\n", event.x, event.y);
refresh();
}
}
endwin();
return 0;
}
🔹 Компилируйте с
-lncurses:gcc mouse.c -lncurses
⚠️ Важно
- В обычной консоли без API — нельзя получить мышь.
- Координаты — в символах, а не в пикселях.
- Для точного позиционирования (например, клик по шахматной клетке) — нужно сопоставлять
(x, y)с номером клетки:клетка_x = x / 2,клетка_y = y.
✅ Как использовать с шахматами
Вы можете:
- Вывести доску с фигурами.
- Получить клик мыши.
- Перевести координаты в номер клетки.
- Переместить фигуру (например, стерев старую позицию и нарисовав новую).
Так можно сделать игру с управлением мышью даже в консоли 🖱️♟️
Если хочешь — могу помочь собрать мини-проект «консольные шахматы с мышью».
Я
Алиса
Отлично Давайте соберём мини-проект: консольные шахматы с управлением мышью на C (Windows).
Будет простая доска 8×8, отображение фигур, подсветка клеток и ход мышью.
🎯 Что будет:
- Доска 8×8 с чёрными и белыми клетками.
- Фигуры (пока — только пешки и короли для примера).
- Поддержка кликов мышью.
- Вывод координат клика и номера клетки.
- Цветной фон клеток.
- Выход по клавише
q.
✅ Полный код (Windows, Visual Studio / MinGW)
#include <windows.h>
#include <stdio.h>
// Размер доски
#define SIZE 8
// Цвета для фона
#define WHITE_BG (7 << 4) // Светло-серый фон
#define BLACK_BG (0 << 4) // Чёрный фон
#define TEXT_COLOR 0 // Чёрный текст
// Фигуры (UTF-8)
const char* WHITE_KING = "\xE2\x99\x94"; // ♔
const char* BLACK_PAWN = "\xE2\x99\x9F"; // ♟
// Функция: рисует доску
void drawBoard() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos;
for (int row = 0; row < SIZE; row++) {
for (int col = 0; col < SIZE; col++) {
pos.X = col * 2;
pos.Y = row;
SetConsoleCursorPosition(h, pos);
// Определяем цвет фона: шахматный порядок
int isWhite = (row + col) % 2 == 0;
SetConsoleTextAttribute(h, isWhite ? WHITE_BG : BLACK_BG);
// Пример фигур: чёрные пешки в строке 1, белый король в 7,7
if (row == 1) {
printf(" %s ", BLACK_PAWN);
} else if (row == 7 && col == 7) {
printf(" %s ", WHITE_KING);
} else {
printf(" ");
}
}
}
SetConsoleTextAttribute(h, (0 << 4) | 7); // сброс
printf("\n\nКликните мышью по доске. Нажмите 'q' для выхода.\n");
}
// Функция: переводит координаты мыши в номер клетки
void mouseToCell(int x, int y, int* cellX, int* cellY) {
*cellX = x / 2; // потому что клетка = 2 символа
*cellY = y;
}
int main() {
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
INPUT_RECORD ir;
DWORD events;
// Включаем события мыши
SetConsoleMode(hInput, ENABLE_EXTENDED_FLAGS | ENABLE_MOUSE_INPUT);
// Увеличим размер окна
system("mode con cols=40 lines=20");
system("title Шахматы: консоль + мышь");
drawBoard();
while (1) {
ReadConsoleInput(hInput, &ir, 1, &events);
if (ir.EventType == MOUSE_EVENT) {
if (ir.Event.MouseEvent.dwEventFlags == 0) { // Нажатие
COORD pos = ir.Event.MouseEvent.dwMousePosition;
int cellX, cellY;
mouseToCell(pos.X, pos.Y, &cellX, &cellY);
if (cellX >= 0 && cellX < SIZE && cellY >= 0 && cellY < SIZE) {
printf("Левый клик: клетка (%d, %d)\n", cellX, cellY);
}
}
}
// Проверка клавиши 'q'
if (_kbhit()) {
char ch = _getch();
if (ch == 'q') break;
}
}
return 0;
}
🔧 Как компилировать (Windows)
- Visual Studio: создайте консольный проект → вставьте код.
- MinGW (через терминал):bash
gcc chess.c -o chess.exe chess.exe
🖱️ Что произойдёт
- Откроется консоль.
- Нарисуется доска с пешками и королём.
- При клике по клетке — внизу выведется её номер (например,
(4, 5)). - Нажмите
q— программа завершится.
🛠️ Что можно добавить дальше
- Подсветка клетки при клике (смена фона на зелёный).
- Выбор фигуры → клик на другую клетку → перемещение.
- Проверка валидности хода.
- Очистка старой позиции перед перемещением.
- Загрузка начальной расстановки всех фигур.
📌 Советы
- Используйте шрифт Consolas или DejaVu Sans Mono — иначе символы могут съезжать.
- Не уменьшайте окно — иначе координаты сбиваются.
- На Windows 10/11 — всё работает хорошо.
Хочешь, я добавлю подсветку клетки при клике или реализую ход фигуры? Могу продолжить.
Я
Алиса
В этом проекте дополнительные библиотеки линковать не нужно — всё, что используется, входит в стандартные средства Windows и компилятора.
🔧 Что используется и откуда берётся
| Функция / Средство | Библиотека | Нужно ли линковать? | Комментарий |
|---|---|---|---|
printf, getch, _kbhit | stdio.h, conio.h | ❌ Нет | Часть стандартной библиотеки C (MSVCRT) |
GetStdHandle, SetConsoleCursorPosition, SetConsoleTextAttribute | windows.h | ❌ Нет | Входит в Windows SDK, линкуется автоматически при использовании gcc или cl |
ReadConsoleInput | windows.h | ❌ Нет | То же — стандартный API Windows |
system() | stdlib.h | ❌ Нет | Стандартная функция C |
✅ Как компилировать — без лишних флагов
1. MinGW (gcc):
gcc chess.c -o chess.exe
- Никаких
-lфлагов не нужно. gccавтоматически линкуетkernel32.lib(где лежат функции Windows API).
2. MSVC (Visual Studio):
- Просто добавьте
.cфайл в проект. - Компилятор сам подключит
msvcrt.libиkernel32.lib.
3. Если всё же ошибка линковки (редко):
Иногда MinGW требует явного указания:
gcc chess.c -o chess.exe -lkernel32
Но на практике — это избыточно, потому что kernel32 подключается по умолчанию.
📦 Что не нужно устанавливать
- Никаких
ncurses,SDL,OpenGL— не требуется. - Никаких
.dll— всё работает через системные вызовы.
⚠️ Важно: работает только на Windows
Потому что:
windows.h— только для Windows.SetConsoleMode,INPUT_RECORD— специфичны для Windows API.
Если вы хотите кроссплатформенную версию (Linux/macOS), тогда уже нужно будет линковать ncurses:
gcc chess_linux.c -o chess -lncurses
Итог
🔹 На Windows: никаких -l флагов не нужно — всё работает «из коробки».
🔹 Просто компилируйте как обычную программу на C.
🔹 Это одно из преимуществ Win32 API — он доступен без установки чего-то дополнительного.
Готов продолжить — например, добавить подсветку клетки при клике?
Я
Алиса
Да, можно — и это очень важно для консольных приложений вроде шахмат, чтобы экран не прокручивался вверх при вводе. Проблема возникает, когда вывод (printf) достигает нижней строки консоли, и система автоматически прокручивает буфер вверх.
Чтобы этого избежать, нужно управлять позицией окна консоли или фиксировать размер буфера и окна, чтобы вывод оставался в видимой области.
✅ Решение: зафиксировать окно и использовать SetConsoleWindowPosition
Идея:
- Установить фиксированный размер окна.
- Использовать
SetConsoleWindowPosition, чтобы окно всегда "смотрело" на нужную область (например, на доску). - Выводить сообщения внизу, но не за пределы окна.
- Или выводить ввод поверх определённой строки (например, строки состояния).
🔧 Пример: фиксируем окно, чтобы не было прокрутки
#include <windows.h>
#include <stdio.h>
void setupConsole() {
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD bufferSize = {80, 30}; // Буфер: 80x30
SMALL_RECT windowSize = {0, 0, 79, 19}; // Окно: 80x20
// Устанавливаем размер буфера
SetConsoleScreenBufferSize(hOut, bufferSize);
// Устанавливаем размер окна
SetConsoleWindowInfo(hOut, TRUE, &windowSize);
// Отключаем полосы прокрутки
CONSOLE_SCREEN_BUFFER_INFO info;
GetConsoleScreenBufferInfo(hOut, &info);
info.dwSize.Y = 30; // фиксируем буфер
SetConsoleScreenBufferSize(hOut, info.dwSize);
}
Теперь, даже если вы выводите много строк, окно не будет прокручиваться, потому что мы его зафиксировали.
✅ Как читать ввод, не прокручивая экран
Вариант 1: Вывод в строку состояния (рекомендуется)
Зарезервируйте, например, строку Y = 21 для ввода.
char input[10];
int row = 21; // строка ввода
while (1) {
// Перемещаем курсор в строку ввода
COORD pos = {0, row};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
// Очищаем строку
printf(" ");
// Возвращаем курсор и читаем
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
printf("Команда: ");
fgets(input, sizeof(input), stdin);
// Обрабатываем
if (input[0] == 'q') break;
// Обновляем игру или вывод
// ...
}
🔹 Такой способ не вызывает прокрутки, потому что ввод всегда в одной и той же строке.
Вариант 2: Использовать ReadConsoleInput без printf
Вместо scanf или fgets, читайте ввод через ReadConsoleInput — тогда вы сами контролируете, где и как выводить символы.
char buffer[10] = {0};
int len = 0;
while (1) {
INPUT_RECORD ir;
DWORD count;
ReadConsoleInput(hInput, &ir, 1, &count);
if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
char ch = ir.Event.KeyEvent.uChar.AsciiChar;
if (ch == '\r') { // Enter
printf("\nВы ввели: %s\n", buffer);
break;
} else if (ch == '\b' && len > 0) { // Backspace
len--;
printf("\b \b"); // стираем символ
} else if (ch >= ' ' && len < 9) {
buffer[len++] = ch;
printf("%c", ch);
}
}
}
🔹 Полный контроль над выводом — никакой прокрутки.
✅ Как совместить с шахматами
- Нарисуйте доску в строках
0–7. - Используйте строки
10–15для лога (например, "Ход: e2-e4"). - Используйте строку
20для ввода. - Зафиксируйте окно, чтобы всё это всегда было видно.
⚠️ Важно
- Не используйте
system("cls")— он вызывает мигание и может сбить позицию. - Лучше очищать только нужные строки через
SetConsoleCursorPositionи пробелы. - Убедитесь, что
Console.BufferHeightбольше, чем видимое окно — иначе прокрутка всё равно возможна.
Итог
🔹 Да, можно читать ввод без прокрутки.
🔹 Ключевые приёмы:
- Фиксировать размер окна и буфера.
- Выводить ввод в заранее определённую строку.
- Использовать
SetConsoleCursorPositionвместоprintfв "чувствительных" зонах.
Хочешь — могу добавить в наш проект строку ввода внизу и лог ходов, чтобы всё работало плавно, без моргания и прокрутки.
Я
Алиса
Конечно Вот полный рабочий пример консольных шахмат с:
- ✅ Фиксированным окном (без прокрутки)
- ✅ Выводом шахматной доски
- ✅ Обработкой мыши и клавиатуры
- ✅ Строкой статуса внизу для ввода и сообщений
🖼️ Что вы увидите:
- Доска 8×8 (с пешками и королём) — сверху
- Строка статуса — внизу (строка 15)
- Координаты клика мыши и ввод с клавиатуры — в статусе
- Нажмите
q— выход
✅ Полный код (Windows, C)
#include <windows.h>
#include <stdio.h>
#include <string.h>
#define BOARD_SIZE 8
#define STATUS_LINE 12
#define BUFFER_HEIGHT 30
#define WINDOW_WIDTH 80
#define WINDOW_HEIGHT 18
// Фигуры (UTF-8)
const char* WHITE_KING = "\xE2\x99\x94"; // ♔
const char* BLACK_PAWN = "\xE2\x99\x9F"; // ♟
const char* EMPTY = " ";
// Цвета фона
#define WHITE_SQUARE (7 << 4) // светло-серый
#define BLACK_SQUARE (0 << 4) // чёрный
#define TEXT_COLOR 0
HANDLE hOut;
HANDLE hIn;
// Установка размера консоли
void setupConsole() {
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
hIn = GetStdHandle(STD_INPUT_HANDLE);
// Размер буфера
SetConsoleScreenBufferSize(hOut, (COORD){WINDOW_WIDTH, BUFFER_HEIGHT});
// Размер окна
SMALL_RECT window = {0, 0, WINDOW_WIDTH - 1, WINDOW_HEIGHT - 1};
SetConsoleWindowInfo(hOut, TRUE, &window);
// Отключаем курсор мигание (не обязательно)
CONSOLE_CURSOR_INFO cursor = {1, 0};
SetConsoleCursorInfo(hOut, &cursor);
// Включаем события мыши и клавиатуры
SetConsoleMode(hIn, ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS);
}
// Рисуем доску
void drawBoard() {
COORD pos;
for (int row = 0; row < BOARD_SIZE; row++) {
for (int col = 0; col < BOARD_SIZE; col++) {
pos.X = col * 4;
pos.Y = row;
SetConsoleCursorPosition(hOut, pos);
int isWhite = (row + col) % 2 == 0;
SetConsoleTextAttribute(hOut, isWhite ? WHITE_SQUARE : BLACK_SQUARE);
if (row == 1) {
printf(" %s ", BLACK_PAWN);
} else if (row == 7 && col == 7) {
printf(" %s ", WHITE_KING);
} else {
printf("%s", EMPTY);
}
}
}
SetConsoleTextAttribute(hOut, (7 << 4) | 0); // сброс
}
// Вывод в строку статуса
void setStatus(const char* msg) {
COORD pos = {0, STATUS_LINE};
SetConsoleCursorPosition(hOut, pos);
printf("%-*s", WINDOW_WIDTH, msg); // очищает строку
}
int main() {
setupConsole();
drawBoard();
setStatus("Готов. Кликните мышью или нажмите клавишу. 'q' — выход.");
char inputBuffer[64] = {0};
int bufPos = 0;
INPUT_RECORD ir;
DWORD count;
while (1) {
ReadConsoleInput(hIn, &ir, 1, &count);
if (ir.EventType == MOUSE_EVENT) {
if (ir.Event.MouseEvent.dwEventFlags == 0) { // клик
COORD mousePos = ir.Event.MouseEvent.dwMousePosition;
int cellX = mousePos.X / 4;
int cellY = mousePos.Y;
if (cellX >= 0 && cellX < BOARD_SIZE && cellY >= 0 && cellY < BOARD_SIZE) {
char msg[128];
sprintf(msg, "Левый клик: клетка (%d, %d)", cellX, cellY);
setStatus(msg);
}
}
}
else if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) {
char ch = ir.Event.KeyEvent.uChar.AsciiChar;
if (ch == 'q' || ch == 'Q') {
break;
}
else if (ch == '\r') { // Enter
if (bufPos > 0) {
char msg[128];
sprintf(msg, "Вы ввели: %s", inputBuffer);
setStatus(msg);
bufPos = 0;
inputBuffer[0] = '\0';
}
}
else if (ch == '\b' && bufPos > 0) { // Backspace
bufPos--;
inputBuffer[bufPos] = '\0';
char display[128];
sprintf(display, "Ввод: %s ", inputBuffer);
setStatus(display);
}
else if (ch >= ' ' && bufPos < 63) {
inputBuffer[bufPos++] = ch;
inputBuffer[bufPos] = '\0';
char display[128];
sprintf(display, "Ввод: %s", inputBuffer);
setStatus(display);
}
}
}
setStatus("Завершение...");
Sleep(800);
return 0;
}
🔧 Как компилировать
gcc chess_full.c -o chess.exe
chess.exe
📌 Особенности
- Клетка = 4 символа — чтобы было красиво (пробелы по бокам).
- Строка статуса = 12 — не пересекается с доской.
- Буфер высотой 30 — больше окна, но прокрутки нет, потому что окно зафиксировано.
- Ввод с клавиатуры — в строке статуса, с поддержкой
BackspaceиEnter. - Мышь — показывает номер клетки.
✅ Что можно добавить
- Подсветку выбранной клетки.
- Хранение состояния доски в массиве.
- Проверку ходов.
- Загрузку начальной позиции.
Готов расширить проект — например, сделать выбор фигуры → клик на клетку → перемещение. Хочешь?
_____________ старый текст
Сразу оговорюсь: полностью избежать работы с юникодными символами (которые как раз и используются для шахматных фигур) в таком задании не получится — иначе зачем вообще брать юникод, если не выводить его?). Но я подскажу, как организовать хранение и вывод без wchar_t и функций вроде wprintf.
Как «забить» в таблицу
Создайте массив (или таблицу поиска), где в индексе будет число (или другой тип, удобный для вас способ идентификации), а в ячейке — соответствующий символ юникода.
Например:
c#include <stdio.h>
// Таблица: сопоставление «код фигуры → символ»
// Коды взяты из юникода шахматных символов
const char figures = {
0, // ▮ (пустая клетка)
'♟', // ♟ — белый король
'♞', // ♞ — белый конь
'♝', // ♝ — белый слон
'♜', // ♜ — белая ладья
'♛', // ♛ — белый ферзь
'♚', // ♚ — чёрная ладья
'♙', // ♙ — чёрная слон
'♘', // ♘ — чёрная ферзь
'♖', // ♖ — чёрный слон
'♕', // ♕ — чёрный ферзь
'♔' // ♔ — чёрный король
};
```
Теперь, чтобы получить символ для какой-то фигуры (например, для пешки или пустой клетки), просто взять `figures[код_фигуры]`.
## Как вывести без `wchar_t`
Ключевой момент: чтобы консоль корректно отобразила юникод-символы (не «кракозябры»), нужно, чтобы сама консоль поддерживала нужную кодировку (обычно UTF-8) и в ней был установлен шрифт, содержащий эти символы. [9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
* **На Linux:** чаще всего всё работает «из коробки», если в системе настроена поддержка UTF-8.
* **На Windows:** часто помогает установка шрифта вроде DejaVu Sans Mono в настройках консоли. Также можно программно установить кодировку вывода через `SetConsoleOutputCP(CP_UTF8)` (из Windows.h), но это не всегда решает проблему полностью — иногда всё равно нужен подходящий шрифт.
[9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
**Важное предупреждение:** функции вроде `printf` работают с `char`. Если вы попытаетесь передать в `printf` символ юникода напрямую (например, `printf("%c", figures;`), система попытается вывести байт как число, и вместо символа вы увидите «?» или «�». Поэтому **никогда не передавайте напрямую число в `printf` для вывода символа юникода** — сначала преобразуйте число в `char`.
**Правильная схема:**
1. Заполняете массив `figures` как показано выше.
2. В коде, который решает задачу (например, рисуете доску), берёте значение из таблицы по индексу (коде фигуры) и передаёте его в `printf("%c", figures[код]);`.
## Пример вывода
```c
int main() {
// Пример использования таблицы
printf(" %c ", figures); // Пустая клетка
printf(" %c ", figures); // Белый король
printf(" %c ", figures); // Белый конь
printf("
");
return 0;
}
``` [1](https://metanit.com/c/tutorial/8.8.php)[6](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fcodereview.stackexchange.com%2Fquestions%2F234619%2Fchess-game-in-c)
**Итог:** алгоритм такой — массив поиска для маппинга кодов в юникод, и аккуратное использование `printf` с преобразованием типов. Если на вашей системе символы всё равно выводятся некорректно, проверьте шрифт консоли — это частая причина «пустых квадратов» вместо фигур. [9](https://stackoverflow.com/questions/27483800/displaying-unicode-chess-pieces-in-windows-console)[3](https://tr-page.yandex.ru/translate?lang=en-ru&url=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F27483800%2Fdisplaying-unicode-chess-pieces-in-windows-console)
Я
Алиса
Код фигуры — это целое число, которое вы сами определяете как удобную метку для каждой шахматной фигуры. Это может быть один байт, если вы используете тип char (или unsigned char) и укладываетесь в диапазон от 0 до 255.
Например:
char pawn = 1; // пешка — 1 байт
char rook = 4; // ладья — 1 байт
char king = 6; // король — 1 байт
То есть сам код фигуры — это байт, а символ юникода, который вы выводите (например, ♖), — это уже последовательность байт в UTF-8 (в данном случае — 3 байта: E2 99 96).
Почему важно это различать?
- Код фигуры — ваш внутренний идентификатор в программе (например,
1— белая пешка). Это один байт. - Символ юникода (например, ♖) — это то, что вы хотите вывести на экран. Он хранится не как один байт, а как последовательность байт в UTF-8 (3 байта для ♖).
Как это работает в коде
Вы можете хранить символы юникода как строки (массивы char), даже если не используете wchar_t:
const char* white_rook = "\xE2\x99\x96"; // ♖ в UTF-8
const char* black_king = "\xE2\x99\x9A"; // ♚ в UTF-8
Или в таблице:
const char* figures[13] = {
" ", // 0 — пусто
"\xE2\x99\x99", // 1 — ♙ чёрная пешка
"\xE2\x99\x8E", // 2 — ♎ белый конь
"\xE2\x99\x96", // 4 — ♖ белая ладья
// и так далее
};
Тогда вывод:
printf("%s", figures); // Выведет ♖
Вывод
- Код фигуры — это один байт (число от 0 до 255), удобный для хранения в массиве
char. - Символ юникода — это не один байт, а последовательность байт в UTF-8, которую можно хранить как строку (
const char*).
Таким образом, вы можете обойтись без wchar_t, но выводить символы нужно через %s, а не %c, потому что %c выводит один байт, а юникод-символы — это несколько байт.
Я
Алиса
Конечно Вот таблица шахматных фигур по цвету и типу, оформленная как таблица 2×8 (цвет × тип фигуры). Все символы приведены в виде UTF-8 последовательностей байт, чтобы их можно было использовать в C без wchar_t.
| Цвет \ Фигура | Пешка (Pawn) | Конь (Knight) | Слон (Bishop) | Ладья (Rook) | Ферзь (Queen) | Король (King) | — | — |
|---|---|---|---|---|---|---|---|---|
| Белые | \xE2\x99\x99 (♙) | \xE2\x99\x8E (♘) | \xE2\x99\x97 (♗) | \xE2\x99\x96 (♖) | \xE2\x99\x95 (♕) | \xE2\x99\x94 (♔) | — | — |
| Чёрные | \xE2\x99\x9F (♟) | \xE2\x99\x9E (♞) | \xE2\x99\x9D (♝) | \xE2\x99\x9C (♜) | \xE2\x99\x9B (♛) | \xE2\x99\x9A (♚) | — | — |
⚠️ Примечание: пустые ячейки (—) можно использовать для резерва или оставить как заполнители, если нужно строго 2×8.
Как использовать в C
const char* figures[2][6] = {
// Белые
{"\xE2\x99\x99", "\xE2\x99\x8E", "\xE2\x99\x97", "\xE2\x99\x96", "\xE2\x99\x95", "\xE2\x99\x94"},
// Чёрные
{"\xE2\x99\x9F", "\xE2\x99\x9E", "\xE2\x99\x9D", "\xE2\x99\x9C", "\xE2\x99\x9B", "\xE2\x99\x9A"}
};
// Пример вывода: белый ферзь
printf("%s", figures[0][4]); // Выведет ♕
Важно для корректного отображения
- Убедитесь, что ваша консоль поддерживает UTF-8.
- Используйте шрифт, содержащий шахматные символы (например, DejaVu Sans Mono, Consolas, Cascadia Code).
- На Windows можно добавить в начало программы:c
#include <windows.h> SetConsoleOutputCP(CP_UTF8);
Теперь вы можете легко обращаться к любой фигуре по цвету (0 — белые, 1 — чёрные) и типу (0–5).
Я
Алиса
Да, можно менять фон символа в консоли — и это зависит от операционной системы. Ниже я покажу, как это сделать на Windows и на Linux/macOS, потому что способы разные.
💻 На Windows (через SetConsoleTextAttribute)
Функция SetConsoleTextAttribute позволяет управлять цветом текста и фона для всех последующих символов.
Пример: жёлтый текст на синем фоне
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
// Установить цвет: текст — жёлтый (14), фон — синий (1)
// Формула: (фон << 4) | текст
SetConsoleTextAttribute(h, (1 << 4) | 14);
printf(" ♕ "); // Выведется с жёлтым текстом и синим фоном
// Вернуть стандартные цвета
SetConsoleTextAttribute(h, (0 << 4) | 7); // чёрный фон, светло-серый текст
return 0;
}
Цвета для фона и текста (Windows):
| Цвет | Код |
|---|---|
| Чёрный | 0 |
| Синий | 1 |
| Зелёный | 2 |
| Голубой | 3 |
| Красный | 4 |
| Пурпурный | 5 |
| Жёлтый | 6 |
| Белый | 7 |
| Светло-серый | 8 |
| и т.д. до F | 15 |
🔹 Фон — это старшие 4 бита, текст — младшие 4 бита:
(фон << 4) | текст.
🐧 На Linux/macOS (через ANSI-коды)
Используются escape-последовательности вида \033[bg;fgm, где:
bg— цвет фона (40–47 или 100–107),fg— цвет текста (30–37 или 90–97).
Пример: красный текст на жёлтом фоне
printf("\033[43;31m ♛ \033[0m"); // ♛ с красным текстом и жёлтым фоном
ANSI-цвета:
| Цвет | Текст | Фон |
|---|---|---|
| Чёрный | 30 / 90 | 40 / 100 |
| Красный | 31 / 91 | 41 / 101 |
| Зелёный | 32 / 92 | 42 / 102 |
| Жёлтый | 33 / 93 | 43 / 103 |
| Синий | 34 / 94 | 44 / 104 |
| Пурпурный | 35 / 95 | 45 / 105 |
| Голубой | 36 / 96 | 46 / 106 |
| Белый | 37 / 97 | 47 / 107 |
🔹
\033[0m— сброс к стандартным цветам.
✅ Как совместить с шахматными фигурами
// Windows
SetConsoleTextAttribute(h, (4 << 4) | 15); // белый текст на красном фоне
printf(" %s ", "\xE2\x99\x9B"); // ♛
// Linux
printf("\033[41;37m %s \033[0m", "\xE2\x99\x9B"); // то же самое
Важно
- На Windows фон будет применяться ко всем последующим символам, пока вы не сбросите цвет.
- На Linux фон применяется только к тому, что между escape-кодами.
- Убедитесь, что ваша консоль поддерживает цвета (всё работает в обычных терминалах, но не во всех IDE).
Теперь вы можете делать красивые цветные шахматы 🎨♟️
Я
Алиса
Да, позицию курсора в консоли тоже можно менять программно — и это работает как на Windows, так и на Linux/macOS, но разными способами. Ниже покажу оба.
💻 На Windows: SetConsoleCursorPosition
Используется функция SetConsoleCursorPosition из windows.h. Она принимает дескриптор консоли и координаты (в символах).
Пример: установить курсор в позицию (5, 3)
#include <windows.h>
#include <stdio.h>
int main() {
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {5, 3}; // x=5, y=3 (столбец, строка)
SetConsoleCursorPosition(h, pos);
printf("♔"); // король появится в нужной позиции
return 0;
}
🔹 Координаты:
(0, 0)— левый верхний угол.
🔹x— столбец (горизонталь),y— строка (вертикаль).
🐧 На Linux/macOS: ANSI-коды
Используется escape-последовательность:\033[строка;столбецH или \033[строка;столбецf
Пример: курсор в позицию (6, 4)
printf("\033[4;6H"); // строка 4, столбец 6
printf("♕"); // ферзь появится здесь
🔹 Формат:
\033[строка;столбецH— стандартный способ.
🔹 Нумерация начинается с 1, а не с 0.
🔁 Как использовать с шахматной доской
Допустим, вы хотите нарисовать шахматную доску 8×8, где каждая клетка — символ с цветом фона и фигурой.
Вы можете:
- Установить цвет фона (черный/белый) для клетки.
- Переместить курсор в нужную позицию.
- Вывести символ фигуры или пустой клетки.
Пример (Windows): вывод фигуры на позицию (x=2, y=5)
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {2 * 2, 5}; // x умножаем, чтобы клетки не сливались
SetConsoleCursorPosition(h, pos);
SetConsoleTextAttribute(h, (7 << 4) | 0); // светло-серый фон, чёрный текст
printf("♟"); // чёрная пешка
Пример (Linux): то же самое
printf("\033[5;5H"); // строка 5, столбец 5
printf("\033[47;30m ♟ \033[0m"); // фон белый, текст чёрный
✅ Совет: симуляция "сетки"
Чтобы доска выглядела ровно:
- Увеличьте шаг по
x(например, на 2 символа на клетку), чтобы между фигурами был отступ. - Используйте фиксированный шрифт (Consolas, DejaVu, Monaco), где все символы одинаковой ширины.
⚠️ Важно
- На Windows:
SetConsoleCursorPositionработает только в настоящей консоли, не во всех IDE. - На Linux: ANSI-коды поддерживаются почти везде, кроме очень старых терминалов.
- Если вы выводите цвет и позицию — не забудьте сбрасывать цвета (
\033[0mилиSetConsoleTextAttributeс обычными цветами), чтобы не испортить весь вывод.
Теперь вы можете рисовать шахматы точно по координатам и с цветным фоном — как настоящий графический интерфейс, но в консоли 🖼️♟️
const char* figures[2][6] = {
// Белые
{"\xE2\x99\x99", "\xE2\x99\x8E", "\xE2\x99\x97", "\xE2\x99\x96", "\xE2\x99\x95", "\xE2\x99\x94"},
// Чёрные
{"\xE2\x99\x9F", "\xE2\x99\x9E", "\xE2\x99\x9D", "\xE2\x99\x9C", "\xE2\x99\x9B", "\xE2\x99\x9A"}
};
// Пример вывода: белый ферзь
printf("%s", figures[0][4]); // Выведет ♕
Комментариев нет:
Отправить комментарий