Dantes3000 |
Отправлено: 02 Февраля, 2019 - 03:02:24
|


Эксперт

Покинул форум
Сообщений всего: 1490
Дата рег-ции: Июнь 2016
Репутация: 58

|
Игра крестики-нолики (Отобразить)CODE:external(INT, "CreateWindow", "CreateWindowExA", "User32.dll" );
external(INT, "SetWindowTextA", "SetWindowTextA", "User32.dll" );
createdialog(0);
showdialog(0, "Диалог",100, 100, 180, 250, 1, 1);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
int b[9]; //кнопки
int move=0; //счетчик хода
string m[9]={"-","-","-","-","-","-","-","-","-"}; //текст кнопок
b[0]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 10, 50, 50, formatwi(w), 0, 0, 0);
b[1]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 10, 50, 50, formatwi(w), 0, 0, 0);
b[2]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 10, 50, 50, formatwi(w), 0, 0, 0);
b[3]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 60, 50, 50, formatwi(w), 0, 0, 0);
b[4]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 60, 50, 50, formatwi(w), 0, 0, 0);
b[5]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 60, 50, 50, formatwi(w), 0, 0, 0);
b[6]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 110, 50, 50, formatwi(w), 0, 0, 0);
b[7]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 110, 50, 50, formatwi(w), 0, 0, 0);
b[8]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 110, 50, 50, formatwi(w), 0, 0, 0);
pc_move();
loop()
{
sleep(10);
rename("Ход №"+format(move));
}
function check_win()
{
for(int i = 0; i < 3; i++) //Для победы нужны 3 клеточки
{
if (m[i*3] == m[i*3+1] && m[i*3+1] == m[i*3+2]) return m[i];//Комбинации для победы вычисляются по формулам
if (m[i] == m[i+3] && m[i+3] == m[i+6]) return m[i];//Вертикальная
if ((m[2] == m[4] && m[4] == m[6]) || (m[0] == m[4] && m[4] == m[8])) return m[i];//наискось
}
return '-'; //Иначе - ничья
}
function result()
{
if(check_win()=='O') {messagebox("Вы выиграли"); goto global st;}
if(check_win()=='X') {messagebox("Вы проиграли"); goto global st;}
if(move>8 && check_win()=='-') {messagebox("Ничья"); goto global st;}
}
function pc_move()
{
int r;
loop()
{
r=rand(0, 9);
if(m[r]=="-") break;
}
move++;
m[r]="X";
SetWindowTextA(b[r], "X");
result();
}
function getmessage(0, WM_COMMAND)
{
for(int k=0; k<9; k++)
{
if(message.lparam==b[k])
{
if(m[k]=="X" || m[k]=="O") break;
m[k]="O";
while(getkeystate(1)) sleep(10);
move++;
SetWindowTextA(b[k], "O");
//pause(500); //можно поставить
result();
pc_move();
}
}
}
st:;
Иногда багает, если играть несколько раз подряд.
Можно сломать, если тыкать быстро ко клеткам.
Чтобы исправить - надо ловить нажатие по клеткам чуть иначе.(Отредактировано автором: 02 Февраля, 2019 - 03:05:56) |
|
|
Kibor |
Отправлено: 02 Февраля, 2019 - 04:22:35
|


Эксперт

Покинул форум
Сообщений всего: 8268
Дата рег-ции: Март 2013
Откуда: Одесса
Репутация: 357

