;Инструкции процессора 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
Помогите с кодом на Assemblere (Игра "Поймай точку")
В начале игры пользователь вводит своё имя, которое появляется в заголовке, а также уровень сложности (1–10).
В окне консоли в случайной позиции появляется точка (например, символ «О») и через некоторое время исчезает. Задача игрока – успеть щелкнуть мышью по точке. В зависимости от степени попадания окрашивать точку (или её окрестность) в один из цветов – красный – «не попали», желтый – «попали в некоторую окрестность точки», зеленый – «полное попадание».
Предусмотреть:
– подсчет очков
– постепенное уменьшение времени отображения точки (начальный интервал выбирать в зависимости от введенного в начале игры уровня сложности)
– игра продолжается до тех пор, пока не было совершено 10 попаданий или 10 промахов.
В конце выводить сообщение о выигрыше или проигрыше.
В окне консоли в случайной позиции появляется точка (например, символ «О») и через некоторое время исчезает. Задача игрока – успеть щелкнуть мышью по точке. В зависимости от степени попадания окрашивать точку (или её окрестность) в один из цветов – красный – «не попали», желтый – «попали в некоторую окрестность точки», зеленый – «полное попадание».
Предусмотреть:
– подсчет очков
– постепенное уменьшение времени отображения точки (начальный интервал выбирать в зависимости от введенного в начале игры уровня сложности)
– игра продолжается до тех пор, пока не было совершено 10 попаданий или 10 промахов.
В конце выводить сообщение о выигрыше или проигрыше.
Вот на что меня хватило (лишь начальные наработки), потому как несколько месяцев практики явно не хватает для нормальной работы!:
Код:
Лучше напиши на что тебя не хватило. По коду сложно определить не вчитываясь что ты уже написал.
- Создается консоль.
- Запрашивается имя.
- Запрашивается уровень сложности(даже не знаю корректно или нет)
- Создается другая консоль(удаляя предыдущую, чтобы затереть введенные данные), в названии консоли отображается имя.
- Затем действие останавливается(ожидание события, если удерживать любую клавишу нажатой, или водить мышкой, то через равные промежутки времени в квадрате от 2 до 18, появляются "O"). По нажатию ESC консоль закрывается.
Поржал.
Помогу тебе попозже, если не найдёшь готового решения к этому времени.
Цитата: CassandraDied
=) Я профан полный в данном языке, другого не придумал ничего)
Ну, пока у меня нет времени заняться этим самому, могу подсказать какие функции посмотреть, чтобы ты сам что-то делал в этом время. А приложение должно быть обязательно консольное?
Да, приложение должно быть консольным. На счет функций, тоже был бы рад, не откажусь от любой помощи!
Как отлавливать клики мышью.
Структура с координатами курсора после клика.
Как создать таймер.
Функция получения размера буффера консоли.
Структура в которой будет размер буффера в строках и столбцах.
Функция печатает символ в определённой позиции.
Функция меняет фон символа в определённой позиции.
Все ссылки на английском, но ничего не помешает переключиться на машинный перевод или нагуглить те же описания функций, но написанные нашими комрадами. Этих ссылок хватит, чтобы ты сам полностью написал программу.
Структура с координатами курсора после клика.
Как создать таймер.
Функция получения размера буффера консоли.
Структура в которой будет размер буффера в строках и столбцах.
Функция печатает символ в определённой позиции.
Функция меняет фон символа в определённой позиции.
Все ссылки на английском, но ничего не помешает переключиться на машинный перевод или нагуглить те же описания функций, но написанные нашими комрадами. Этих ссылок хватит, чтобы ты сам полностью написал программу.
Спасибо за помощь!
Для примера: клик по определенной координате(О) вызывает некоторое событие, а мне нужно чтобы по клике в окрестностях координаты(Х) клик вызывал другое событие, (N) - ничего не вызывать:
N N N N N
N X X X N
N Х О Х N
N X X X N
N N N N N
Проверка(клик):
если (клик.х == точка.х) и (клик.y == точка.у)
тогда ПопаданиеВТочку()
иначе если (клик.х >= точка.х - 1) и (клик.х <= точка.х + 1) и (клик.y >= точка.y - 1) и (клик.y <= точка.y +1)
тогда ПопаданиеВОкрестность()
Ну и 1 нужно менять на желаемую величину в зависимости от того, какой большой может быть окрестность.
На assemblere такой неплохой код получается из этого простого условия! Думал, может попроще можно придумать как-нибудь, ну ладно, спасибо за помощь! =)
Проверка(клик):
если клик.х - точка.х + клик.y - точка.у == 0
тогда ПопаданиеВТочку()
иначе если Модуль(точка.х - клик.х) <=1 и Модуль(точка.y - клик.y) <=1
тогда ПопаданиеВОкрестность()
Чуть поменьше возьни с условиями.
Проверка(клик):
если клик.х - точка.х + клик.y - точка.у == 0
тогда ПопаданиеВТочку()
иначе если (1 - Модуль(точка.х - клик.х) xor 1 - Модуль(точка.y - клик.y)) < 0
тогда ПопаданиеВОкрестность()
Но этот вариант нужно протестить. Не уверен, что побитовый xor бит знака учитывает.
А как модуль организовать на асемблере?
Какой модуль?
Модуль числа я имел ввиду, но уже не нужно, я разобрался!=)
Вообще, стоит пробежаться по первой главе книги Ассемблер и дизассемблирование Пирогова. Там почти полный набор инструкций. Хоть будешь знать, что вообще можно сделать.
Хорошо, почитаю! Спасибо!)
Проверяешь крайний левый бит. Если 1, то читаешь, как хранятся отрицательные числа в двоичном формате и понимаешь, как обратить знак. Если 0, то оно уже положительное
Я понял это уже, спасибо!