Обновить
3
Валерий Рязанов@longvalery

Мастер на все руки ;)

Отправить сообщение

виноват. в перерывах между работой, где, увы, PHP малость накосячил... но завтра попробую во-первых доделать Linux ветку и устранить косяки... , а, во-вторых, если получится (не будут приставать), то выложу результат на github

Попробовал создать универсальную игру

Скрытый текст
import msvcrt
import random
import sys
import time

WIDTH = 79
HEIGHT = 25
PAUSE = 0.2

if sys.platform == "win32":
    import ctypes
    kernel32 = ctypes.windll.kernel32
    STD_OUTPUT_HANDLE = -11

    def clear_screen():
        # Очистка экрана в Windows (аналог \033[2J)
        for _ in range(100):
            print()

    def hide_cursor():
        # Скрыть курсор в Windows (аналог \033[?25l)
        kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 0x0001 | 0x0002 | 0x0004)
        info = ctypes.create_string_buffer(22)
        kernel32.GetConsoleScreenBufferInfo(kernel32.GetStdHandle(-11), info)
        mode = ctypes.cast(info, ctypes.POINTER(ctypes.c_uint32)).contents.value
        ctypes.cast(info, ctypes.POINTER(ctypes.c_uint32)).contents.value = mode & ~0x0020

    def show_cursor():
        # Показать курсор в Windows (аналог \033[?25h)
        kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 0x0001 | 0x0002 | 0x0004)
        info = ctypes.create_string_buffer(22)
        kernel32.GetConsoleScreenBufferInfo(kernel32.GetStdHandle(-11), info)
        mode = ctypes.cast(info, ctypes.POINTER(ctypes.c_uint32)).contents.value
        ctypes.cast(info, ctypes.POINTER(ctypes.c_uint32)).contents.value = mode | 0x0020


    def move_cursor_home():
        h = kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
        csbi = ctypes.create_string_buffer(22)
        kernel32.GetConsoleScreenBufferInfo(h, csbi)
        # csbi layout (упрощённо): [0]=size, [4]=cursor pos (X,Y) как два int32
        cursor_pos = ctypes.cast(csbi, ctypes.POINTER(ctypes.c_uint32)).contents
        # В структуре CONSOLE_SCREEN_BUFFER_INFO курсор находится по смещению 4+8=12 байт (два int32)
        cursor = ctypes.cast(ctypes.addressof(csbi) + 12, ctypes.POINTER(ctypes.c_ulonglong)).contents.value
        x = cursor & 0xFFFF
        y = (cursor >> 16) & 0xFFFF
        # Просто ставим курсор в (0,0)
        class COORD(ctypes.Structure):
            _fields_ = [("X", ctypes.c_short), ("Y", ctypes.c_short)]
        coord = COORD(0, 0)
        kernel32.SetConsoleCursorPosition(h, coord)
else:
    # Unix: оставляем ANSI-последовательности
    def clear_screen():
        print("\033[2J", end="", flush=True)

    def hide_cursor():
        print("\033[?25l", end="", flush=True)

    def show_cursor():
        print("\033[?25h", end="", flush=True)

    def move_cursor_home():
        print("\033[H", end="", flush=True)

def get_arrow_key():
    """
    Возвращает 'LEFT', 'RIGHT', 'UP', 'DOWN' или None, если нажатий нет.
    Работает неблокирующе.
    """
    if not msvcrt.kbhit():
        return None
    ch = msvcrt.getwch()  # может вернуть один или два символа для стрелок
    if ch == '\x1b':  # Esc
        return 'ESC'
    # Стрелки в Windows: первый байт — спецкод (обычно \xe0 или 0x00), второй — код клавиши
    if ch in ('\xe0', '\0'):
        ch2 = msvcrt.getwch()
        if ch2 == 'K':
            return 'LEFT'
        elif ch2 == 'M':
            return 'RIGHT'
        elif ch2 == 'H':
            return 'UP'
        elif ch2 == 'P':
            return 'DOWN'
    return None

def move_road(rows:list) -> list:
    last = rows.pop()
    line = [" "] * WIDTH
    x = random.randint(1, WIDTH - 1)
    line[x] = "#"
    rows.insert(0, line)
    return rows