|
Немного поправил.
Пояснения почему "ломается":
Функции GetMessage вызываются при любом сообщение.
Программа не блокирует их прием даже если не завершилось выполнение кода который был в работе от предыдущего сообщения. То есть если мы кликнули по кнопке и пошел выполняться код, то второй клик по кнопке быстрый прервет выполнение кода и начнет сначала. Это для того что бы не было пропущенных сообщений и скрипт отрабатывал разные сообщения быстро.
Пояснение. Есть код:
CODE:function getmessage(0, WM_COMMAND)
{
//Тут код
//Еще код есть
//Еще строка + message.lparam
//Если (это == то то) return;
//Еще код идет
}
К примеру вызвалась функция.
Код дошел до
//Еще код есть
и опять нажали на кнопку..
Эта функция опять вызовется прервавшись.
Как бороться:
CODE:int f=0;
function getmessage(0, WM_COMMAND)
{
if (f==1) return;//Если мы уже выполняем код в функции
f=1;//Запрещаем ходить пока не закончим этот код
//Тут код
//Еще код есть
//Еще строка + message.lparam
//Если (это == то то) {f=0; return;}//Снимаем запрет
//Еще код идет
f=0;//Снимаем запрет
}
Теперь выполнение кода не прервется пока не будет выполнен ход этой функции, но другие сообщения будут ловиться. Вернее прервется посмотреть что там пришло, но не начнет код сначала, а сразу продолжит откуда прервался.
Но еще есть проблема
Если во время выполнения этого кода будет какое то сообщение, то даже при блокировке с помощью переменной f будет перезаписан параметр message.lparam, с которым работает этот код.
Решение:
CODE:int f=0;
int p;
function getmessage(0, WM_COMMAND)
{
if (f==1) return;//Если мы уже выполняем код в функции
f=1;//Запрещаем ходить пока не закончим этот код
p=message.lparam;
//Тут код
//Еще код есть
//Еще строка + p
//Если (это == то то) {f=0; return;}//Снимаем запрет
//Еще код идет
f=0;//Снимаем запрет
}
Мы при получение сообщения и начале работы кода сразу сохраняем значение message.lparam в p
и теперь работаем с ней. И нам не важно что message.lparam может измениться.
Так же поправил пару неточностей:
Было:
CODE:if (m[i*3] == m[i*3+1] && m[i*3+1] == m[i*3+2]) return m[i];//Возвращало m[i], который относится к другой линии
Так же добавил нужные проверки.
Стало:
CODE:if (m[i*3]!= "-" && m[i*3] == m[i*3+1] && m[i*3+1] == m[i*3+2]) return m[i*3];//Комбинации для победы вычисляются по формулам
CODE:external(INT, "CreateWindow", "CreateWindowExA", "User32.dll" );
external(INT, "SetWindowTextA", "SetWindowTextA", "User32.dll" );
createdialog(0);
showdialog(0, "Диалог",100, 100, 180, 250, 1, 1);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
int b[9]; //кнопки
int move=0; //счетчик хода
string m[9]={"-","-","-","-","-","-","-","-","-"}; //текст кнопок
b[0]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 10, 50, 50, formatwi(w), 0, 0, 0);
b[1]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 10, 50, 50, formatwi(w), 0, 0, 0);
b[2]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 10, 50, 50, formatwi(w), 0, 0, 0);
b[3]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 60, 50, 50, formatwi(w), 0, 0, 0);
b[4]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 60, 50, 50, formatwi(w), 0, 0, 0);
b[5]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 60, 50, 50, formatwi(w), 0, 0, 0);
b[6]=CreateWindow(0, "BUTTON", "-", 1342177280, 10, 110, 50, 50, formatwi(w), 0, 0, 0);
b[7]=CreateWindow(0, "BUTTON", "-", 1342177280, 60, 110, 50, 50, formatwi(w), 0, 0, 0);
b[8]=CreateWindow(0, "BUTTON", "-", 1342177280, 110, 110, 50, 50, formatwi(w), 0, 0, 0);
int f=1;//флаг для блокировки что бы не отрабатывала функция пока не закончится работа
//запишется в p message.lparam если клик разрешен.так как при любом сообщение lparam перезапишется
//даже если f=1. Что бы не ломалась логика будет работать с сохраненным значением p
int p=0;
pc_move();
f=0;//Разрешили клик
loop()
{
sleep(10);
rename("Ход №"+format(move));
}
function check_win()
{
for(int i = 0; i < 3; i++) //Для победы нужны 3 клеточки
{
if (m[i*3]!= "-" && m[i*3] == m[i*3+1] && m[i*3+1] == m[i*3+2]) return m[i*3];//Комбинации для победы вычисляются по формулам
if (m[i]!= "-" && m[i] == m[i+3] && m[i+3] == m[i+6]) return m[i];//Вертикальная
if ((m[2]!= "-" && m[2] == m[4] && m[4] == m[6]) || (m[0]!= "-" && m[0] == m[4] && m[4] == m[8])) return m[2];//наискось
}
return '-'; //Иначе - ничья
}
function result()
{
if(check_win()=='O') {messagebox("Вы выиграли"); goto global st;}
if(check_win()=='X') {messagebox("Вы проиграли"); goto global st;}
if(move>8 && check_win()=='-') {messagebox("Ничья"); goto global st;}
}
function pc_move()
{
int r;
loop()
{
r=rand(0, 9);
if(m[r]=="-") break;
}
move++;
m[r]="X";
SetWindowTextA(b[r], "X");
result();
}
function getmessage(0, WM_COMMAND)
{
if (f==1) return;//Если комп не сделал ход выходим
f=1;//Запрещаем ходить пока комп не ответит
p=message.lparam;
for(int k=0; k<9; k++)
{
if(p==b[k])
{
if(m[k]=="X" || m[k]=="O") break;
m[k]="O";
while(getkeystate(1)) sleep(10);
move++;
SetWindowTextA(b[k], "O");
//pause(500);
result();
pc_move();
}
}
f=0;//Разрешаем ход
}
st:;
Потом сделаю возможность делать блокирующие функции и не блокирующие. |
|
|
Kibor |
Отправлено: 02 Февраля, 2019 - 13:59:06
|


