понедельник, 29 июня 2026 г.

Интерфейс с жава

 Да, абсолютно! Именно так и работает код через ProcessBuilder, который я показал выше: внешняя программа запускается заново на каждый ход, делает расчёт, выдаёт ответ в консоль и сразу закрывается.

В Java аналогом классической функции system() из C++ является метод Runtime.getRuntime().exec(). Он делает ровно то же самое — запускает программу с нуля.
Однако, передать данные в запущенную программу через обычную команду system("engine.exe") неудобно, потому что она не умеет передавать аргументы через стандартный ввод. Чтобы программа запускалась каждый раз заново и сразу получала позицию, проще всего передавать доску как аргумент командной строки (прямо при запуске, например: engine.exe 011200...).
Вот как будет выглядеть этот максимально простой вариант в Java:

Код на стороне Java (Запуск каждый раз с нуля)

Вставьте этот метод в наш графический интерфейс. Он будет вызываться только в момент, когда должен походить движок:
import java.io.*;

// ... внутри класса CornersGame ...

private void makeSingleRunEngineTurn() {
    try {
        // 1. Собираем доску в одну компактную строку из 64 цифр (без запятых)
        StringBuilder boardState = new StringBuilder();
        for (int r = 0; r < 8; r++) {
            for (int c = 0; c < 8; c++) {
                boardState.append(board[r][c]);
            }
        }

        // 2. Запускаем программу и передаем ей строку как аргумент
        // Это аналог вызова в консоли: engine.exe 00000000111...
        Process process = Runtime.getRuntime().exec("engine.exe " + boardState.toString());

        // 3. Читаем то, что программа вывела в консоль перед завершением
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
        String response = reader.readLine(); // Строка вида "2224" (откудаX, откудаY, кудаX, кудаY)

        // Ждем, пока процесс гарантированно завершится (программа закроется)
        process.waitFor(); 
        reader.close();

        // 4. Если ответ получен, двигаем шашку на экране
        if (response != null && response.length() == 4) {
            // Переводим символы "2", "2", "2", "4" в числа 2, 2, 2, 4
            int fromX = Character.getNumericValue(response.charAt(0));
            int fromY = Character.getNumericValue(response.charAt(1));
            int toX   = Character.getNumericValue(response.charAt(2));
            int toY   = Character.getNumericValue(response.charAt(3));

            // Делаем ход движка
            board[toY][toX] = board[fromY][fromX];
            board[fromY][fromX] = 0;

            // Передаем ход человеку и обновляем графику
            whiteTurn = true;
            checkWin();
        }

    } catch (Exception e) {
        e.printStackTrace();
        JOptionPane.showMessageDialog(this, "Не удалось запустить движок engine.exe");
    }
}

Как в этом случае должен принимать данные сам движок (engine.exe)?

Так как программа запускается каждый раз заново, она должна принимать позицию через аргументы функции main (массив argv в C++ / C# или sys.argv в Python).
Пример простейшего движка на C++ под такую логику:
#include <iostream>
#include <string>

int main(int argc, char* argv[]) {
    // Проверяем, передали ли нам строку с доской
    if (argc < 2) {
        return 1; // Ошибка: аргумент не передан
    }

    // argv[1] — это строка из 64 символов (например, "22200000...")
    std::string board = argv[1]; 

    // --- ЗДЕСЬ ВАШ АЛГОРИТМ ИЩЕТ ЛУЧШИЙ ХОД ---
    // Для примера: пусть движок всегда хочет сходить с клетки (2,2) на (2,4)
    std::string bestMove = "2224"; 

    // Просто выводим ход в консоль и завершаем работу программы
    std::cout << bestMove << std::endl; 
    
    return 0; // Программа успешно закрывается, Java ловит этот вывод
}

Плюсы такого подхода

  • Идеальная изоляция: Движок гарантированно очищает за собой память (ОЗУ) после каждого хода, так как операционная система полностью закрывает процесс. Вы можете не бояться утечек памяти в коде движка.
  • Простейший код: Не нужно настраивать сложные двусторонние потоки данных, открывать сессии или писать JNI-обертки. Передал аргумент при старте — забрал строчку на выходе.
Если вы хотите интегрировать этот метод в наш готовый графический интерфейс, дайте знать: я подскажу, в какое место метода handleMouseClick его прописать, чтобы он автоматически срабатывал сразу после хода игрока.

Комментариев нет:

Отправить комментарий