def game():
    score = 0
    car = WIDTH // 2
    rows = [[" "] * WIDTH for _ in range(HEIGHT)]
    rows[-1][car] = "A"
    for _ in range(10):
        x = random.randint(1, WIDTH - 1)
        y = random.randint(1, HEIGHT - 1)
        rows[y][x] = "#"
    while True:
        move_cursor_home()
        key = get_arrow_key()
        if key:
            if key == 'ESC':
                break
            direction = key
            rows[-1][car] = " "
            if direction == 'LEFT':
                car = car - 1 if car > 1 else 1
            if direction == 'RIGHT':
                car = car + 1 if car < WIDTH else WIDTH - 1

        road = "\n".join("|" + "".join(row) + "|" for row in rows)
        print(road, end="", flush=True)
        print(f"\n Счёт: {score}", flush=True)
        time.sleep(PAUSE)
        rows = move_road(rows)
        if rows[-1][car] == "#":
            break
        rows[-1][car] = "A"
        score += 1

if __name__ == "__main__":
    clear_screen()
    hide_cursor()
    game()
    show_cursor()

получилось малость длинее

на Windows работает, на Linux не проверял

На мой взгляд, habr должен обучать на примерах, поэтому работающий код расположен здесь ( https://github.com/longvalery/JWTFastAPI.git ) ветка master.

Я попробовал перевести логику на авторизации с учётом замечания Rsa97.

Чуток покопипастил и соорудил развитие этой фичи

Может в vanilla CSS дело и до for() дойдёт, чтобы препроцессоры не применять...

.progress::before {

    content: if(

      style(--progress <= 0): "0%";  

      style(--progress <= 1): "1%";

      style(--progress <= 2): "2%";

      style(--progress <= 3): "3%";

      style(--progress <= 4): "4%";

      style(--progress <= 5): "5%";

      style(--progress <= 6): "6%";

      style(--progress <= 7): "7%";

      style(--progress <= 8): "8%";

      style(--progress <= 9): "9%";

      style(--progress <= 10): "10%";

      style(--progress <= 11): "11%";

      style(--progress <= 12): "12%";

      style(--progress <= 13): "13%";

      style(--progress <= 14): "14%";

      style(--progress <= 15): "15%";

      style(--progress <= 16): "16%";

      style(--progress <= 17): "17%";

      style(--progress <= 18): "18%";

      style(--progress <= 19): "19%";

      style(--progress <= 20): "20%";

      style(--progress <= 21): "21%";

      style(--progress <= 22): "22%";

      style(--progress <= 23): "23%";

      style(--progress <= 24): "24%";

      style(--progress <= 25): "25%";

      style(--progress <= 26): "26%";

      style(--progress <= 27): "27%";

      style(--progress <= 28): "28%";

      style(--progress <= 29): "29%";

      style(--progress <= 30): "30%";

     

      style(--progress <= 31): "31%";

      style(--progress <= 32): "32%";

      style(--progress <= 33): "33%";

      style(--progress <= 34): "34%";

      style(--progress <= 35): "35%";

      style(--progress <= 36): "36%";

      style(--progress <= 37): "37%";

      style(--progress <= 38): "38%";

      style(--progress <= 39): "39%";

      style(--progress <= 40): "40%";

      style(--progress <= 41): "41%";

      style(--progress <= 42): "42%";

      style(--progress <= 43): "43%";

      style(--progress <= 44): "44%";

      style(--progress <= 45): "45%";

      style(--progress <= 46): "46%";

      style(--progress <= 47): "47%";

      style(--progress <= 48): "48%";

      style(--progress <= 49): "49%";

      style(--progress <= 50): "50%";

      style(--progress <= 51): "51%";

      style(--progress <= 52): "52%";

      style(--progress <= 53): "53%";

      style(--progress <= 54): "54%";

      style(--progress <= 55): "55%";

      style(--progress <= 56): "56%";

      style(--progress <= 57): "57%";

      style(--progress <= 58): "58%";

      style(--progress <= 59): "59%";

      style(--progress <= 60): "60%";

      style(--progress <= 61): "61%";

      style(--progress <= 62): "62%";

      style(--progress <= 63): "63%";

      style(--progress <= 64): "64%";

      style(--progress <= 65): "65%";

      style(--progress <= 66): "66%";

      style(--progress <= 67): "67%";

      style(--progress <= 68): "68%";

      style(--progress <= 69): "69%";

      style(--progress <= 70): "70%";

      style(--progress <= 71): "71%";

      style(--progress <= 72): "72%";

      style(--progress <= 73): "73%";

      style(--progress <= 74): "74%";

      style(--progress <= 75): "75%";

      style(--progress <= 76): "76%";

      style(--progress <= 77): "77%";

      style(--progress <= 78): "78%";

      style(--progress <= 79): "79%";

      style(--progress <= 80): "80%";

      style(--progress <= 81): "81%";

      style(--progress <= 82): "82%";

      style(--progress <= 83): "83%";

      style(--progress <= 84): "84%";

      style(--progress <= 85): "85%";

      style(--progress <= 86): "86%";

      style(--progress <= 87): "87%";

      style(--progress <= 88): "88%";

      style(--progress <= 89): "89%";

      style(--progress <= 90): "90%";

      style(--progress <= 91): "91%";

      style(--progress <= 92): "92%";

      style(--progress <= 93): "93%";

      style(--progress <= 94): "94%";

      style(--progress <= 95): "95%";

      style(--progress <= 96): "96%";

      style(--progress <= 97): "97%";

      style(--progress <= 98): "98%";

      style(--progress <= 99): "99%";

      else: "100%";

    );

    color: var(--color);

  }

Хмм.. изволите загадки загадывать?

"Я его слепила из того, что было". Потому как мне показалось, что с помощью данного инструмента можно достаточно быстро слепить нечто приличное.

Если же есть другие предложения, то изложите, please.

А свободное ПО тем и отличается от покупного, что постоянно нужно что-то "дотачиваить по месту" и "морщить лоб" при отсутствии документации. А здесь в исходниках есть масса примеров и доки.

Честно говоря, еще не пробовал. Я ведь только месяц назад узнал про Киви. Это учебный проект, на котором первым учеником был я ;)