Эксперт

Покинул форум
Сообщений всего: 8268
Дата рег-ции: Март 2013
Откуда: Одесса
Репутация: 357

|
Да какая там отдача) Я его делал из за сильного интереса. Да и это была моя вторая программа после крестиков ноликов) Ну и еще пару подобных.
Я пользуюсь) Вот себе квартиру свою делал и смотрел перепланировку и ремонт)
Создание таймера на winapi
CODE:external(INT, "SetTimer", "SetTimer", "User32.dll" );
createdialog(0);
//////////
showdialog(0, "Диалог", 558, 234, 250, 300, 1, 1);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
//////////
SetTimer(formatwi(w), 1, 1000, 0);
loop()
{
beep(500, 100);
looptime(300)sleep(10);
}
function getmessage(0, WM_TIMER)
{
beep(2500, 100);
} |
|
|
Zireael |
Отправлено: 02 Февраля, 2019 - 19:05:32
|


Эксперт

Покинул форум
Сообщений всего: 4552
Дата рег-ции: Нояб. 2017
Репутация: 590

|
Пример как вывести изображение на диалог и кнопку (Отобразить)CODE:#define BM_SETIMAGE 247
#define STM_SETIMAGE 370
external(INT, "CreateWindow", "CreateWindowExA", "User32.dll" );
external(INT, "LoadImage", "LoadImageA", "User32.dll" );
int image1=LoadImage(0, "C:\Button1.bmp", 0, 100, 34, 16); // загрузка картинки кнопки 100*34
int image2=LoadImage(0, "C:\Button2.bmp", 0, 100, 50, 16); // загрузка картинки кнопки 100*50
int fon=LoadImage(0, "C:\Fon.bmp", 0, 300, 300, 16); // загрузка картинки фона, вместо статика
createdialog(0);
showdialog(0, "Диалог",100, 100, 300, 300, 1, 0);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
int static=CreateWindow(0, "STATIC", "", 128+14+1342177280, 0, 0, 300, 300, formatwi(w), 0, 0, 0); // создать статик, фон
int button1=CreateWindow(0, "BUTTON", "", 8+128+1342177280, 20, 10, 100, 34, formatwi(w), 0, 0, 0); // создать кнопку
int button2=CreateWindow(0, "BUTTON", "", 8+128+1342177280, 20, 60, 100, 50, formatwi(w), 0, 0, 0); // создать кнопку
sendmessage(STM_SETIMAGE, 0, fon, formatiw(static)); // установить фон
sendmessage(BM_SETIMAGE, 0, image1, formatiw(button1)); // установить изображение кнопки
sendmessage(BM_SETIMAGE, 0, image2, formatiw(button2)); // установить изображение кнопки
loop()sleep(1);
function getmessage(0, WM_COMMAND)
{
if(message.lparam==button1)messagebox("Нажата кнопка Кнопка");
if(message.lparam==button2)messagebox("Нажата кнопка Текст");
}
Вот так это выглядит:
Нажмите для увеличения

