Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Помогите с кодом на Assemblere (Игра "Поймай точку")

85K
13 декабря 2012 года
BuSh83
11 / / 13.12.2012
Помогите пожалуйста с кодом игры "Поймай точку". Текст задачи:
Цитата:
В начале игры пользователь вводит своё имя, которое появляется в заголовке, а также уровень сложности (1–10).

В окне консоли в случайной позиции появляется точка (например, символ «О») и через некоторое время исчезает. Задача игрока – успеть щелкнуть мышью по точке. В зависимости от степени попадания окрашивать точку (или её окрестность) в один из цветов – красный – «не попали», желтый – «попали в некоторую окрестность точки», зеленый – «полное попадание».

Предусмотреть:
– подсчет очков
– постепенное уменьшение времени отображения точки (начальный интервал выбирать в зависимости от введенного в начале игры уровня сложности)
– игра продолжается до тех пор, пока не было совершено 10 попаданий или 10 промахов.

В конце выводить сообщение о выигрыше или проигрыше.


Вот на что меня хватило (лишь начальные наработки), потому как несколько месяцев практики явно не хватает для нормальной работы!:

Код:
;Инструкции процессора Pentium
.586P

;Плоская модель памяти, соглашение о вызовах в стиле STDCALL
.MODEL FLAT, STDCALL

;константы
STD_OUTPUT_HANDLE   EQU -11     ;консоль вывода
STD_INPUT_HANDLE    EQU -10

MAX_TIME    EQU 10  ;время ожидания одной цели
HIT_SCORE   EQU 2
PHIT_SCORE  EQU 1
QL_TARGET   EQU 10      ;количество операций

XMAX    EQU 18
XMIN    EQU 2
YMAX    EQU 18
YMIN    EQU 2

;атрибуты цветов
FOREGROUND_BLUE     equ 1h  ;синий цвет букв
FOREGROUND_GREEN    equ 2h  ;зеленый цвет букв
FOREGROUND_RED      equ 4h  ;красный цвет букв
FOREGROUND_INTENSITY    equ 8h  ;повышенная интенсивность букв
BACKGROUND_BLUE     equ 10h     ;синий свет фона
BACKGROUND_GREEN    equ 20h     ;зеленый цвет фона
BACKGROUND_RED      equ 40h     ;красный цвет фона
BACKGROUND_INTENSITY    equ 80h     ;повышенная интенсивность фона

COL1 = FOREGROUND_BLUE + FOREGROUND_GREEN + FOREGROUND_RED + FOREGROUND_INTENSITY   ;цвет выводимого текста

;тип события
KEY_EVENT           equ 1h
MOUSE_EVENT         equ 2h

FROM_LEFT_1ST_BUTTON_PRESSED         equ 1h

;Прототипы API-функций
EXTERN  wsprintfA:NEAR
EXTERN GetStdHandle@4:NEAR
EXTERN WriteConsoleA@20:NEAR
EXTERN SetConsoleTitleA@4:NEAR
EXTERN CharToOemA@8:NEAR
EXTERN FreeConsole@0:NEAR
EXTERN AllocConsole@0:NEAR
EXTERN SetConsoleCursorPosition@8:NEAR
EXTERN SetConsoleTextAttribute@8:NEAR
EXTERN ReadConsoleA@20:NEAR
EXTERN ReadConsoleInputA@16:NEAR
EXTERN CloseHandle@4:NEAR
EXTERN ExitProcess@4:NEAR
;EXTERN GetNumberOfConsoleInputEvents@6:NEAR заюзать перед циклом обработки событий

;Директивы компоновщику
includelib user32.lib       ;для функции CharToOemA@8:NEAR
includelib kernel32.lib

;-----------------------------------------------
;структура координат
COOR  STRUC
    X  WORD ?
    Y  WORD ?
COOR  ENDS

;Сегмент данных
_DATA SEGMENT
HANDL_OUT   DWORD ?
HANDL_IN    DWORD ?
HANDL_ERR DWORD ?
CO      DWORD   ?
STAT    DB 0    ;статус игры 1б - попадание
SCORE   DB 0    ;кол-во очков
TIMER   DW MAX_TIME ;таймер
RD      DB ?
DIF     DB ?
TIT     DB "Модель 'Поймай точку'",0
STR1    DB "Введите имя:",0
STR2    DB "Нажмите Enter для продолжения...",0
STR3    DB "Введите сложность:",0
TARGET  DB "O",0    ;цель
TNULL   DB " ",0    ;закрашивание цели
FORM    DB "Координаты: %u %u "   ;вывод координат мыши (удалить)
BUF     DB 200 dup(?)   ;временное хранение введеной строки
NM      DB 30 dup(?)
LENS    DWORD ?     ;количество выведенных символов
MCRD    COOR <?>    ;координаты мыши
TCRD    COOR <?>    ;координаты цели