Сейчас немного завис на изменении языка приложения. Большинство элементов отработало хорошо динамическую перезагрузку, но ряд упорно не желает работать после этого корректно.

Как закончу, обязательно попробую приложение на Андроиде. Впрочем, никто не мешает Вам оценить это самостоятельно. Код-то открытый.

В догон. Сходу pyinstaller мой проект не собрал. Пришлось добавить в код несколько бесполезных для запуска строк импорта, потому что сборщик, увы, не видит элементы из декларативной kivy-части.

Сделал соответствующие изменения на github.

И пока не победил сборку в один файл :( . Всё-таки рядом с exe-файлом нужно положить каталог assets с картинками.

Запускается и отлаживается в PyCharm очень легко. Для сборки под Windows до exe-файла использую pyinstaller. Но это обычная для python-скриптов практика. И не относится к "птичке".

Не вопрос. Для первых восьми экранов вставил. Продолжать ?

Пардон, упустил... это древний баг autoit.

Что бы исправить ошибку замените строку отправки пути к файлу на эту

autoit.control_set_text(idExplorerOpen, idInputLine, args.file)

Подробнее об этой проблеме здесь (Autoit Send sometimes convert : to ; (colon to semi colon) and \ to | (backslash to pipe) - AutoIt General Help and Support - AutoIt Forums (autoitscript.com) )

control_set иногда срабатывает правильно, а иногда неправильно. Это зависит от раскладки клавиатуры, операционной системы и ... погоды за окном ;)

Через pip

webdriver_manager

selenium

argparse

И отдельно, как описано выше, через setup.py - PyAutoit

Возможно, именно последний притащил много лишнего на Ваш взгляд.

Но я не заморачиваюсь подобными вопросами и не делаю freeze и анализ после каждой установки пакета.

Увы. Это действительно так. Я ставил в чистом, виртуальном окружении всего три пакета, но pip притащил все зависимости.

Позвольте спросить: "А в чем проблема с длинным списком зависимых пакетов?"

Вы забыли, что нужно еще выполнить пункт 1.1. pip install webdriver_manager

Тогда всё будет без ошибок

Но код рабочий, круто.

Спасибо

Информация

В рейтинге
5 543-й
Откуда
Смоленск, Смоленская обл., Россия
Дата рождения
Зарегистрирован
Активность

Специализация

Десктоп разработчик, Фулстек разработчик
Старший
SQL
Python
Базы данных
Microsoft SQL Server
Разработка программного обеспечения
Системное программирование
Linux
Django
MySQL
ООП