Картинки (https://drive.google.com/open?id...1b57mjyRENipDRXp) закинуть на диск C:\ или сделать свои. |
|
|
Zireael |
Отправлено: 02 Февраля, 2019 - 23:13:22
|


Эксперт

Покинул форум
Сообщений всего: 4552
Дата рег-ции: Нояб. 2017
Репутация: 590

|
Пример как добавить список (Отобразить)CODE:#define LB_ADDSTRING 384
#define LB_GETSELCOUNT 400
#define LB_GETSELITEMS 401
external(INT, "CreateWindow", "CreateWindowExA", "User32.dll" );
createdialog(0);
showdialog(0, "Диалог",100, 100, 300, 300, 1, 1);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
int list=CreateWindow(0, "LISTBOX", "", 1+2048+8388608+2097152+1342177280, 10, 10, 100, 100, formatwi(w), 0, 0, 0);
char c[255];
strcpy(#c[0], "qwerty");
sendmessage(LB_ADDSTRING, 0, address(#c[0]), formatiw(list)); // добавить строку в список
strcpy(#c[0], "asdf");
sendmessage(LB_ADDSTRING, 0, address(#c[0]), formatiw(list)); // добавить строку в список
strcpy(#c[0], "zxcv");
sendmessage(LB_ADDSTRING, 0, address(#c[0]), formatiw(list));
strcpy(#c[0], "123");
sendmessage(LB_ADDSTRING, 0, address(#c[0]), formatiw(list));
strcpy(#c[0], "456");
sendmessage(LB_ADDSTRING, 0, address(#c[0]), formatiw(list));
int list_arr[5]; // массив для получения выбранных строк
int count=0; // количество выбранных строк
string s;
loop()
{
textbkcolor(255, 65280);
textout(0, 150, 250, "Всего выбрано строк: "+format(count), 0);
sendmessage(LB_GETSELITEMS, sizearray(list_arr), address(#list_arr[0]), formatiw(list)); // получить массив с выбранными строками
s="Номера выбранных строк: ";
for(int i=0; i<count && i<sizearray(list_arr); i++)s=s+format(list_arr[i])+" ";
textout(1, 150, 270, s, 0);
sleep(10);
}
function getmessage(0, WM_COMMAND)
{
if(message.lparam==list)count=sendmessage(LB_GETSELCOUNT, 0, 0, formatiw(list)); // количество выбранных строк
resettextout(1);
}
Если строки в список не поместятся, то будет добавлена вертикальная полоса прокрутки.
Выбирать можно несколько строк с нажатыми Shift или Ctrl. |
|
|
Dantes3000 |
Отправлено: 03 Февраля, 2019 - 00:50:07
|


Эксперт

Покинул форум
Сообщений всего: 1490
Дата рег-ции: Июнь 2016
Репутация: 58

|
Это я туплю или так нельзя?
CODE:external(INT, "CreateWindow", "CreateWindowExA", "User32.dll" );
createdialog(0);
showdialog(0, "Диалог",100, 100, 300, 300, 1, 1);
while(window ("Диалог")==0)sleep(10);
win w=window ("Диалог");
int nums_text[15];
int xk=5;
int yk=5;
for(int k=0; k>4; k++)
{
nums_text[k]=CreateWindow(0, "BUTTON", "s "+format(k), 1342177280, xk, yk, 50, 50, formatwi(w), 0, 0, 0);
xk=xk+50;
}
loop()sleep(1); |
|
|
|