random_seed dd 0  ; Переменная для хранения промежуточных результатов работы генератора
rmax dd ?   ; правый край диапазона
rmin dd ?   ; левый край диапазона

MOUS_KEY        WORD        9 dup(?)
_DATA ENDS

;--------------------------------------
;сегмент кода
_TEXT SEGMENT
START:
   
    PUSH OFFSET STR2        ;перекодируем строку
    PUSH OFFSET STR2
    CALL CharToOemA@8
   
    PUSH OFFSET STR3        ;перекодируем строку
    PUSH OFFSET STR3
    CALL CharToOemA@8
   
    PUSH STD_INPUT_HANDLE       ;получить HANDL_IN ввода
    CALL GetStdHandle@4
    MOV HANDL_IN,EAX
   
    PUSH STD_OUTPUT_HANDLE      ;получить HANDL_OUT вывода
    CALL GetStdHandle@4
    MOV HANDL_OUT,EAX
   
    PUSH OFFSET TIT     ;перекодируем строку
    PUSH OFFSET TIT
    CALL CharToOemA@8
    PUSH OFFSET TIT     ;задать заголовок окна консоли
    CALL SetConsoleTitleA@4
   
    PUSH OFFSET STR1        ;перекодируем строку
    PUSH OFFSET STR1
    CALL CharToOemA@8
    PUSH OFFSET STR1        ;вывести строку
    CALL LENSTR             ;в EBX длина строки
    PUSH 0
    PUSH OFFSET LENS
    PUSH EBX
    PUSH OFFSET STR1
    PUSH HANDL_OUT
    CALL WriteConsoleA@20
   
   
    PUSH 0              ;ждать ввод строки
    PUSH OFFSET LENS
    PUSH 200
    PUSH OFFSET NM
    PUSH HANDL_IN
    CALL ReadConsoleA@20
   
    PUSH OFFSET STR3        ;вывести строку
    CALL LENSTR             ;в EBX длина строки
    PUSH 0
    PUSH OFFSET LENS
    PUSH EBX
    PUSH OFFSET STR3
    PUSH HANDL_OUT
    CALL WriteConsoleA@20
   
    PUSH 0              ;ждать ввод строки
    PUSH OFFSET LENS
    PUSH 200
    PUSH OFFSET BUF
    PUSH HANDL_IN
    CALL ReadConsoleA@20
   
    MOV AL, BYTE PTR BUF
    AND AL, 0fh
    MOV DIF, AL
   
    PUSH OFFSET STR2        ;вывести строку
    CALL LENSTR             ;в EBX длина строки
    PUSH 0
    PUSH OFFSET LENS
    PUSH EBX
    PUSH OFFSET STR2
    PUSH HANDL_OUT
    CALL WriteConsoleA@20
   
    PUSH 0              ;ждать ввод строки
    PUSH OFFSET LENS
    PUSH 200
    PUSH OFFSET BUF
    PUSH HANDL_IN
    CALL ReadConsoleA@20
   
    CALL FreeConsole@0      ;освободить существующую консоль
    CALL AllocConsole@0     ;образовать новую консоль
   
    PUSH STD_INPUT_HANDLE       ;получить HANDL_IN ввода
    CALL GetStdHandle@4
    MOV HANDL_IN,EAX
   
    PUSH STD_OUTPUT_HANDLE  ;получить HANDL_OUT вывода
    CALL GetStdHandle@4
    MOV HANDL_OUT,EAX
   
    PUSH OFFSET NM      ;задать заголовок окна консоли
    CALL SetConsoleTitleA@4
   
   
   
   
;-----------[Основная логика игры]-------------
LOO:
    CMP TIMER, MAX_TIME
    JE  RAND_TARGET_SET
   
    PUSH OFFSET CO          ;прочитать одну запись о событии
    PUSH 1
    PUSH OFFSET MOUS_KEY
    PUSH HANDL_IN
    CALL ReadConsoleInputA@16
   
    ;CMP WORD PTR MOUS_KEY,MOUSE_EVENT  ;проверим, не с мышью ли что?
    ;JE LOO1
    INC TIMER
   
    PUSH OFFSET TIMER       ;задать заголовок окна консоли
    CALL SetConsoleTitleA@4
   
    CMP BYTE PTR MOUS_KEY+14,27 ;есть, какое?
    JNE LOO
   
    CALL FreeConsole@0      ;закрыть консоль
    PUSH 0
    CALL ExitProcess@4
    RET

JMP LOO                 ;к началу цикла
;-------------------------------------------

   
RAND_TARGET_SET:
; Инициализация генератора случайных чисел
    call random_init
    mov [rmin], XMIN
    mov [rmax], XMAX
; Получаем в EAX случайное число из заданного диапазона
    call WIRandom
    mov TCRD.X, AX
; Инициализация генератора случайных чисел
    call random_init
    mov [rmin], XMIN
    mov [rmax], XMAX
; Получаем в EAX случайное число из заданного диапазона
    call WIRandom
    mov TCRD.Y, AX

    PUSH COL1               ;задать цветовые атрибуты выводимого текста
    PUSH HANDL_OUT
    CALL SetConsoleTextAttribute@8
   
    PUSH TCRD
    PUSH HANDL_OUT
    CALL SetConsoleCursorPosition@8
   
    PUSH OFFSET TARGET
    CALL LENSTR
    PUSH OFFSET TARGET      ;вывести строку
    CALL LENSTR             ;в EBX длина строки
   
    PUSH 0
    PUSH OFFSET LENS   
    PUSH EBX
    PUSH OFFSET TARGET 
    PUSH HANDL_OUT
    CALL WriteConsoleA@20
   
    MOV AX, 0
    MOV TIMER, AX
   
    JMP LOO
   
   
   
;--------------------------------------
;Процедура для определения длины строки
LENSTR  PROC
    PUSH EBP
    MOV EBP,ESP
    PUSH EAX
    PUSH EDI
;--------------
    CLD
    MOV EDI,DWORD PTR [EBP+08H]
    MOV EBX,EDI
    MOV ECX,1000000
    XOR AL,AL
    REPNE SCASB
    SUB EDI,EBX
    MOV EBX,EDI
    DEC EBX
;--------------
    POP EDI
    POP EAX
    POP EBP
    RET 4
LENSTR ENDP

;----[Функция инициализации генератора случайных чисел]--------
random_init proc
        push    eax
        push    edx
        rdtsc
        xor     eax,edx
        mov     [random_seed],eax
        pop     edx
        pop     eax
        ret
random_init endp
;-------------------------------------------------------------------
;----[Функция генерации случайного числа в диапазоне rmin..rmax]----------------
WIRandom proc
        push    edx
        push    ecx
        mov     ecx,[rmax]
        sub     ecx,[rmin]
        inc     ecx
        call WRandom
        xor     edx,edx
        div     ecx
        mov     eax,edx
        add     eax,[rmin]
        pop     ecx
        pop     edx
        ret
WIRandom endp
;-------------------------------------------------------------------
;----[Функция генерации случайного числа]---------------------------
WRandom proc
        push    edx
        push    ecx
        mov     eax,[random_seed]
        xor     edx,edx
        mov     ecx,127773
        div     ecx
        mov     ecx,eax
        mov     eax,16807
        mul     edx
        mov     edx,ecx
        mov     ecx,eax
        mov     eax,2836
        mul     edx
        sub     ecx,eax
        xor     edx,edx
        mov     eax,ecx
        mov     [random_seed],ecx
        mov     ecx,100000
        div     ecx
        mov     eax,edx
        pop     ecx
        pop     edx
        ret
WRandom endp
;-------------------------------------------------------------------

_TEXT ENDS
END START
414
14 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Лучше напиши на что тебя не хватило. По коду сложно определить не вчитываясь что ты уже написал.
85K
14 декабря 2012 года
BuSh83
11 / / 13.12.2012
Вот как работает написанный код:
  1. Создается консоль.
  2. Запрашивается имя.
  3. Запрашивается уровень сложности(даже не знаю корректно или нет)
  4. Создается другая консоль(удаляя предыдущую, чтобы затереть введенные данные), в названии консоли отображается имя.
  5. Затем действие останавливается(ожидание события, если удерживать любую клавишу нажатой, или водить мышкой, то через равные промежутки времени в квадрате от 2 до 18, появляются "O"). По нажатию ESC консоль закрывается.
На этом программа исчерпывает себя, то есть ни одной поставленной задачи я не достиг. Сделал лишние наметки на данные, которые пока не используются.
414
14 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Цитата:
Создается другая консоль(удаляя предыдущую, чтобы затереть введенные данные).


Поржал.
Помогу тебе попозже, если не найдёшь готового решения к этому времени.

85K
14 декабря 2012 года
BuSh83
11 / / 13.12.2012
Цитата: CassandraDied
Цитата:
Создается другая консоль(удаляя предыдущую, чтобы затереть введенные данные).


Поржал.
Помогу тебе попозже, если не найдёшь готового решения к этому времени.


=) Я профан полный в данном языке, другого не придумал ничего)

414
14 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Ну, пока у меня нет времени заняться этим самому, могу подсказать какие функции посмотреть, чтобы ты сам что-то делал в этом время. А приложение должно быть обязательно консольное?
85K
15 декабря 2012 года
BuSh83
11 / / 13.12.2012
Да, приложение должно быть консольным. На счет функций, тоже был бы рад, не откажусь от любой помощи!
414
15 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Как отлавливать клики мышью.
Структура с координатами курсора после клика.
Как создать таймер.
Функция получения размера буффера консоли.
Структура в которой будет размер буффера в строках и столбцах.
Функция печатает символ в определённой позиции.
Функция меняет фон символа в определённой позиции.
Все ссылки на английском, но ничего не помешает переключиться на машинный перевод или нагуглить те же описания функций, но написанные нашими комрадами. Этих ссылок хватит, чтобы ты сам полностью написал программу.
85K
16 декабря 2012 года
BuSh83
11 / / 13.12.2012
Спасибо за помощь!
85K
22 декабря 2012 года
BuSh83
11 / / 13.12.2012
Появился еще вопрос: как разумным методом вычислить клик в радиусе от нужной координаты?
Для примера: клик по определенной координате(О) вызывает некоторое событие, а мне нужно чтобы по клике в окрестностях координаты(Х) клик вызывал другое событие, (N) - ничего не вызывать:
N N N N N
N X X X N
N Х О Х N
N X X X N
N N N N N
414
22 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Никак. То есть, ты можешь получить координаты клика, но анализировать в окрестностях точки он или в самой точке придётся самому. Это можно проверить простым условием:
Цитата:

Проверка(клик):
если (клик.х == точка.х) и (клик.y == точка.у)
тогда ПопаданиеВТочку()
иначе если (клик.х >= точка.х - 1) и (клик.х <= точка.х + 1) и (клик.y >= точка.y - 1) и (клик.y <= точка.y +1)
тогда ПопаданиеВОкрестность()


Ну и 1 нужно менять на желаемую величину в зависимости от того, какой большой может быть окрестность.

85K
22 декабря 2012 года
BuSh83
11 / / 13.12.2012
На assemblere такой неплохой код получается из этого простого условия! Думал, может попроще можно придумать как-нибудь, ну ладно, спасибо за помощь! =)
414
22 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Цитата:

Проверка(клик):
если клик.х - точка.х + клик.y - точка.у == 0
тогда ПопаданиеВТочку()
иначе если Модуль(точка.х - клик.х) <=1 и Модуль(точка.y - клик.y) <=1
тогда ПопаданиеВОкрестность()


Чуть поменьше возьни с условиями.

414
22 декабря 2012 года
CassandraDied
763 / / 24.05.2012
А если ещё поменьше условий сделать, то так:
Цитата:

Проверка(клик):
если клик.х - точка.х + клик.y - точка.у == 0
тогда ПопаданиеВТочку()
иначе если (1 - Модуль(точка.х - клик.х) xor 1 - Модуль(точка.y - клик.y)) < 0
тогда ПопаданиеВОкрестность()


Но этот вариант нужно протестить. Не уверен, что побитовый xor бит знака учитывает.

85K
22 декабря 2012 года
BuSh83
11 / / 13.12.2012
А как модуль организовать на асемблере?
414
22 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Какой модуль?
85K
23 декабря 2012 года
BuSh83
11 / / 13.12.2012
Модуль числа я имел ввиду, но уже не нужно, я разобрался!=)
414
23 декабря 2012 года
CassandraDied
763 / / 24.05.2012
Кажется, в обычных инструкциях нет такой команды, но она есть для математического сопроцессора, мнемоника - FABS.
Вообще, стоит пробежаться по первой главе книги Ассемблер и дизассемблирование Пирогова. Там почти полный набор инструкций. Хоть будешь знать, что вообще можно сделать.
85K
23 декабря 2012 года
BuSh83
11 / / 13.12.2012
Хорошо, почитаю! Спасибо!)
7
25 декабря 2012 года
@pixo $oft
3.4K / / 20.09.2006
Проверяешь крайний левый бит. Если 1, то читаешь, как хранятся отрицательные числа в двоичном формате и понимаешь, как обратить знак. Если 0, то оно уже положительное
85K
26 декабря 2012 года
BuSh83
11 / / 13.12.2012
Я понял это уже, спасибо!
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог